diff --git a/lib/node.js b/lib/node.js index dda05cc2f60..e906b1a4bef 100644 --- a/lib/node.js +++ b/lib/node.js @@ -371,15 +371,49 @@ declare module "cluster" { declare module.exports: Cluster; } -type crypto$createCredentialsDetails = any; // TODO +// deprecated +type crypto$createCredentialsDetails = { + pfx: string, + key: string, + passphrase: string, + cert: string, + ca: string | string[], + crl: string | string[], + ciphers: string, + ... +}; + +type crypto$PrivateKeyInput = { + key: string | Buffer, + format?: crypto$KeyFormat, + type?: 'pkcs1' | 'pkcs8' | 'sec1', + passphrase?: string | Buffer, + ... +}; + +type crypto$PublicKeyInput = { + key: string | Buffer, + format?: crypto$KeyFormat, + type?: 'pkcs1' | 'spki', + ... +}; + +type crypto$SignPrivateKeyInput = crypto$PrivateKeyInput & { + padding?: + | typeof crypto$constants.RSA_PKCS1_PADDING + | typeof crypto$constants.RSA_PKCS1_PSS_PADDING, + saltLength?: number, + ... +}; declare class crypto$Cipher extends stream$Duplex { final(output_encoding: 'latin1' | 'binary' | 'base64' | 'hex'): string; final(output_encoding: void): Buffer; getAuthTag(): Buffer; - setAAD(buffer: Buffer): crypto$Cipher; + setAAD(buffer: Buffer, options?: { plaintextLength: number }): crypto$Cipher; setAuthTag(buffer: Buffer): void; setAutoPadding(auto_padding?: boolean): crypto$Cipher; + update(data: string | Buffer | $TypedArray | DataView): Buffer; update( data: string, input_encoding: 'utf8' | 'ascii' | 'latin1' | 'binary', @@ -395,73 +429,91 @@ declare class crypto$Cipher extends stream$Duplex { input_encoding: void | 'utf8' | 'ascii' | 'latin1' | 'binary', output_encoding: 'latin1' | 'binary' | 'base64' | 'hex' ): string; - update( - data: Buffer, - input_encoding: void, - output_encoding: void - ): Buffer; + update(data: Buffer, input_encoding: void, output_encoding: void): Buffer; } +// deprecated type crypto$Credentials = { - // TODO -} + context?: any, + ... +}; type crypto$DiffieHellman = { - computeSecret( - other_public_key: string, - input_encoding?: string, - output_encoding?: string - ): any; - generateKeys(encoding?: string): any; - getGenerator(encoding?: string): any; - getPrime(encoding?: string): any; - getPrivateKey(encoding?: string): any; - getPublicKey(encoding?: string): any; - setPrivateKey(private_key: any, encoding?: string): void; - setPublicKey(public_key: any, encoding?: string): void; -} + computeSecret(other_public_key: Buffer | $TypedArray | DataView): Buffer; + computeSecret(other_public_key: string, input_encoding: string): Buffer; + computeSecret(other_public_key: Buffer | $TypedArray | DataView, output_encoding: string): string; + computeSecret(other_public_key: string, input_encoding: string, output_encoding: string): string; + generateKeys(): Buffer, + generateKeys(encoding: string): string, + getGenerator(): Buffer, + getGenerator(encoding: string): string, + getPrime(): Buffer, + getPrime(encoding: string): string, + getPrivateKey(): Buffer, + getPrivateKey(encoding: string): string, + getPublicKey(): Buffer, + getPublicKey(encoding: string): string, + setPublicKey(public_key: Buffer | $TypedArray | DataView): void, + setPublicKey(public_key: string, encoding: string): void, + setPrivateKey(private_key: Buffer | $TypedArray | DataView): void, + setPrivateKey(private_key: string, encoding: string): void, + verifyError: number, + ... +}; type crypto$ECDH$Encoding = 'latin1' | 'hex' | 'base64'; -type crypto$ECDH$Format = 'compressed' | 'uncompressed'; +type crypto$ECDH$Format = 'compressed' | 'uncompressed' | 'hybrid'; declare class crypto$ECDH { - computeSecret( - other_public_key: Buffer | $TypedArray | DataView - ): Buffer, + static convertKey( + key: string | Buffer | $TypedArray | DataView, + curve: string, + inputEncoding?: crypto$ECDH$Encoding, + outputEncoding?: crypto$ECDH$Encoding, + format?: crypto$ECDH$Format + ): Buffer | string; + computeSecret(other_public_key: Buffer | $TypedArray | DataView): Buffer; computeSecret( other_public_key: string, input_encoding: crypto$ECDH$Encoding - ): Buffer, + ): Buffer; computeSecret( other_public_key: Buffer | $TypedArray | DataView, output_encoding: crypto$ECDH$Encoding - ): string, + ): string; computeSecret( other_public_key: string, input_encoding: crypto$ECDH$Encoding, output_encoding: crypto$ECDH$Encoding - ): string, - generateKeys(format?: crypto$ECDH$Format): Buffer, - generateKeys(encoding: crypto$ECDH$Encoding, format?: crypto$ECDH$Format): string, - getPrivateKey(): Buffer, - getPrivateKey(encoding: crypto$ECDH$Encoding): string, - getPublicKey(format?: crypto$ECDH$Format): Buffer, - getPublicKey(encoding: crypto$ECDH$Encoding, format?: crypto$ECDH$Format): string, - setPrivateKey(private_key: Buffer | $TypedArray | DataView): void, - setPrivateKey(private_key: string, encoding: crypto$ECDH$Encoding): void + ): string; + generateKeys(format?: crypto$ECDH$Format): Buffer; + generateKeys( + encoding: crypto$ECDH$Encoding, + format?: crypto$ECDH$Format + ): string; + getPrivateKey(): Buffer; + getPrivateKey(encoding: crypto$ECDH$Encoding): string; + getPublicKey(format?: crypto$ECDH$Format): Buffer; + getPublicKey( + encoding: crypto$ECDH$Encoding, + format?: crypto$ECDH$Format + ): string; + setPrivateKey(private_key: Buffer | $TypedArray | DataView): void; + setPrivateKey(private_key: string, encoding: crypto$ECDH$Encoding): void; } declare class crypto$Decipher extends stream$Duplex { final(output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8'): string; final(output_encoding: void): Buffer; getAuthTag(): Buffer; - setAAD(buffer: Buffer): void; + setAAD(buffer: Buffer, options?: { plaintextLength: number }): void; setAuthTag(buffer: Buffer): void; setAutoPadding(auto_padding?: boolean): crypto$Cipher; + update(data: string | Buffer | $TypedArray | DataView): Buffer; update( data: string, input_encoding: 'latin1' | 'binary' | 'base64' | 'hex', - output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8', + output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8' ): string; update( data: string, @@ -471,132 +523,448 @@ declare class crypto$Decipher extends stream$Duplex { update( data: Buffer, input_encoding: void, - output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8', + output_encoding: 'latin1' | 'binary' | 'ascii' | 'utf8' ): string; - update( - data: Buffer, - input_encoding: void, - output_encoding: void - ): Buffer; + update(data: Buffer, input_encoding: void, output_encoding: void): Buffer; } declare class crypto$Hash extends stream$Duplex { digest(encoding: 'hex' | 'latin1' | 'binary' | 'base64'): string; digest(encoding: 'buffer'): Buffer; digest(encoding: void): Buffer; - update(data: string | Buffer, input_encoding?: 'utf8' | 'ascii' | 'latin1' | - 'binary'): crypto$Hash; + update( + data: string | Buffer | $TypedArray | DataView, + input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary' + ): crypto$Hash; } declare class crypto$Hmac extends stream$Duplex { digest(encoding: 'hex' | 'latin1' | 'binary' | 'base64'): string; digest(encoding: 'buffer'): Buffer; digest(encoding: void): Buffer; - update(data: string | Buffer, input_encoding?: 'utf8' | 'ascii' | 'latin1' | - 'binary'): crypto$Hmac; + update( + data: string | Buffer | $TypedArray | DataView, + input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary' + ): crypto$Hmac; } -type crypto$Sign$private_key = string | { - key: string, - passphrase: string, -} declare class crypto$Sign extends stream$Writable { - static(algorithm: string, options?: writableStreamOptions): crypto$Sign, + static (algorithm: string, options?: writableStreamOptions): crypto$Sign; constructor(algorithm: string, options?: writableStreamOptions): void; sign( - private_key: crypto$Sign$private_key, + private_key: + | crypto$SignPrivateKeyInput + | string + | Buffer + | crypto$KeyObject, output_format: 'latin1' | 'binary' | 'hex' | 'base64' ): string; sign( - private_key: crypto$Sign$private_key, + private_key: + | crypto$SignPrivateKeyInput + | string + | Buffer + | crypto$KeyObject, output_format: void ): Buffer; - update(data: string | Buffer, input_encoding?: 'utf8' | 'ascii' | 'latin1' | - 'binary'): crypto$Sign; + update( + data: string | Buffer | $TypedArray | DataView, + input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary' + ): crypto$Sign; } +type crypto$Verify$object = crypto$PublicKeyInput & { + padding?: + | typeof crypto$constants.RSA_PKCS1_PADDING + | typeof crypto$constants.RSA_PKCS1_PSS_PADDING, + saltLength?: number, + ... +}; + declare class crypto$Verify extends stream$Writable { - static(algorithm: string, options?: writableStreamOptions): crypto$Verify, + static (algorithm: string, options?: writableStreamOptions): crypto$Verify; constructor(algorithm: string, options?: writableStreamOptions): void; - update(data: string | Buffer, input_encoding?: 'utf8' | 'ascii' | 'latin1' | - 'binary' ): crypto$Verify; + update( + data: string | Buffer | $TypedArray | DataView, + input_encoding?: 'utf8' | 'ascii' | 'latin1' | 'binary' + ): crypto$Verify; + verify( + object: crypto$Verify$object | string | Buffer | crypto$KeyObject, + signature: Buffer | $TypedArray | DataView, + signature_format: void + ): boolean; verify( - object: string, - signature: string | Buffer | $TypedArray | DataView, + object: crypto$Verify$object | string | Buffer | crypto$KeyObject, + signature: string, signature_format: 'latin1' | 'binary' | 'hex' | 'base64' ): boolean; - verify(object: string, signature: Buffer, signature_format: void): boolean; } +type crypto$RsaPublicKey = { + key: string | Buffer, + padding?: + | typeof crypto$constants.RSA_NO_PADDING + | typeof crypto$constants.RSA_PKCS1_PADDING + | typeof crypto$constants.RSA_PKCS1_OAEP_PADDING,, + ... +}; + +type crypto$RsaPrivateKey = { + key: string | Buffer, + passphrase?: string | Buffer, + padding?: + | typeof crypto$constants.RSA_NO_PADDING + | typeof crypto$constants.RSA_PKCS1_PADDING + | typeof crypto$constants.RSA_PKCS1_OAEP_PADDING, + ... +}; + +type crypto$KeyType = 'rsa' | 'dsa' | 'ec'; +type crypto$KeyFormat = 'pem' | 'der'; -type crypto$key = string | { - key: string, - passphrase?: string, - padding?: string // TODO: enum type in crypto.constants +type crypto$BasePrivateKeyEncodingOptions = { + format: T, + cipher: string, + passphrase: string, + ... +}; + +type crypto$KeyExportOptions = { + type: 'pkcs1' | 'spki' | 'pkcs8' | 'sec1', + format: T, + cipher?: string, + passphrase?: string | Buffer, + ... +}; + +type crypto$KeyPairKeyObjectResult = { + publicKey: crypto$KeyObject, + privateKey: crypto$KeyObject, + ... +} + +type crypto$ECKeyPairKeyObjectOptions = { + /** + * Name of the curve to use. + */ + namedCurve: string, + ... +} + +type crypto$RSAKeyPairKeyObjectOptions = { + /** + * Key size in bits + */ + modulusLength: number, + + /** + * @default 0x10001 + */ + publicExponent?: number, + ... +} + +type crypto$DSAKeyPairKeyObjectOptions = { + /** + * Key size in bits + */ + modulusLength: number, + + /** + * Size of q in bits + */ + divisorLength: number, + ... +} + +type crypto$RSAKeyPairOptions< + PubF: crypto$KeyFormat, + PrivF: crypto$KeyFormat +> = { + /** + * Key size in bits + */ + modulusLength: number, + /** + * @default 0x10001 + */ + publicExponent?: number, + + publicKeyEncoding: { + type: 'pkcs1' | 'spki', + format: PubF, + ... + }, + privateKeyEncoding: crypto$BasePrivateKeyEncodingOptions & { + type: 'pkcs1' | 'pkcs8', + ... + }, + ... +}; + +type crypto$DSAKeyPairOptions< + PubF: crypto$KeyFormat, + PrivF: crypto$KeyFormat +> = { + /** + * Key size in bits + */ + modulusLength: number, + /** + * Size of q in bits + */ + divisorLength: number, + + publicKeyEncoding: { + type: 'spki', + format: PubF, + ... + }, + privateKeyEncoding: crypto$BasePrivateKeyEncodingOptions & { + type: 'pkcs8', + ... + }, + ... }; -declare module "crypto" { +type crypto$ECKeyPairOptions = { + /** + * Name of the curve to use. + */ + namedCurve: string, + + publicKeyEncoding: { + type: 'pkcs1' | 'spki', + format: PubF, + ... + }, + privateKeyEncoding: crypto$BasePrivateKeyEncodingOptions & { + type: 'sec1' | 'pkcs8' + ... + }, + ... +}; + +type crypto$KeyPairSyncResult = { + publicKey: T1, + privateKey: T2, + ... +} + +declare class crypto$KeyObject { + asymmetricKeyType?: crypto$KeyType; + export(options: crypto$KeyExportOptions<'pem'>): string | Buffer; + export(options?: crypto$KeyExportOptions<'der'>): Buffer; + symmetricSize?: number; + type: 'secret' | 'public' | 'private'; +} + +type crypto$ScryptOptions = { + N?: number, + r?: number, + p?: number, + maxmem?: number, + ... +}; + +declare var crypto$constants: {| + OPENSSL_VERSION_NUMBER: number, + + /** Applies multiple bug workarounds within OpenSSL. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html for detail. */ + SSL_OP_ALL: number, + /** Allows legacy insecure renegotiation between OpenSSL and unpatched clients or servers. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html. */ + SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: number, + /** Attempts to use the server's preferences instead of the client's when selecting a cipher. See https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html. */ + SSL_OP_CIPHER_SERVER_PREFERENCE: number, + /** Instructs OpenSSL to use Cisco's "speshul" version of DTLS_BAD_VER. */ + SSL_OP_CISCO_ANYCONNECT: number, + /** Instructs OpenSSL to turn on cookie exchange. */ + SSL_OP_COOKIE_EXCHANGE: number, + /** Instructs OpenSSL to add server-hello extension from an early version of the cryptopro draft. */ + SSL_OP_CRYPTOPRO_TLSEXT_BUG: number, + /** Instructs OpenSSL to disable a SSL 3.0/TLS 1.0 vulnerability workaround added in OpenSSL 0.9.6d. */ + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: number, + /** Instructs OpenSSL to always use the tmp_rsa key when performing RSA operations. */ + SSL_OP_EPHEMERAL_RSA: number, + /** Allows initial connection to servers that do not support RI. */ + SSL_OP_LEGACY_SERVER_CONNECT: number, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: number, + SSL_OP_MICROSOFT_SESS_ID_BUG: number, + /** Instructs OpenSSL to disable the workaround for a man-in-the-middle protocol-version vulnerability in the SSL 2.0 server implementation. */ + SSL_OP_MSIE_SSLV2_RSA_PADDING: number, + SSL_OP_NETSCAPE_CA_DN_BUG: number, + SSL_OP_NETSCAPE_CHALLENGE_BUG: number, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: number, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: number, + /** Instructs OpenSSL to disable support for SSL/TLS compression. */ + SSL_OP_NO_COMPRESSION: number, + SSL_OP_NO_QUERY_MTU: number, + /** Instructs OpenSSL to always start a new session when performing renegotiation. */ + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: number, + SSL_OP_NO_SSLv2: number, + SSL_OP_NO_SSLv3: number, + SSL_OP_NO_TICKET: number, + SSL_OP_NO_TLSv1: number, + SSL_OP_NO_TLSv1_1: number, + SSL_OP_NO_TLSv1_2: number, + SSL_OP_PKCS1_CHECK_1: number, + SSL_OP_PKCS1_CHECK_2: number, + /** Instructs OpenSSL to always create a new key when using temporary/ephemeral DH parameters. */ + SSL_OP_SINGLE_DH_USE: number, + /** Instructs OpenSSL to always create a new key when using temporary/ephemeral ECDH parameters. */ + SSL_OP_SINGLE_ECDH_USE: number, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG: number, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: number, + SSL_OP_TLS_BLOCK_PADDING_BUG: number, + SSL_OP_TLS_D5_BUG: number, + /** Instructs OpenSSL to disable version rollback attack detection. */ + SSL_OP_TLS_ROLLBACK_BUG: number, + + ENGINE_METHOD_RSA: number, + ENGINE_METHOD_DSA: number, + ENGINE_METHOD_DH: number, + ENGINE_METHOD_RAND: number, + ENGINE_METHOD_EC: number, + ENGINE_METHOD_CIPHERS: number, + ENGINE_METHOD_DIGESTS: number, + ENGINE_METHOD_PKEY_METHS: number, + ENGINE_METHOD_PKEY_ASN1_METHS: number, + ENGINE_METHOD_ALL: number, + ENGINE_METHOD_NONE: number, + + DH_CHECK_P_NOT_SAFE_PRIME: number, + DH_CHECK_P_NOT_PRIME: number, + DH_UNABLE_TO_CHECK_GENERATOR: number, + DH_NOT_SUITABLE_GENERATOR: number, + + ALPN_ENABLED: number, + + RSA_PKCS1_PADDING: 1, + RSA_SSLV23_PADDING: number, + RSA_NO_PADDING: 3, + RSA_PKCS1_OAEP_PADDING: 4, + RSA_X931_PADDING: number, + RSA_PKCS1_PSS_PADDING: 6, + /** Sets the salt length for RSA_PKCS1_PSS_PADDING to the digest size when signing or verifying. */ + RSA_PSS_SALTLEN_DIGEST: number, + /** Sets the salt length for RSA_PKCS1_PSS_PADDING to the maximum permissible value when signing data. */ + RSA_PSS_SALTLEN_MAX_SIGN: number, + /** Causes the salt length for RSA_PKCS1_PSS_PADDING to be determined automatically when verifying a signature. */ + RSA_PSS_SALTLEN_AUTO: number, + + POINT_CONVERSION_COMPRESSED: number, + POINT_CONVERSION_UNCOMPRESSED: number, + POINT_CONVERSION_HYBRID: number, + + /** Specifies the built-in default cipher list used by Node.js (colon-separated values). */ + defaultCoreCipherList: string, + /** Specifies the active default cipher list used by the current Node.js process (colon-separated values). */ + defaultCipherList: string +|}; + +declare module 'crypto' { + // deprecated declare var DEFAULT_ENCODING: string; - declare class Sign extends crypto$Sign {} - declare class Verify extends crypto$Verify {} + declare var Sign: Class; + declare var Verify: Class; + declare var ECDH: Class; + + declare var Certificate: { + exportChallenge(spkac: string | Buffer | $TypedArray | DataView): Buffer; + exportPublicKey(spkac: string | Buffer | $TypedArray | DataView, encoding?: string): Buffer; + verifySpkac(spkac: Buffer | $TypedArray | DataView): boolean; + }; + + declare var constants: typeof crypto$constants; + + // deprecated + declare function createCipher( + algorithm: string, + password: string | Buffer | $TypedArray | DataView, + options?: transformStreamOptions + ): crypto$Cipher; - declare function createCipher(algorithm: string, password: string | Buffer): crypto$Cipher; declare function createCipheriv( algorithm: string, - key: string | Buffer, - iv: string | Buffer + key: string | Buffer | $TypedArray | DataView | crypto$KeyObject, + iv: string | Buffer | $TypedArray | DataView, + options?: transformStreamOptions ): crypto$Cipher; + + // deprecated declare function createCredentials( details?: crypto$createCredentialsDetails - ): crypto$Credentials - declare function createDecipher(algorithm: string, password: string | Buffer): crypto$Decipher; + ): crypto$Credentials; + + declare function createDecipher( + algorithm: string, + password: string | Buffer | $TypedArray | DataView + ): crypto$Decipher; declare function createDecipheriv( algorithm: string, - key: string | Buffer, - iv: string | Buffer + key: string | Buffer | $TypedArray | DataView, + iv: string | Buffer | $TypedArray | DataView, + options?: transformStreamOptions ): crypto$Decipher; - declare function createDiffieHellman(prime_length: number): crypto$DiffieHellman; - declare function createDiffieHellman(prime: number, encoding?: string): crypto$DiffieHellman; + declare function createDiffieHellman( + prime_length: number + ): crypto$DiffieHellman; + declare function createDiffieHellman( + prime: number, + encoding?: string + ): crypto$DiffieHellman; declare function createECDH(curveName: string): crypto$ECDH; declare function createHash(algorithm: string): crypto$Hash; - declare function createHmac(algorithm: string, key: string | Buffer): crypto$Hmac; + declare function createHmac( + algorithm: string, + key: string | Buffer | $TypedArray | DataView | crypto$KeyObject, + options?: transformStreamOptions + ): crypto$Hmac; + declare function createPrivateKey( + key: crypto$PrivateKeyInput | string | Buffer + ): crypto$KeyObject; + declare function createPublicKey( + key: crypto$PublicKeyInput | string | Buffer | crypto$KeyObject + ): crypto$KeyObject; + declare function createSecretKey(key: Buffer): crypto$KeyObject; declare function createSign(algorithm: string): crypto$Sign; declare function createVerify(algorithm: string): crypto$Verify; declare function getCiphers(): Array; declare function getCurves(): Array; declare function getDiffieHellman(group_name: string): crypto$DiffieHellman; + declare function getFips(): boolean; declare function getHashes(): Array; declare function pbkdf2( - password: string | Buffer, - salt: string | Buffer, + password: string | Buffer | $TypedArray | DataView, + salt: string | Buffer | $TypedArray | DataView, iterations: number, keylen: number, digestOrCallback: string | ((err: ?Error, derivedKey: Buffer) => void), callback?: (err: ?Error, derivedKey: Buffer) => void ): void; declare function pbkdf2Sync( - password: string | Buffer, - salt: string | Buffer, + password: string | Buffer | $TypedArray | DataView, + salt: string | Buffer | $TypedArray | DataView, iterations: number, keylen: number, digest?: string ): Buffer; declare function privateDecrypt( - private_key: crypto$key, - buffer: Buffer + private_key: crypto$RsaPrivateKey | string | Buffer | crypto$KeyObject, + buffer: Buffer | $TypedArray | DataView ): Buffer; declare function privateEncrypt( - private_key: crypto$key, - buffer: Buffer + private_key: crypto$RsaPrivateKey | string | Buffer | crypto$KeyObject, + buffer: Buffer | $TypedArray | DataView ): Buffer; declare function publicDecrypt( - key: crypto$key, - buffer: Buffer + key: crypto$RsaPublicKey | string | Buffer | crypto$KeyObject, + buffer: Buffer | $TypedArray | DataView ): Buffer; declare function publicEncrypt( - key: crypto$key, - buffer: Buffer + key: crypto$RsaPublicKey | string | Buffer | crypto$KeyObject, + buffer: Buffer | $TypedArray | DataView ): Buffer; // `UNUSED` argument strictly enforces arity to enable overloading this // function with 1-arg and 2-arg variants. @@ -612,32 +980,211 @@ declare module "crypto" { size: number, callback: (err: ?Error, buffer: Buffer) => void ): void; - declare function randomFillSync(buffer: Buffer): void - declare function randomFillSync(buffer: Buffer, offset: number): void - declare function randomFillSync( - buffer: Buffer, + declare function randomFillSync( + buffer: T + ): void; + declare function randomFillSync( + buffer: T, + offset: number + ): void; + declare function randomFillSync( + buffer: T, offset: number, size: number - ): void - declare function randomFill( - buffer: Buffer, - callback: (err: ?Error, buffer: Buffer) => void - ): void - declare function randomFill( - buffer: Buffer, + ): void; + declare function randomFill( + buffer: T, + callback: (err: ?Error, buffer: T) => void + ): void; + declare function randomFill( + buffer: T, offset: number, - callback: (err: ?Error, buffer: Buffer) => void - ): void - declare function randomFill( - buffer: Buffer, + callback: (err: ?Error, buffer: T) => void + ): void; + declare function randomFill( + buffer: T, offset: number, size: number, - callback: (err: ?Error, buffer: Buffer) => void - ): void + callback: (err: ?Error, buffer: T) => void + ): void; declare function timingSafeEqual( a: Buffer | $TypedArray | DataView, b: Buffer | $TypedArray | DataView ): boolean; + declare function scrypt( + password: string | Buffer | $TypedArray | DataView, + salt: string | Buffer | $TypedArray | DataView, + keylen: number, + callback: (err: ?Error, derivedKey: Buffer) => void + ): void; + declare function scrypt( + password: string | Buffer | $TypedArray | DataView, + salt: string | Buffer | $TypedArray | DataView, + keylen: number, + options: crypto$ScryptOptions, + callback: (err: ?Error, derivedKey: Buffer) => void + ): void; + declare function scryptSync( + password: string | Buffer | $TypedArray | DataView, + salt: string | Buffer | $TypedArray | DataView, + keylen: number, + options?: crypto$ScryptOptions + ): Buffer; + + declare function generateKeyPairSync( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'pem', 'pem'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'pem', 'der'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'der', 'pem'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'der', 'der'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'rsa', + options: crypto$RSAKeyPairKeyObjectOptions + ): crypto$KeyPairKeyObjectResult; + + declare function generateKeyPairSync( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'pem', 'pem'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'pem', 'der'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'der', 'pem'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'der', 'der'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'dsa', + options: crypto$DSAKeyPairKeyObjectOptions + ): crypto$KeyPairKeyObjectResult; + + declare function generateKeyPairSync( + type: 'ec', + options: crypto$ECKeyPairOptions<'pem', 'pem'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'ec', + options: crypto$ECKeyPairOptions<'pem', 'der'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'ec', + options: crypto$ECKeyPairOptions<'der', 'pem'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'ec', + options: crypto$ECKeyPairOptions<'der', 'der'> + ): crypto$KeyPairSyncResult; + declare function generateKeyPairSync( + type: 'ec', + options: crypto$ECKeyPairKeyObjectOptions + ): crypto$KeyPairKeyObjectResult; + + declare function generateKeyPair( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'pem', 'pem'>, + callback: (err: ?Error, publicKey: string, privateKey: string) => void + ): void; + declare function generateKeyPair( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'pem', 'der'>, + callback: (err: ?Error, publicKey: string, privateKey: Buffer) => void + ): void; + declare function generateKeyPair( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'der', 'pem'>, + callback: (err: ?Error, publicKey: Buffer, privateKey: string) => void + ): void; + declare function generateKeyPair( + type: 'rsa', + options: crypto$RSAKeyPairOptions<'der', 'der'>, + callback: (err: ?Error, publicKey: Buffer, privateKey: Buffer) => void + ): void; + declare function generateKeyPair( + type: 'rsa', + options: crypto$RSAKeyPairKeyObjectOptions, + callback: ( + err: ?Error, + publicKey: crypto$KeyObject, + privateKey: crypto$KeyObject + ) => void + ): void; + + declare function generateKeyPair( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'pem', 'pem'>, + callback: (err: ?Error, publicKey: string, privateKey: string) => void + ): void; + declare function generateKeyPair( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'pem', 'der'>, + callback: (err: ?Error, publicKey: string, privateKey: Buffer) => void + ): void; + declare function generateKeyPair( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'der', 'pem'>, + callback: (err: ?Error, publicKey: Buffer, privateKey: string) => void + ): void; + declare function generateKeyPair( + type: 'dsa', + options: crypto$DSAKeyPairOptions<'der', 'der'>, + callback: (err: ?Error, publicKey: Buffer, privateKey: Buffer) => void + ): void; + declare function generateKeyPair( + type: 'dsa', + options: crypto$DSAKeyPairKeyObjectOptions, + callback: ( + err: ?Error, + publicKey: crypto$KeyObject, + privateKey: crypto$KeyObject + ) => void + ): void; + + declare function generateKeyPair( + type: 'ec', + options: crypto$ECKeyPairOptions<'pem', 'pem'>, + callback: (err: ?Error, publicKey: string, privateKey: string) => void + ): void; + declare function generateKeyPair( + type: 'ec', + options: crypto$ECKeyPairOptions<'pem', 'der'>, + callback: (err: ?Error, publicKey: string, privateKey: Buffer) => void + ): void; + declare function generateKeyPair( + type: 'ec', + options: crypto$ECKeyPairOptions<'der', 'pem'>, + callback: (err: ?Error, publicKey: Buffer, privateKey: string) => void + ): void; + declare function generateKeyPair( + type: 'ec', + options: crypto$ECKeyPairOptions<'der', 'der'>, + callback: (err: ?Error, publicKey: Buffer, privateKey: Buffer) => void + ): void; + declare function generateKeyPair( + type: 'ec', + options: crypto$ECKeyPairKeyObjectOptions, + callback: ( + err: ?Error, + publicKey: crypto$KeyObject, + privateKey: crypto$KeyObject + ) => void + ): void; + declare function setEngine(engine: string, flags?: number): void; + declare function setFips(fips: boolean): void; } type net$Socket$address = {address: string; family: string; port: number}; diff --git a/tests/node_tests/crypto/crypto.js b/tests/node_tests/crypto/crypto.js index 9d294d96bfa..fd2bb00326d 100644 --- a/tests/node_tests/crypto/crypto.js +++ b/tests/node_tests/crypto/crypto.js @@ -1,39 +1,723 @@ -/* @flow */ - -const crypto = require('crypto'); - -let tests = [ - // Hmac is a duplex stream - function() { - const hmac = crypto.createHmac('sha256', 'a secret'); - - hmac.on('readable', () => { - (hmac.read(): ?(string | Buffer)); - (hmac.read(): number); // 4 errors: null, void, string, Buffer - }); - - hmac.write('some data to hash'); - hmac.write(123); // 2 errors: not a string or a Buffer - hmac.end(); - }, - - // Hmac supports update and digest functions too - function(buf: Buffer) { - const hmac = crypto.createHmac('sha256', 'a secret'); - - hmac.update('some data to hash'); - hmac.update('foo', 'utf8'); - hmac.update('foo', 'bogus'); // 1 error - hmac.update(buf); - hmac.update(buf, 'utf8'); - hmac.update(buf, 'bogus'); // 1 error - - // it's also chainable - (hmac.update('some data to hash').update(buf).digest(): Buffer); - - (hmac.digest('hex'): string); - (hmac.digest(): Buffer); - (hmac.digest('hex'): void); // 1 error - (hmac.digest(): void); // 1 error - } -] +//@flow + +import * as crypto from "crypto"; +import assert from "assert"; +import { promisify } from "util"; + +{ + // crypto_hash_string_test + const hashResult: string = crypto + .createHash("md5") + .update("world") + .digest("hex"); +} + +{ + // crypto_hash_buffer_test + const hashResult: string = crypto + .createHash("md5") + .update(Buffer.from("world")) + .digest("hex"); +} + +{ + // crypto_hash_dataview_test + const hashResult: string = crypto + .createHash("md5") + .update(new DataView(Buffer.from("world").buffer)) + .digest("hex"); +} + +{ + // crypto_hash_int8array_test + const hashResult: string = crypto + .createHash("md5") + .update(new Int8Array(Buffer.from("world").buffer)) + .digest("hex"); +} + +{ + // crypto_hmac_string_test + const hmacResult: string = crypto + .createHmac("md5", "hello") + .update("world") + .digest("hex"); +} + +{ + // crypto_hmac_buffer_test + const hmacResult: string = crypto + .createHmac("md5", "hello") + .update(Buffer.from("world")) + .digest("hex"); +} + +{ + // crypto_hmac_dataview_test + const hmacResult: string = crypto + .createHmac("md5", "hello") + .update(new DataView(Buffer.from("world").buffer)) + .digest("hex"); +} + +{ + // crypto_hmac_int8array_test + const hmacResult: string = crypto + .createHmac("md5", "hello") + .update(new Int8Array(Buffer.from("world").buffer)) + .digest("hex"); +} + +{ + let hmac: crypto$Hmac; + (hmac = crypto.createHmac("md5", "hello")).end("world", "utf8", () => { + const hash: Buffer | string | null | void = hmac.read(); + }); +} + +{ + // crypto_cipher_decipher_string_test + const key: Buffer = Buffer.from([ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ]); + const clearText = "This is the clear text."; + const cipher: crypto$Cipher = crypto.createCipher("aes-128-ecb", key); + let cipherText: string = cipher.update(clearText, "utf8", "hex"); + cipherText += cipher.final("hex"); + + const decipher: crypto$Decipher = crypto.createDecipher("aes-128-ecb", key); + let clearText2: string = decipher.update(cipherText, "hex", "utf8"); + clearText2 += decipher.final("utf8"); + + assert.equal(clearText2, clearText); +} + +{ + // crypto_cipher_decipher_buffer_test + const key: Buffer = Buffer.from([ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ]); + const clearText: Buffer = Buffer.from([ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 8, + 7, + 6, + 5, + 4 + ]); + const cipher: crypto$Cipher = crypto.createCipher("aes-128-ecb", key); + const cipherBuffers: Buffer[] = []; + cipherBuffers.push(cipher.update(clearText)); + cipherBuffers.push(cipher.final()); + + const cipherText: Buffer = Buffer.concat(cipherBuffers); + + const decipher: crypto$Decipher = crypto.createDecipher("aes-128-ecb", key); + const decipherBuffers: Buffer[] = []; + decipherBuffers.push(decipher.update(cipherText)); + decipherBuffers.push(decipher.final()); + + const clearText2: Buffer = Buffer.concat(decipherBuffers); + + assert.deepEqual(clearText2, clearText); +} + +{ + // crypto_cipher_decipher_dataview_test + const key: Buffer = Buffer.from([ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ]); + const clearText: DataView = new DataView( + Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4]).buffer + ); + const cipher: crypto$Cipher = crypto.createCipher("aes-128-ecb", key); + const cipherBuffers: Buffer[] = []; + cipherBuffers.push(cipher.update(clearText)); + cipherBuffers.push(cipher.final()); + + const cipherText: DataView = new DataView( + Buffer.concat(cipherBuffers).buffer + ); + + const decipher: crypto$Decipher = crypto.createDecipher("aes-128-ecb", key); + const decipherBuffers: Buffer[] = []; + decipherBuffers.push(decipher.update(cipherText)); + decipherBuffers.push(decipher.final()); + + const clearText2: Buffer = Buffer.concat(decipherBuffers); + + assert.deepEqual(clearText2, clearText); +} + +{ + const key: string | null = "keykeykeykeykeykeykeykey"; + const nonce = crypto.randomBytes(12); + const aad = Buffer.from("0123456789", "hex"); + + const cipher = crypto.createCipheriv("aes-192-ccm", key, nonce, { + authTagLength: 16 + }); + const plaintext = "Hello world"; + cipher.setAAD(aad, { + plaintextLength: Buffer.byteLength(plaintext) + }); + const ciphertext = cipher.update(plaintext, "utf8"); + cipher.final(); + const tag = cipher.getAuthTag(); + + const decipher = crypto.createDecipheriv("aes-192-ccm", key, nonce, { + authTagLength: 16 + }); + decipher.setAuthTag(tag); + decipher.setAAD(aad, { + plaintextLength: ciphertext.length + }); + const receivedPlaintext: string = decipher.update( + ciphertext, + undefined, + "utf8" + ); + decipher.final(); +} + +{ + const key = "keykeykeykeykeykeykeykey"; + const nonce = crypto.randomBytes(12); + const aad = Buffer.from("0123456789", "hex"); + + const cipher = crypto.createCipheriv("aes-192-gcm", key, nonce); + const plaintext = "Hello world"; + cipher.setAAD(aad, { + plaintextLength: Buffer.byteLength(plaintext) + }); + const ciphertext = cipher.update(plaintext, "utf8"); + cipher.final(); + const tag = cipher.getAuthTag(); + + const decipher = crypto.createDecipheriv("aes-192-gcm", key, nonce); + decipher.setAuthTag(tag); + decipher.setAAD(aad, { + plaintextLength: ciphertext.length + }); + const receivedPlaintext: string = decipher.update( + ciphertext, + undefined, + "utf8" + ); + decipher.final(); +} + +{ + // crypto_timingsafeequal_buffer_test + const buffer1: Buffer = Buffer.from([1, 2, 3, 4, 5]); + const buffer2: Buffer = Buffer.from([1, 2, 3, 4, 5]); + const buffer3: Buffer = Buffer.from([5, 4, 3, 2, 1]); + + assert(crypto.timingSafeEqual(buffer1, buffer2)); + assert(!crypto.timingSafeEqual(buffer1, buffer3)); +} + +{ + // crypto_timingsafeequal_uint32array_test + const arr1: Uint32Array = Uint32Array.of(1, 2, 3, 4, 5); + const arr2: Uint32Array = Uint32Array.of(1, 2, 3, 4, 5); + const arr3: Uint32Array = Uint32Array.of(5, 4, 3, 2, 1); + + assert(crypto.timingSafeEqual(arr1, arr2)); + assert(!crypto.timingSafeEqual(arr1, arr3)); +} + +{ + // crypto_timingsafeequal_safe_typedarray_variant_test + const arr1: Uint32Array = Uint32Array.of(1, 2, 3, 4, 5); + const arr2: Int32Array = Int32Array.of(1, 2, 3, 4, 5); + const arr3: Uint32Array = Uint32Array.of(5, 4, 3, 2, 1); + + assert(crypto.timingSafeEqual(arr1, arr2)); + assert(!crypto.timingSafeEqual(arr1, arr3)); +} + +{ + // crypto_timingsafeequal_safe_int8array_variant_test + const arr1: Int8Array = Int8Array.of(1, 2, 3, 4, 5, ~0, ~1, ~2, ~3, ~4); + const arr2: Uint8Array = Uint8Array.of(1, 2, 3, 4, 5, ~0, ~1, ~2, ~3, ~4); + const arr3: Uint8ClampedArray = Uint8ClampedArray.of( + 1, + 2, + 3, + 4, + 5, + ~0, + ~1, + ~2, + ~3, + ~4 + ); + + assert(crypto.timingSafeEqual(arr1, arr2)); // binary same + assert(!crypto.timingSafeEqual(arr1, arr3)); // binary differ +} + +{ + // crypto_timingsafeequal_dataview_test + const dv1B: Uint8Array = Uint8Array.of(1, 2, 3, 4, 5); + const dv2B: Int8Array = Int8Array.of(1, 2, 3, 4, 5); + const dv3B: Buffer = Buffer.of(5, 4, 3, 2, 1); + const dv4B: Uint8ClampedArray = Uint8ClampedArray.of(5, 4, 3, 2, 1); + const dv1: DataView = new DataView( + dv1B.buffer, + dv1B.byteOffset, + dv1B.byteLength + ); + const dv2: DataView = new DataView( + dv2B.buffer, + dv2B.byteOffset, + dv2B.byteLength + ); + const dv3: DataView = new DataView( + dv3B.buffer, + dv3B.byteOffset, + dv3B.byteLength + ); + const dv4: DataView = new DataView( + dv4B.buffer, + dv4B.byteOffset, + dv4B.byteLength + ); + + assert(crypto.timingSafeEqual(dv1, dv2)); + assert(crypto.timingSafeEqual(dv1, dv1B)); + assert(crypto.timingSafeEqual(dv2, dv1B)); + assert(crypto.timingSafeEqual(dv3, dv4)); + + assert(!crypto.timingSafeEqual(dv1, dv3)); + assert(!crypto.timingSafeEqual(dv2, dv3)); + assert(!crypto.timingSafeEqual(dv1, dv4)); + // ... I'm not going to write all those tests. +} + +{ + // crypto_timingsafeequal_uint32array_test + const ui32_1: Uint32Array = Uint32Array.of(1, 2, 3, 4, 5); + const ui32_2: Uint32Array = Uint32Array.of(1, 2, 3, 4, 5); + const ui32_3: Uint32Array = Uint32Array.of(5, 4, 3, 2, 1); + + assert(crypto.timingSafeEqual(ui32_1, ui32_2)); + assert(!crypto.timingSafeEqual(ui32_1, ui32_3)); +} + +{ + // crypto_randomfill_buffer_test + const buffer: Buffer = Buffer.from(10); + crypto.randomFillSync(buffer); + crypto.randomFillSync(buffer, 2); + crypto.randomFillSync(buffer, 2, 3); + + crypto.randomFill(buffer, (err: ?Error, buf: Buffer) => void {}); + crypto.randomFill(buffer, 2, (err: ?Error, buf: Buffer) => void {}); + crypto.randomFill(buffer, 2, 3, (err: ?Error, buf: Buffer) => void {}); + + // crypto_randomfill_uint8array_test + const ui8arr: Uint8Array = new Uint8Array(10); + crypto.randomFillSync(ui8arr); + crypto.randomFillSync(ui8arr, 2); + crypto.randomFillSync(ui8arr, 2, 3); + + crypto.randomFill(ui8arr, (err: ?Error, buf: Uint8Array) => void {}); + crypto.randomFill(ui8arr, 2, (err: ?Error, buf: Uint8Array) => void {}); + crypto.randomFill(ui8arr, 2, 3, (err: ?Error, buf: Uint8Array) => void {}); + + // crypto_randomfill_int32array_test + const i32arr: Int32Array = new Int32Array(10); + crypto.randomFillSync(i32arr); + crypto.randomFillSync(i32arr, 2); + crypto.randomFillSync(i32arr, 2, 3); + + crypto.randomFill(i32arr, (err: ?Error, buf: Int32Array) => void {}); + crypto.randomFill(i32arr, 2, (err: ?Error, buf: Int32Array) => void {}); + crypto.randomFill(i32arr, 2, 3, (err: ?Error, buf: Int32Array) => void {}); +} + +{ + // scrypt + const pwd: string | Buffer | Int32Array | DataView = Buffer.alloc(16); + const salt: string | Buffer | Int32Array | DataView = Buffer.alloc(16); + crypto.scrypt(pwd, salt, 64, (err: ?Error, derivedKey: Buffer): void => {}); + const opts: crypto$ScryptOptions = { + N: 16384, + r: 8, + p: 1, + maxmem: 32 * 1024 * 1024 + }; + crypto.scrypt( + pwd, + salt, + 64, + opts, + (err: ?Error, derivedKey: Buffer): void => {} + ); + crypto.scrypt( + pwd, + salt, + 64, + { maxmem: 16 * 1024 * 1024 }, + (err: ?Error, derivedKey: Buffer): void => {} + ); + let buf: Buffer = crypto.scryptSync(pwd, salt, 64); + buf = crypto.scryptSync(pwd, salt, 64, opts); + buf = crypto.scryptSync(pwd, salt, 64, { N: 1024 }); +} + +{ + let key: string | Buffer = Buffer.from("buf"); + const curve = "secp256k1"; + let ret: string | Buffer = crypto.ECDH.convertKey(key, curve); + key = "0xfff"; + ret = crypto.ECDH.convertKey(key, curve); + ret = crypto.ECDH.convertKey(key, curve, "hex"); + ret = crypto.ECDH.convertKey(key, curve, "hex", "hex"); + ret = crypto.ECDH.convertKey(key, curve, "hex", "hex", "uncompressed"); + ret = crypto.ECDH.convertKey(key, curve, "hex", "hex", "compressed"); + ret = crypto.ECDH.convertKey(key, curve, "hex", "hex", "hybrid"); +} + +{ + const rsaRes: { + publicKey: Buffer, + privateKey: string + } = crypto.generateKeyPairSync("rsa", { + modulusLength: 123, + publicKeyEncoding: { + format: "der", + type: "pkcs1" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "pem", + passphrase: "secret", + type: "pkcs8" + } + }); + + const dsaRes: { + publicKey: string, + privateKey: Buffer + } = crypto.generateKeyPairSync("dsa", { + modulusLength: 123, + divisorLength: 123, + publicKeyEncoding: { + format: "pem", + type: "spki" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "der", + passphrase: "secret", + type: "pkcs8" + } + }); + + const ecRes: { + publicKey: string, + privateKey: string + } = crypto.generateKeyPairSync("ec", { + namedCurve: "curve", + publicKeyEncoding: { + format: "pem", + type: "pkcs1" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "pem", + passphrase: "secret", + type: "pkcs8" + } + }); +} + +{ + crypto.generateKeyPair( + "rsa", + { + modulusLength: 123, + publicKeyEncoding: { + format: "der", + type: "pkcs1" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "pem", + passphrase: "secret", + type: "pkcs8" + } + }, + (err: ?ErrnoError, publicKey: Buffer, privateKey: string) => {} + ); + + crypto.generateKeyPair( + "dsa", + { + modulusLength: 123, + divisorLength: 123, + publicKeyEncoding: { + format: "pem", + type: "spki" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "der", + passphrase: "secret", + type: "pkcs8" + } + }, + (err: ?ErrnoError, publicKey: string, privateKey: Buffer) => {} + ); + + crypto.generateKeyPair( + "ec", + { + namedCurve: "curve", + publicKeyEncoding: { + format: "pem", + type: "pkcs1" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "pem", + passphrase: "secret", + type: "pkcs8" + } + }, + (err: ?ErrnoError, publicKey: string, privateKey: string) => {} + ); +} + +{ + const generateKeyPairPromisified = promisify(crypto.generateKeyPair); + + const rsaRes: Promise<{ + publicKey: Buffer, + privateKey: string + }> = generateKeyPairPromisified("rsa", { + modulusLength: 123, + publicKeyEncoding: { + format: "der", + type: "pkcs1" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "pem", + passphrase: "secret", + type: "pkcs8" + } + }); + + const dsaRes: Promise<{ + publicKey: string, + privateKey: Buffer + }> = generateKeyPairPromisified("dsa", { + modulusLength: 123, + divisorLength: 123, + publicKeyEncoding: { + format: "pem", + type: "spki" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "der", + passphrase: "secret", + type: "pkcs8" + } + }); + + const ecRes: Promise<{ + publicKey: string, + privateKey: string + }> = generateKeyPairPromisified("ec", { + namedCurve: "curve", + publicKeyEncoding: { + format: "pem", + type: "pkcs1" + }, + privateKeyEncoding: { + cipher: "some-cipher", + format: "pem", + passphrase: "secret", + type: "pkcs8" + } + }); +} + +{ + crypto.createPrivateKey(Buffer.from("asdf")); + crypto.createPrivateKey({ + key: "asd", + format: "der" + }); +} + +{ + crypto.createSecretKey(Buffer.from("asdf")); +} + +{ + const { privateKey, publicKey } = crypto.generateKeyPairSync("ec", { + namedCurve: "sect239k1" + }); + + const sign: crypto.Sign = crypto.createSign("SHA256"); + sign.write("some data to sign"); + sign.end(); + const signature: string = sign.sign(privateKey, "hex"); + + const verify: crypto.Verify = crypto.createVerify("SHA256"); + verify.write("some data to sign"); + verify.end(); + verify.verify(publicKey, signature); // $ExpectType boolean + + // ensure that instanceof works + verify instanceof crypto.Verify; + sign instanceof crypto.Sign; +} + +{ + const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", { + modulusLength: 2048 + }); + + const sign: crypto.Sign = crypto.createSign("SHA256"); + sign.update("some data to sign"); + sign.end(); + const signature: Buffer = sign.sign(privateKey); + + const verify: crypto.Verify = crypto.createVerify("SHA256"); + verify.update("some data to sign"); + verify.end(); + verify.verify(publicKey, signature); // $ExpectType boolean +} + +{ + // crypto_constants_test + let num: number; + let str: string; + + num = crypto.constants.OPENSSL_VERSION_NUMBER; + num = crypto.constants.SSL_OP_ALL; + num = crypto.constants.SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + num = crypto.constants.SSL_OP_CIPHER_SERVER_PREFERENCE; + num = crypto.constants.SSL_OP_CISCO_ANYCONNECT; + num = crypto.constants.SSL_OP_COOKIE_EXCHANGE; + num = crypto.constants.SSL_OP_CRYPTOPRO_TLSEXT_BUG; + num = crypto.constants.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + num = crypto.constants.SSL_OP_EPHEMERAL_RSA; + num = crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT; + num = crypto.constants.SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; + num = crypto.constants.SSL_OP_MICROSOFT_SESS_ID_BUG; + num = crypto.constants.SSL_OP_MSIE_SSLV2_RSA_PADDING; + num = crypto.constants.SSL_OP_NETSCAPE_CA_DN_BUG; + num = crypto.constants.SSL_OP_NETSCAPE_CHALLENGE_BUG; + num = crypto.constants.SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG; + num = crypto.constants.SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; + num = crypto.constants.SSL_OP_NO_COMPRESSION; + num = crypto.constants.SSL_OP_NO_QUERY_MTU; + num = crypto.constants.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; + num = crypto.constants.SSL_OP_NO_SSLv2; + num = crypto.constants.SSL_OP_NO_SSLv3; + num = crypto.constants.SSL_OP_NO_TICKET; + num = crypto.constants.SSL_OP_NO_TLSv1; + num = crypto.constants.SSL_OP_NO_TLSv1_1; + num = crypto.constants.SSL_OP_NO_TLSv1_2; + num = crypto.constants.SSL_OP_PKCS1_CHECK_1; + num = crypto.constants.SSL_OP_PKCS1_CHECK_2; + num = crypto.constants.SSL_OP_SINGLE_DH_USE; + num = crypto.constants.SSL_OP_SINGLE_ECDH_USE; + num = crypto.constants.SSL_OP_SSLEAY_080_CLIENT_DH_BUG; + num = crypto.constants.SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; + num = crypto.constants.SSL_OP_TLS_BLOCK_PADDING_BUG; + num = crypto.constants.SSL_OP_TLS_D5_BUG; + num = crypto.constants.SSL_OP_TLS_ROLLBACK_BUG; + num = crypto.constants.ENGINE_METHOD_RSA; + num = crypto.constants.ENGINE_METHOD_DSA; + num = crypto.constants.ENGINE_METHOD_DH; + num = crypto.constants.ENGINE_METHOD_RAND; + num = crypto.constants.ENGINE_METHOD_EC; + num = crypto.constants.ENGINE_METHOD_CIPHERS; + num = crypto.constants.ENGINE_METHOD_DIGESTS; + num = crypto.constants.ENGINE_METHOD_PKEY_METHS; + num = crypto.constants.ENGINE_METHOD_PKEY_ASN1_METHS; + num = crypto.constants.ENGINE_METHOD_ALL; + num = crypto.constants.ENGINE_METHOD_NONE; + num = crypto.constants.DH_CHECK_P_NOT_SAFE_PRIME; + num = crypto.constants.DH_CHECK_P_NOT_PRIME; + num = crypto.constants.DH_UNABLE_TO_CHECK_GENERATOR; + num = crypto.constants.DH_NOT_SUITABLE_GENERATOR; + num = crypto.constants.ALPN_ENABLED; + num = crypto.constants.RSA_PKCS1_PADDING; + num = crypto.constants.RSA_SSLV23_PADDING; + num = crypto.constants.RSA_NO_PADDING; + num = crypto.constants.RSA_PKCS1_OAEP_PADDING; + num = crypto.constants.RSA_X931_PADDING; + num = crypto.constants.RSA_PKCS1_PSS_PADDING; + num = crypto.constants.RSA_PSS_SALTLEN_DIGEST; + num = crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN; + num = crypto.constants.RSA_PSS_SALTLEN_AUTO; + num = crypto.constants.POINT_CONVERSION_COMPRESSED; + num = crypto.constants.POINT_CONVERSION_UNCOMPRESSED; + num = crypto.constants.POINT_CONVERSION_HYBRID; + + str = crypto.constants.defaultCoreCipherList; + str = crypto.constants.defaultCipherList; +} diff --git a/tests/node_tests/crypto/hmac.js b/tests/node_tests/crypto/hmac.js new file mode 100644 index 00000000000..9d294d96bfa --- /dev/null +++ b/tests/node_tests/crypto/hmac.js @@ -0,0 +1,39 @@ +/* @flow */ + +const crypto = require('crypto'); + +let tests = [ + // Hmac is a duplex stream + function() { + const hmac = crypto.createHmac('sha256', 'a secret'); + + hmac.on('readable', () => { + (hmac.read(): ?(string | Buffer)); + (hmac.read(): number); // 4 errors: null, void, string, Buffer + }); + + hmac.write('some data to hash'); + hmac.write(123); // 2 errors: not a string or a Buffer + hmac.end(); + }, + + // Hmac supports update and digest functions too + function(buf: Buffer) { + const hmac = crypto.createHmac('sha256', 'a secret'); + + hmac.update('some data to hash'); + hmac.update('foo', 'utf8'); + hmac.update('foo', 'bogus'); // 1 error + hmac.update(buf); + hmac.update(buf, 'utf8'); + hmac.update(buf, 'bogus'); // 1 error + + // it's also chainable + (hmac.update('some data to hash').update(buf).digest(): Buffer); + + (hmac.digest('hex'): string); + (hmac.digest(): Buffer); + (hmac.digest('hex'): void); // 1 error + (hmac.digest(): void); // 1 error + } +]