mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
crypto: expose signatureAlgorithm on X509Certificate
Adds the `signatureAlgorithm` property to a X509Certificate allowing users to retrieve a string representing the algorithm used to sign the certificate. This string is defined by the OpenSSL library. Fixes: https://github.com/nodejs/node/issues/59103 PR-URL: https://github.com/nodejs/node/pull/59235 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
This commit is contained in:
parent
f1a8f447d7
commit
64a8b4b1ba
25
deps/ncrypto/ncrypto.cc
vendored
25
deps/ncrypto/ncrypto.cc
vendored
|
|
@ -8,7 +8,9 @@
|
|||
#include <openssl/rand.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/params.h>
|
||||
|
|
@ -1094,6 +1096,29 @@ BIOPointer X509View::getValidTo() const {
|
|||
return bio;
|
||||
}
|
||||
|
||||
std::optional<std::string_view> X509View::getSignatureAlgorithm() const {
|
||||
if (cert_ == nullptr) return std::nullopt;
|
||||
int nid = X509_get_signature_nid(cert_);
|
||||
if (nid == NID_undef) return std::nullopt;
|
||||
const char* ln = OBJ_nid2ln(nid);
|
||||
if (ln == nullptr) return std::nullopt;
|
||||
return std::string_view(ln);
|
||||
}
|
||||
|
||||
std::optional<std::string> X509View::getSignatureAlgorithmOID() const {
|
||||
if (cert_ == nullptr) return std::nullopt;
|
||||
const X509_ALGOR* alg = nullptr;
|
||||
X509_get0_signature(nullptr, &alg, cert_);
|
||||
if (alg == nullptr) return std::nullopt;
|
||||
const ASN1_OBJECT* obj = nullptr;
|
||||
X509_ALGOR_get0(&obj, nullptr, nullptr, alg);
|
||||
if (obj == nullptr) return std::nullopt;
|
||||
std::array<char, 128> buf{};
|
||||
int len = OBJ_obj2txt(buf.data(), buf.size(), obj, 1);
|
||||
if (len < 0 || static_cast<size_t>(len) >= buf.size()) return std::nullopt;
|
||||
return std::string(buf.data(), static_cast<size_t>(len));
|
||||
}
|
||||
|
||||
int64_t X509View::getValidToTime() const {
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
// Boringssl does not implement ASN1_TIME_to_tm in a public way,
|
||||
|
|
|
|||
2
deps/ncrypto/ncrypto.h
vendored
2
deps/ncrypto/ncrypto.h
vendored
|
|
@ -1191,6 +1191,8 @@ class X509View final {
|
|||
BIOPointer getInfoAccess() const;
|
||||
BIOPointer getValidFrom() const;
|
||||
BIOPointer getValidTo() const;
|
||||
std::optional<std::string_view> getSignatureAlgorithm() const;
|
||||
std::optional<std::string> getSignatureAlgorithmOID() const;
|
||||
int64_t getValidFromTime() const;
|
||||
int64_t getValidToTime() const;
|
||||
DataPointer getSerialNumber() const;
|
||||
|
|
|
|||
|
|
@ -2971,6 +2971,26 @@ added:
|
|||
|
||||
The date/time until which this certificate is valid, encapsulated in a `Date` object.
|
||||
|
||||
### `x509.signatureAlgorithm`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* Type: {string|undefined}
|
||||
|
||||
The algorithm used to sign the certificate or `undefined` if the signature algorithm is unknown by OpenSSL.
|
||||
|
||||
### `x509.signatureAlgorithmOid`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* Type: {string}
|
||||
|
||||
The OID of the algorithm used to sign the certificate.
|
||||
|
||||
### `x509.verify(publicKey)`
|
||||
|
||||
<!-- YAML
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ class X509Certificate {
|
|||
fingerprint512: this.fingerprint512,
|
||||
keyUsage: this.keyUsage,
|
||||
serialNumber: this.serialNumber,
|
||||
signatureAlgorithm: this.signatureAlgorithm,
|
||||
signatureAlgorithmOid: this.signatureAlgorithmOid,
|
||||
}, opts)}`;
|
||||
}
|
||||
|
||||
|
|
@ -285,6 +287,24 @@ class X509Certificate {
|
|||
return value;
|
||||
}
|
||||
|
||||
get signatureAlgorithm() {
|
||||
let value = this[kInternalState].get('signatureAlgorithm');
|
||||
if (value === undefined) {
|
||||
value = this[kHandle].signatureAlgorithm();
|
||||
this[kInternalState].set('signatureAlgorithm', value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
get signatureAlgorithmOid() {
|
||||
let value = this[kInternalState].get('signatureAlgorithmOid');
|
||||
if (value === undefined) {
|
||||
value = this[kHandle].signatureAlgorithmOid();
|
||||
this[kInternalState].set('signatureAlgorithmOid', value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
get raw() {
|
||||
let value = this[kInternalState].get('raw');
|
||||
if (value === undefined) {
|
||||
|
|
|
|||
|
|
@ -225,6 +225,30 @@ MaybeLocal<Value> GetValidToDate(Environment* env, const X509View& view) {
|
|||
return Date::New(env->context(), validToTime * 1000.);
|
||||
}
|
||||
|
||||
MaybeLocal<Value> GetSignatureAlgorithm(Environment* env,
|
||||
const X509View& view) {
|
||||
auto algo = view.getSignatureAlgorithm();
|
||||
if (!algo.has_value()) [[unlikely]]
|
||||
return Undefined(env->isolate());
|
||||
Local<Value> ret;
|
||||
if (!ToV8Value(env, algo.value()).ToLocal(&ret)) {
|
||||
return {};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MaybeLocal<Value> GetSignatureAlgorithmOID(Environment* env,
|
||||
const X509View& view) {
|
||||
auto oid = view.getSignatureAlgorithmOID();
|
||||
if (!oid.has_value()) [[unlikely]]
|
||||
return Undefined(env->isolate());
|
||||
Local<Value> ret;
|
||||
if (!ToV8Value(env, oid.value()).ToLocal(&ret)) {
|
||||
return {};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MaybeLocal<Value> GetSerialNumber(Environment* env, const X509View& view) {
|
||||
if (auto serial = view.getSerialNumber()) {
|
||||
return OneByteString(env->isolate(),
|
||||
|
|
@ -342,6 +366,26 @@ void ValidToDate(const FunctionCallbackInfo<Value>& args) {
|
|||
}
|
||||
}
|
||||
|
||||
void SignatureAlgorithm(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
X509Certificate* cert;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&cert, args.This());
|
||||
Local<Value> ret;
|
||||
if (GetSignatureAlgorithm(env, cert->view()).ToLocal(&ret)) {
|
||||
args.GetReturnValue().Set(ret);
|
||||
}
|
||||
}
|
||||
|
||||
void SignatureAlgorithmOID(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
X509Certificate* cert;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&cert, args.This());
|
||||
Local<Value> ret;
|
||||
if (GetSignatureAlgorithmOID(env, cert->view()).ToLocal(&ret)) {
|
||||
args.GetReturnValue().Set(ret);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
X509Certificate* cert;
|
||||
|
|
@ -822,6 +866,10 @@ Local<FunctionTemplate> X509Certificate::GetConstructorTemplate(
|
|||
SetProtoMethodNoSideEffect(isolate, tmpl, "validFrom", ValidFrom);
|
||||
SetProtoMethodNoSideEffect(isolate, tmpl, "validToDate", ValidToDate);
|
||||
SetProtoMethodNoSideEffect(isolate, tmpl, "validFromDate", ValidFromDate);
|
||||
SetProtoMethodNoSideEffect(
|
||||
isolate, tmpl, "signatureAlgorithm", SignatureAlgorithm);
|
||||
SetProtoMethodNoSideEffect(
|
||||
isolate, tmpl, "signatureAlgorithmOid", SignatureAlgorithmOID);
|
||||
SetProtoMethodNoSideEffect(
|
||||
isolate, tmpl, "fingerprint", Fingerprint<Digest::SHA1>);
|
||||
SetProtoMethodNoSideEffect(
|
||||
|
|
@ -996,6 +1044,8 @@ void X509Certificate::RegisterExternalReferences(
|
|||
registry->Register(ValidFrom);
|
||||
registry->Register(ValidToDate);
|
||||
registry->Register(ValidFromDate);
|
||||
registry->Register(SignatureAlgorithm);
|
||||
registry->Register(SignatureAlgorithmOID);
|
||||
registry->Register(Fingerprint<Digest::SHA1>);
|
||||
registry->Register(Fingerprint<Digest::SHA256>);
|
||||
registry->Register(Fingerprint<Digest::SHA512>);
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ const der = Buffer.from(
|
|||
assert.strictEqual(x509.keyUsage, undefined);
|
||||
assert.strictEqual(x509.serialNumber.toUpperCase(), '147D36C1C2F74206DE9FAB5F2226D78ADB00A426');
|
||||
|
||||
assert.strictEqual(x509.signatureAlgorithm, 'sha256WithRSAEncryption');
|
||||
assert.strictEqual(x509.signatureAlgorithmOid, '1.2.840.113549.1.1.11');
|
||||
|
||||
assert.deepStrictEqual(x509.raw, der);
|
||||
|
||||
if (!process.features.openssl_is_boringssl) {
|
||||
|
|
@ -448,3 +451,17 @@ CWwQO8JZjJqFtqtuzy2n+gLCvqePgG/gmSqHOPm2ZbLW
|
|||
assert.deepStrictEqual(c2.validToDate, new Date('2050-01-02T00:00:01Z'));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const certPem = `-----BEGIN CERTIFICATE-----
|
||||
MIGXMHugAwIBAgIBATANBgkrBgEEAYaNHwEFADASMRAwDgYDVQQDEwdVbmtub3du
|
||||
MB4XDTI0MDEwMTAwMDAwMFoXDTM0MDEwMTAwMDAwMFowEjEQMA4GA1UEAxMHVW5r
|
||||
bm93bjAaMA0GCSqGSIb3DQEBAQUAAwkAAAAAAAAAAAAwDQYJKwYBBAGGjR8BBQAD
|
||||
CQAAAAAAAAAAAA==
|
||||
-----END CERTIFICATE-----`;
|
||||
|
||||
const cert = new X509Certificate(certPem);
|
||||
|
||||
assert.strictEqual(cert.signatureAlgorithm, undefined);
|
||||
assert.strictEqual(cert.signatureAlgorithmOid, '1.3.6.1.4.1.99999.1');
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user