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 657f690343ff03..b001712b64e42f 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 e327786e36b907..68bfeaa945759c 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 e49545810d3f78..f4a584c1d742bb 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 afd88531ea4a31..3c7598478fda13 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/' ]);