Skip to content

Commit

Permalink
src: add x509.fingerprint512 to crypto module
Browse files Browse the repository at this point in the history
PR-URL: #39809
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
3nprob authored and tniessen committed Nov 10, 2021
1 parent 5e0dd79 commit 79d6815
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 0 deletions.
9 changes: 9 additions & 0 deletions doc/api/crypto.md
Expand Up @@ -2564,6 +2564,15 @@ added: v15.6.0

The SHA-256 fingerprint of this certificate.

### `x509.fingerprint512`
<!-- YAML
added: REPLACEME
-->

* Type: {string}

The SHA-512 fingerprint of this certificate.

### `x509.infoAccess`

<!-- YAML
Expand Down
7 changes: 7 additions & 0 deletions doc/api/tls.md
Expand Up @@ -1133,6 +1133,9 @@ certificate.

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/39809
description: Add fingerprint512.
- version: v11.4.0
pr-url: https://github.com/nodejs/node/pull/24358
description: Support Elliptic Curve public key info.
Expand All @@ -1158,6 +1161,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.
Expand Down Expand Up @@ -1216,6 +1222,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: <Buffer ... > }
Expand Down
10 changes: 10 additions & 0 deletions lib/internal/crypto/x509.js
Expand Up @@ -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)}`;
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions src/crypto/crypto_common.cc
Expand Up @@ -1103,6 +1103,10 @@ MaybeLocal<Object> X509ToObject(Environment* env, X509* cert) {
info,
env->fingerprint256_string(),
GetFingerprintDigest(env, EVP_sha256(), cert)) ||
!Set<Value>(context,
info,
env->fingerprint512_string(),
GetFingerprintDigest(env, EVP_sha512(), cert)) ||
!Set<Value>(context,
info,
env->ext_key_usage_string(),
Expand Down
10 changes: 10 additions & 0 deletions src/crypto/crypto_x509.cc
Expand Up @@ -68,6 +68,7 @@ Local<FunctionTemplate> 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);
Expand Down Expand Up @@ -268,6 +269,15 @@ void X509Certificate::Fingerprint256(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(ret);
}

void X509Certificate::Fingerprint512(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
X509Certificate* cert;
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder());
Local<Value> ret;
if (GetFingerprintDigest(env, EVP_sha512(), cert->get()).ToLocal(&ret))
args.GetReturnValue().Set(ret);
}

void X509Certificate::KeyUsage(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
X509Certificate* cert;
Expand Down
1 change: 1 addition & 0 deletions src/crypto/crypto_x509.h
Expand Up @@ -81,6 +81,7 @@ class X509Certificate : public BaseObject {
static void ValidTo(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Fingerprint(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Fingerprint256(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Fingerprint512(const v8::FunctionCallbackInfo<v8::Value>& args);
static void KeyUsage(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SerialNumber(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Raw(const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down
1 change: 1 addition & 0 deletions src/env.h
Expand Up @@ -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") \
Expand Down
11 changes: 11 additions & 0 deletions test/parallel/test-crypto-x509.js
Expand Up @@ -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');

Expand Down Expand Up @@ -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'
};

Expand Down
12 changes: 12 additions & 0 deletions test/parallel/test-tls-peer-certificate.js
Expand Up @@ -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(
Expand Down Expand Up @@ -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'),
Expand Down

0 comments on commit 79d6815

Please sign in to comment.