From d64c93c0cbece4afa4bb05097b629c81bcb80bed Mon Sep 17 00:00:00 2001 From: Sam Aarons Date: Sun, 17 May 2015 18:04:36 -0700 Subject: [PATCH] tls: Add subjectPublicKeyInfo to certificate info Added `subjectPublicKeyInfo` attribute to the peer certificate object. The attribute is a buffer containing the DER-encoded value of the SubjectPublicKeyInfo structure as described in RFC 5280. This will allow applications to retrieve the SPKI information necessary for validating HTTP public key pins according to RFC 7469. https://tools.ietf.org/html/rfc7469 --- doc/api/tls.markdown | 3 ++- src/env.h | 1 + src/node_crypto.cc | 10 +++++++++- test/parallel/test-tls-peer-certificate.js | 7 +++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index 657f690343ff..b001712b64e4 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -725,7 +725,8 @@ Example: valid_from: 'Nov 11 09:52:22 2009 GMT', valid_to: 'Nov 6 09:52:22 2029 GMT', fingerprint: '2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF', - serialNumber: 'B9B0D332A1AA5635' } + serialNumber: 'B9B0D332A1AA5635', + subjectPublicKeyInfo: < SPKI DER buffer > } If the peer does not provide a certificate, it returns `null` or an empty object. diff --git a/src/env.h b/src/env.h index e327786e36b9..68bfeaa94575 100644 --- a/src/env.h +++ b/src/env.h @@ -193,6 +193,7 @@ namespace node { V(status_string, "status") \ V(stdio_string, "stdio") \ V(subject_string, "subject") \ + V(subject_public_key_info_string, "subjectPublicKeyInfo") \ V(subjectaltname_string, "subjectaltname") \ V(sys_string, "sys") \ V(syscall_string, "syscall") \ diff --git a/src/node_crypto.cc b/src/node_crypto.cc index e49545810d3f..f4a584c1d742 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -1217,9 +1217,17 @@ static Local X509ToObject(Environment* env, X509* cert) { EVP_PKEY* pkey = X509_get_pubkey(cert); RSA* rsa = nullptr; - if (pkey != nullptr) + if (pkey != nullptr) { rsa = EVP_PKEY_get1_RSA(pkey); + int pkey_size = i2d_PUBKEY(pkey, nullptr); + Local pkey_buff = Buffer::New(env, pkey_size); + unsigned char* pkey_serialized = reinterpret_cast( + Buffer::Data(pkey_buff)); + i2d_PUBKEY(pkey, &pkey_serialized); + info->Set(env->subject_public_key_info_string(), pkey_buff); + } + if (rsa != nullptr) { BN_print(bio, rsa->n); BIO_get_mem_ptr(bio, &mem); diff --git a/test/parallel/test-tls-peer-certificate.js b/test/parallel/test-tls-peer-certificate.js index afd88531ea4a..3c7598478fda 100644 --- a/test/parallel/test-tls-peer-certificate.js +++ b/test/parallel/test-tls-peer-certificate.js @@ -19,6 +19,11 @@ var options = { }; var verified = false; +var expectedBase64SubjectPublicKeyInfo = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB' + + 'iQKBgQC46zeFbysX7vHHmIH3COYiB34dOpEVR4rEb6ZZXfkeXoDe7NgZfBbOeqw6iavhr' + + '9SRmvFs8ankDCpr2DvY0X3uDdLKyrYNbhrfJxdYB5hhwdKVHGokZdOPH68b/ScMJcsGGg' + + 'Mo7TTMRxx2MZLzESOOJ5BCv4p4BKYibSRCa43lhwIDAQAB'; + var server = tls.createServer(options, function(cleartext) { cleartext.end('World'); }); @@ -37,6 +42,8 @@ server.listen(common.PORT, function() { common.debug(util.inspect(peerCert)); assert.equal(peerCert.subject.emailAddress, 'ry@tinyclouds.org'); assert.equal(peerCert.serialNumber, '9A84ABCFB8A72AC0'); + assert.equal(peerCert.subjectPublicKeyInfo.toString('base64'), + expectedBase64SubjectPublicKeyInfo); assert.deepEqual(peerCert.infoAccess['OCSP - URI'], [ 'http://ocsp.nodejs.org/' ]);