From 7c61970bd3dc8e94935d71dc7570a529e400cb20 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Sat, 21 Aug 2021 00:33:13 +0900 Subject: [PATCH] src: add x509.fingerprint512 to crypto module --- doc/api/crypto.md | 9 +++++++++ doc/api/tls.md | 10 +++++++--- lib/internal/crypto/x509.js | 10 ++++++++++ src/crypto/crypto_common.cc | 4 ++++ src/crypto/crypto_x509.cc | 10 ++++++++++ src/crypto/crypto_x509.h | 1 + src/env.h | 1 + test/parallel/test-crypto-x509.js | 11 +++++++++++ test/parallel/test-tls-peer-certificate.js | 12 ++++++++++++ 9 files changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 73f5ecd9506aa7..b3fd6fcb8e6d2d 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -2475,6 +2475,15 @@ added: v15.6.0 The SHA-256 fingerprint of this certificate. +### `x509.fingerprint512` + + +* Type: {string} + +The SHA-512 fingerprint of this certificate. + ### `x509.infoAccess` A certificate object has properties corresponding to the fields of the @@ -1115,6 +1115,9 @@ certificate. * `fingerprint256` {string} The SHA-256 digest of the DER encoded certificate. It is returned as a `:` separated hexadecimal string. Example: `'2A:7A:C2:DD:...'`. +* `fingerprint512` {string} The SHA-512 digest of the DER encoded certificate. + It is returned as a `:` separated hexadecimal string. Example: + `'2A:7A:C2:DD:...'`. * `ext_key_usage` {Array} (Optional) The extended key usage, a set of OIDs. * `subjectaltname` {string} (Optional) A string containing concatenated names for the subject, an alternative to the `subject` names. @@ -1172,6 +1175,7 @@ Example certificate: valid_to: 'Nov 20 23:59:59 2019 GMT', fingerprint: '01:02:59:D9:C3:D2:0D:08:F7:82:4E:44:A4:B4:53:C5:E2:3A:87:4D', fingerprint256: '69:AE:1A:6A:D4:3D:C6:C1:1B:EA:C6:23:DE:BA:2A:14:62:62:93:5C:7A:EA:06:41:9B:0B:BC:87:CE:48:4E:02', + fingerprint512: '19:2B:3E:C3:B3:5B:32:E8:AE:BB:78:97:27:E4:BA:6C:39:C9:92:79:4F:31:46:39:E2:70:E5:5F:89:42:17:C9:E8:64:CA:FF:BB:72:56:73:6E:28:8A:92:7E:A3:2A:15:8B:C2:E0:45:CA:C3:BC:EA:40:52:EC:CA:A2:68:CB:32', ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ], serialNumber: '66593D57F20CBC573E433381B5FEC280', raw: } diff --git a/lib/internal/crypto/x509.js b/lib/internal/crypto/x509.js index ff8e6086576662..51b0d51b0deeeb 100644 --- a/lib/internal/crypto/x509.js +++ b/lib/internal/crypto/x509.js @@ -133,6 +133,7 @@ class X509Certificate extends JSTransferable { validTo: this.validTo, fingerprint: this.fingerprint, fingerprint256: this.fingerprint256, + fingerprint512: this.fingerprint512, keyUsage: this.keyUsage, serialNumber: this.serialNumber, }, opts)}`; @@ -233,6 +234,15 @@ class X509Certificate extends JSTransferable { return value; } + get fingerprint512() { + let value = this[kInternalState].get('fingerprint512'); + if (value === undefined) { + value = this[kHandle].fingerprint512(); + this[kInternalState].set('fingerprint512', value); + } + return value; + } + get keyUsage() { let value = this[kInternalState].get('keyUsage'); if (value === undefined) { diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc index f4b7bd3ad8548a..3d31b675e97631 100644 --- a/src/crypto/crypto_common.cc +++ b/src/crypto/crypto_common.cc @@ -1081,6 +1081,10 @@ MaybeLocal X509ToObject(Environment* env, X509* cert) { info, env->fingerprint256_string(), GetFingerprintDigest(env, EVP_sha256(), cert)) || + !Set(context, + info, + env->fingerprint512_string(), + GetFingerprintDigest(env, EVP_sha512(), cert)) || !Set(context, info, env->ext_key_usage_string(), diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc index 574a3a194de82f..c3d9e7af7ba6c0 100644 --- a/src/crypto/crypto_x509.cc +++ b/src/crypto/crypto_x509.cc @@ -68,6 +68,7 @@ Local X509Certificate::GetConstructorTemplate( env->SetProtoMethod(tmpl, "validFrom", ValidFrom); env->SetProtoMethod(tmpl, "fingerprint", Fingerprint); env->SetProtoMethod(tmpl, "fingerprint256", Fingerprint256); + env->SetProtoMethod(tmpl, "fingerprint512", Fingerprint512); env->SetProtoMethod(tmpl, "keyUsage", KeyUsage); env->SetProtoMethod(tmpl, "serialNumber", SerialNumber); env->SetProtoMethod(tmpl, "pem", Pem); @@ -268,6 +269,15 @@ void X509Certificate::Fingerprint256(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(ret); } +void X509Certificate::Fingerprint512(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + X509Certificate* cert; + ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); + Local ret; + if (GetFingerprintDigest(env, EVP_sha512(), cert->get()).ToLocal(&ret)) + args.GetReturnValue().Set(ret); +} + void X509Certificate::KeyUsage(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); X509Certificate* cert; diff --git a/src/crypto/crypto_x509.h b/src/crypto/crypto_x509.h index 05bfb6e7cb3e20..12f527235e6341 100644 --- a/src/crypto/crypto_x509.h +++ b/src/crypto/crypto_x509.h @@ -80,6 +80,7 @@ class X509Certificate : public BaseObject { static void ValidTo(const v8::FunctionCallbackInfo& args); static void Fingerprint(const v8::FunctionCallbackInfo& args); static void Fingerprint256(const v8::FunctionCallbackInfo& args); + static void Fingerprint512(const v8::FunctionCallbackInfo& args); static void KeyUsage(const v8::FunctionCallbackInfo& args); static void SerialNumber(const v8::FunctionCallbackInfo& args); static void Raw(const v8::FunctionCallbackInfo& args); diff --git a/src/env.h b/src/env.h index 8760bc4361f199..12f3844f3f9027 100644 --- a/src/env.h +++ b/src/env.h @@ -256,6 +256,7 @@ constexpr size_t kFsStatsBufferLength = V(file_string, "file") \ V(filename_string, "filename") \ V(fingerprint256_string, "fingerprint256") \ + V(fingerprint512_string, "fingerprint512") \ V(fingerprint_string, "fingerprint") \ V(flags_string, "flags") \ V(flowlabel_string, "flowlabel") \ diff --git a/test/parallel/test-crypto-x509.js b/test/parallel/test-crypto-x509.js index c85a79b4854369..d1782359277dc5 100644 --- a/test/parallel/test-crypto-x509.js +++ b/test/parallel/test-crypto-x509.js @@ -103,6 +103,12 @@ const der = Buffer.from( 'B0:BE:46:49:B8:29:63:E0:6F:63:C8:8A:57:9C:3F:9B:72:C6:F5:89:E3:0D:' + '84:AC:5B:08:9A:20:89:B6:8F:D6' ); + assert.strictEqual( + x509.fingerprint512, + 'D0:05:01:82:2C:D8:09:BE:27:94:E7:83:F1:88:BC:7A:8B:D0:39:97:54:B6:' + + 'D0:B4:46:5B:DE:13:5B:68:86:B6:F2:A8:95:22:D5:6E:8B:35:DA:89:29:CA:' + + 'A3:06:C5:CE:43:C1:7F:2D:7E:5F:44:A5:EE:A3:CB:97:05:A3:E3:68' + ); assert.strictEqual(x509.keyUsage, undefined); assert.strictEqual(x509.serialNumber, 'ECC9B856270DA9A8'); @@ -226,6 +232,11 @@ const der = Buffer.from( fingerprint256: 'B0:BE:46:49:B8:29:63:E0:6F:63:C8:8A:57:9C:3F:9B:72:' + 'C6:F5:89:E3:0D:84:AC:5B:08:9A:20:89:B6:8F:D6', + fingerprint512: + 'D0:05:01:82:2C:D8:09:BE:27:94:E7:83:F1:88:BC:7A:8B:' + + 'D0:39:97:54:B6:D0:B4:46:5B:DE:13:5B:68:86:B6:F2:A8:' + + '95:22:D5:6E:8B:35:DA:89:29:CA:A3:06:C5:CE:43:C1:7F:' + + '2D:7E:5F:44:A5:EE:A3:CB:97:05:A3:E3:68', serialNumber: 'ECC9B856270DA9A8' }; diff --git a/test/parallel/test-tls-peer-certificate.js b/test/parallel/test-tls-peer-certificate.js index 523638d4a39649..f220bbc992f7e9 100644 --- a/test/parallel/test-tls-peer-certificate.js +++ b/test/parallel/test-tls-peer-certificate.js @@ -69,6 +69,12 @@ connect({ 'B0:BE:46:49:B8:29:63:E0:6F:63:C8:8A:57:9C:3F:9B:72:C6:F5:89:E3:0D:84:AC:' + '5B:08:9A:20:89:B6:8F:D6' ); + assert.strictEqual( + peerCert.fingerprint512, + 'D0:05:01:82:2C:D8:09:BE:27:94:E7:83:F1:88:BC:7A:8B:D0:39:97:54:B6:' + + 'D0:B4:46:5B:DE:13:5B:68:86:B6:F2:A8:95:22:D5:6E:8B:35:DA:89:29:CA:' + + 'A3:06:C5:CE:43:C1:7F:2D:7E:5F:44:A5:EE:A3:CB:97:05:A3:E3:68' + ); // SHA256 fingerprint of the public key assert.strictEqual( @@ -119,6 +125,12 @@ connect({ 'AB:08:3C:40:C7:07:D7:D1:79:32:92:3B:96:52:D0:38:4C:22:ED:CD:23:51:D0:A1:' + '67:AA:33:A0:D5:26:5C:41' ); + assert.strictEqual( + peerCert.fingerprint512, + '52:F4:86:64:69:0F:94:6F:78:DE:17:7A:5C:92:CA:0F:05:2E:6A:EE:4A:FF:8B:39:' + + 'D6:5E:7A:B8:08:77:B3:80:FC:40:A1:F4:58:CC:7A:DF:BB:3D:38:F9:02:77:50:2B:' + + '9A:0B:FB:79:B4:BD:E9:F5:9C:44:C8:5D:D5:F0:E2:BC' + ); assert.strictEqual( sha256(peerCert.pubkey).digest('hex'),