11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  FunctionPrototypeCall,
51cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf,
61cb0ef41Sopenharmony_ci  ReflectApply,
71cb0ef41Sopenharmony_ci} = primordials;
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  codes: {
111cb0ef41Sopenharmony_ci    ERR_CRYPTO_SIGN_KEY_REQUIRED,
121cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
131cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_VALUE,
141cb0ef41Sopenharmony_ci  },
151cb0ef41Sopenharmony_ci} = require('internal/errors');
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciconst {
181cb0ef41Sopenharmony_ci  validateFunction,
191cb0ef41Sopenharmony_ci  validateEncoding,
201cb0ef41Sopenharmony_ci  validateString,
211cb0ef41Sopenharmony_ci} = require('internal/validators');
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciconst {
241cb0ef41Sopenharmony_ci  Sign: _Sign,
251cb0ef41Sopenharmony_ci  SignJob,
261cb0ef41Sopenharmony_ci  Verify: _Verify,
271cb0ef41Sopenharmony_ci  kCryptoJobAsync,
281cb0ef41Sopenharmony_ci  kCryptoJobSync,
291cb0ef41Sopenharmony_ci  kSigEncDER,
301cb0ef41Sopenharmony_ci  kSigEncP1363,
311cb0ef41Sopenharmony_ci  kSignJobModeSign,
321cb0ef41Sopenharmony_ci  kSignJobModeVerify,
331cb0ef41Sopenharmony_ci} = internalBinding('crypto');
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciconst {
361cb0ef41Sopenharmony_ci  getArrayBufferOrView,
371cb0ef41Sopenharmony_ci  getDefaultEncoding,
381cb0ef41Sopenharmony_ci  kHandle,
391cb0ef41Sopenharmony_ci} = require('internal/crypto/util');
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ciconst {
421cb0ef41Sopenharmony_ci  preparePrivateKey,
431cb0ef41Sopenharmony_ci  preparePublicOrPrivateKey,
441cb0ef41Sopenharmony_ci} = require('internal/crypto/keys');
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciconst { Writable } = require('stream');
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ciconst {
511cb0ef41Sopenharmony_ci  isArrayBufferView,
521cb0ef41Sopenharmony_ci} = require('internal/util/types');
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_cifunction Sign(algorithm, options) {
551cb0ef41Sopenharmony_ci  if (!(this instanceof Sign))
561cb0ef41Sopenharmony_ci    return new Sign(algorithm, options);
571cb0ef41Sopenharmony_ci  validateString(algorithm, 'algorithm');
581cb0ef41Sopenharmony_ci  this[kHandle] = new _Sign();
591cb0ef41Sopenharmony_ci  this[kHandle].init(algorithm);
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  ReflectApply(Writable, this, [options]);
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Sign.prototype, Writable.prototype);
651cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Sign, Writable);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ciSign.prototype._write = function _write(chunk, encoding, callback) {
681cb0ef41Sopenharmony_ci  this.update(chunk, encoding);
691cb0ef41Sopenharmony_ci  callback();
701cb0ef41Sopenharmony_ci};
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciSign.prototype.update = function update(data, encoding) {
731cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  if (typeof data === 'string') {
761cb0ef41Sopenharmony_ci    validateEncoding(data, encoding);
771cb0ef41Sopenharmony_ci  } else if (!isArrayBufferView(data)) {
781cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
791cb0ef41Sopenharmony_ci      'data', ['string', 'Buffer', 'TypedArray', 'DataView'], data);
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  this[kHandle].update(data, encoding);
831cb0ef41Sopenharmony_ci  return this;
841cb0ef41Sopenharmony_ci};
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_cifunction getPadding(options) {
871cb0ef41Sopenharmony_ci  return getIntOption('padding', options);
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_cifunction getSaltLength(options) {
911cb0ef41Sopenharmony_ci  return getIntOption('saltLength', options);
921cb0ef41Sopenharmony_ci}
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_cifunction getDSASignatureEncoding(options) {
951cb0ef41Sopenharmony_ci  if (typeof options === 'object') {
961cb0ef41Sopenharmony_ci    const { dsaEncoding = 'der' } = options;
971cb0ef41Sopenharmony_ci    if (dsaEncoding === 'der')
981cb0ef41Sopenharmony_ci      return kSigEncDER;
991cb0ef41Sopenharmony_ci    else if (dsaEncoding === 'ieee-p1363')
1001cb0ef41Sopenharmony_ci      return kSigEncP1363;
1011cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_VALUE('options.dsaEncoding', dsaEncoding);
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  return kSigEncDER;
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_cifunction getIntOption(name, options) {
1081cb0ef41Sopenharmony_ci  const value = options[name];
1091cb0ef41Sopenharmony_ci  if (value !== undefined) {
1101cb0ef41Sopenharmony_ci    if (value === value >> 0) {
1111cb0ef41Sopenharmony_ci      return value;
1121cb0ef41Sopenharmony_ci    }
1131cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_VALUE(`options.${name}`, value);
1141cb0ef41Sopenharmony_ci  }
1151cb0ef41Sopenharmony_ci  return undefined;
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ciSign.prototype.sign = function sign(options, encoding) {
1191cb0ef41Sopenharmony_ci  if (!options)
1201cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_SIGN_KEY_REQUIRED();
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  const { data, format, type, passphrase } = preparePrivateKey(options, true);
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  // Options specific to RSA
1251cb0ef41Sopenharmony_ci  const rsaPadding = getPadding(options);
1261cb0ef41Sopenharmony_ci  const pssSaltLength = getSaltLength(options);
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  // Options specific to (EC)DSA
1291cb0ef41Sopenharmony_ci  const dsaSigEnc = getDSASignatureEncoding(options);
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  const ret = this[kHandle].sign(data, format, type, passphrase, rsaPadding,
1321cb0ef41Sopenharmony_ci                                 pssSaltLength, dsaSigEnc);
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  encoding = encoding || getDefaultEncoding();
1351cb0ef41Sopenharmony_ci  if (encoding && encoding !== 'buffer')
1361cb0ef41Sopenharmony_ci    return ret.toString(encoding);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  return ret;
1391cb0ef41Sopenharmony_ci};
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_cifunction signOneShot(algorithm, data, key, callback) {
1421cb0ef41Sopenharmony_ci  if (algorithm != null)
1431cb0ef41Sopenharmony_ci    validateString(algorithm, 'algorithm');
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  if (callback !== undefined)
1461cb0ef41Sopenharmony_ci    validateFunction(callback, 'callback');
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  data = getArrayBufferOrView(data, 'data');
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  if (!key)
1511cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_SIGN_KEY_REQUIRED();
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  // Options specific to RSA
1541cb0ef41Sopenharmony_ci  const rsaPadding = getPadding(key);
1551cb0ef41Sopenharmony_ci  const pssSaltLength = getSaltLength(key);
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  // Options specific to (EC)DSA
1581cb0ef41Sopenharmony_ci  const dsaSigEnc = getDSASignatureEncoding(key);
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  const {
1611cb0ef41Sopenharmony_ci    data: keyData,
1621cb0ef41Sopenharmony_ci    format: keyFormat,
1631cb0ef41Sopenharmony_ci    type: keyType,
1641cb0ef41Sopenharmony_ci    passphrase: keyPassphrase,
1651cb0ef41Sopenharmony_ci  } = preparePrivateKey(key);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  const job = new SignJob(
1681cb0ef41Sopenharmony_ci    callback ? kCryptoJobAsync : kCryptoJobSync,
1691cb0ef41Sopenharmony_ci    kSignJobModeSign,
1701cb0ef41Sopenharmony_ci    keyData,
1711cb0ef41Sopenharmony_ci    keyFormat,
1721cb0ef41Sopenharmony_ci    keyType,
1731cb0ef41Sopenharmony_ci    keyPassphrase,
1741cb0ef41Sopenharmony_ci    data,
1751cb0ef41Sopenharmony_ci    algorithm,
1761cb0ef41Sopenharmony_ci    pssSaltLength,
1771cb0ef41Sopenharmony_ci    rsaPadding,
1781cb0ef41Sopenharmony_ci    dsaSigEnc);
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  if (!callback) {
1811cb0ef41Sopenharmony_ci    const { 0: err, 1: signature } = job.run();
1821cb0ef41Sopenharmony_ci    if (err !== undefined)
1831cb0ef41Sopenharmony_ci      throw err;
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci    return Buffer.from(signature);
1861cb0ef41Sopenharmony_ci  }
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  job.ondone = (error, signature) => {
1891cb0ef41Sopenharmony_ci    if (error) return FunctionPrototypeCall(callback, job, error);
1901cb0ef41Sopenharmony_ci    FunctionPrototypeCall(callback, job, null, Buffer.from(signature));
1911cb0ef41Sopenharmony_ci  };
1921cb0ef41Sopenharmony_ci  job.run();
1931cb0ef41Sopenharmony_ci}
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_cifunction Verify(algorithm, options) {
1961cb0ef41Sopenharmony_ci  if (!(this instanceof Verify))
1971cb0ef41Sopenharmony_ci    return new Verify(algorithm, options);
1981cb0ef41Sopenharmony_ci  validateString(algorithm, 'algorithm');
1991cb0ef41Sopenharmony_ci  this[kHandle] = new _Verify();
2001cb0ef41Sopenharmony_ci  this[kHandle].init(algorithm);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  ReflectApply(Writable, this, [options]);
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Verify.prototype, Writable.prototype);
2061cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Verify, Writable);
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ciVerify.prototype._write = Sign.prototype._write;
2091cb0ef41Sopenharmony_ciVerify.prototype.update = Sign.prototype.update;
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ciVerify.prototype.verify = function verify(options, signature, sigEncoding) {
2121cb0ef41Sopenharmony_ci  const {
2131cb0ef41Sopenharmony_ci    data,
2141cb0ef41Sopenharmony_ci    format,
2151cb0ef41Sopenharmony_ci    type,
2161cb0ef41Sopenharmony_ci    passphrase,
2171cb0ef41Sopenharmony_ci  } = preparePublicOrPrivateKey(options, true);
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  sigEncoding = sigEncoding || getDefaultEncoding();
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  // Options specific to RSA
2221cb0ef41Sopenharmony_ci  const rsaPadding = getPadding(options);
2231cb0ef41Sopenharmony_ci  const pssSaltLength = getSaltLength(options);
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  // Options specific to (EC)DSA
2261cb0ef41Sopenharmony_ci  const dsaSigEnc = getDSASignatureEncoding(options);
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  signature = getArrayBufferOrView(signature, 'signature', sigEncoding);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  return this[kHandle].verify(data, format, type, passphrase, signature,
2311cb0ef41Sopenharmony_ci                              rsaPadding, pssSaltLength, dsaSigEnc);
2321cb0ef41Sopenharmony_ci};
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_cifunction verifyOneShot(algorithm, data, key, signature, callback) {
2351cb0ef41Sopenharmony_ci  if (algorithm != null)
2361cb0ef41Sopenharmony_ci    validateString(algorithm, 'algorithm');
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  if (callback !== undefined)
2391cb0ef41Sopenharmony_ci    validateFunction(callback, 'callback');
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  data = getArrayBufferOrView(data, 'data');
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  if (!isArrayBufferView(data)) {
2441cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
2451cb0ef41Sopenharmony_ci      'data',
2461cb0ef41Sopenharmony_ci      ['Buffer', 'TypedArray', 'DataView'],
2471cb0ef41Sopenharmony_ci      data,
2481cb0ef41Sopenharmony_ci    );
2491cb0ef41Sopenharmony_ci  }
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci  // Options specific to RSA
2521cb0ef41Sopenharmony_ci  const rsaPadding = getPadding(key);
2531cb0ef41Sopenharmony_ci  const pssSaltLength = getSaltLength(key);
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  // Options specific to (EC)DSA
2561cb0ef41Sopenharmony_ci  const dsaSigEnc = getDSASignatureEncoding(key);
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  if (!isArrayBufferView(signature)) {
2591cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
2601cb0ef41Sopenharmony_ci      'signature',
2611cb0ef41Sopenharmony_ci      ['Buffer', 'TypedArray', 'DataView'],
2621cb0ef41Sopenharmony_ci      signature,
2631cb0ef41Sopenharmony_ci    );
2641cb0ef41Sopenharmony_ci  }
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_ci  const {
2671cb0ef41Sopenharmony_ci    data: keyData,
2681cb0ef41Sopenharmony_ci    format: keyFormat,
2691cb0ef41Sopenharmony_ci    type: keyType,
2701cb0ef41Sopenharmony_ci    passphrase: keyPassphrase,
2711cb0ef41Sopenharmony_ci  } = preparePublicOrPrivateKey(key);
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci  const job = new SignJob(
2741cb0ef41Sopenharmony_ci    callback ? kCryptoJobAsync : kCryptoJobSync,
2751cb0ef41Sopenharmony_ci    kSignJobModeVerify,
2761cb0ef41Sopenharmony_ci    keyData,
2771cb0ef41Sopenharmony_ci    keyFormat,
2781cb0ef41Sopenharmony_ci    keyType,
2791cb0ef41Sopenharmony_ci    keyPassphrase,
2801cb0ef41Sopenharmony_ci    data,
2811cb0ef41Sopenharmony_ci    algorithm,
2821cb0ef41Sopenharmony_ci    pssSaltLength,
2831cb0ef41Sopenharmony_ci    rsaPadding,
2841cb0ef41Sopenharmony_ci    dsaSigEnc,
2851cb0ef41Sopenharmony_ci    signature);
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  if (!callback) {
2881cb0ef41Sopenharmony_ci    const { 0: err, 1: result } = job.run();
2891cb0ef41Sopenharmony_ci    if (err !== undefined)
2901cb0ef41Sopenharmony_ci      throw err;
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci    return result;
2931cb0ef41Sopenharmony_ci  }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  job.ondone = (error, result) => {
2961cb0ef41Sopenharmony_ci    if (error) return FunctionPrototypeCall(callback, job, error);
2971cb0ef41Sopenharmony_ci    FunctionPrototypeCall(callback, job, null, result);
2981cb0ef41Sopenharmony_ci  };
2991cb0ef41Sopenharmony_ci  job.run();
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_cimodule.exports = {
3031cb0ef41Sopenharmony_ci  Sign,
3041cb0ef41Sopenharmony_ci  signOneShot,
3051cb0ef41Sopenharmony_ci  Verify,
3061cb0ef41Sopenharmony_ci  verifyOneShot,
3071cb0ef41Sopenharmony_ci};
308