@fidm/x509
Advanced tools
Comparing version 1.1.0 to 1.1.1
/// <reference types="node" /> | ||
/** | ||
* Converts IP string into buffer, 4 bytes for IPv4, and 16 bytes for IPv6. | ||
* It will return null when IP string invalid. | ||
* | ||
* ```js | ||
* console.log(bytesFromIP('::1')) // <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01> | ||
* ``` | ||
* @param ip IP string to convert | ||
*/ | ||
export declare function bytesFromIP(ip: string): Buffer | null; | ||
/** | ||
* Converts 4-bytes into an IPv4 string representation or 16-bytes into | ||
* an IPv6 string representation. The bytes must be in network order. | ||
* | ||
* ```js | ||
* console.log(bytesToIP(Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]))) // '::1' | ||
* ``` | ||
* @param bytes buffer to convert | ||
*/ | ||
export declare function bytesToIP(bytes: Buffer): string; | ||
/** | ||
* Returns Object Identifier (dot-separated numeric string) that registered by initOID function. | ||
* It will return empty string if not exists. | ||
* @param nameOrId OID name or OID | ||
*/ | ||
export declare function getOID(nameOrId: string): string; | ||
/** | ||
* Returns Object Identifier name that registered by initOID function. | ||
* It will return the argument nameOrId if not exists. | ||
* @param nameOrId OID name or OID | ||
*/ | ||
export declare function getOIDName(nameOrId: string): string; |
@@ -7,2 +7,11 @@ 'use strict'; | ||
const net_1 = require("net"); | ||
/** | ||
* Converts IP string into buffer, 4 bytes for IPv4, and 16 bytes for IPv6. | ||
* It will return null when IP string invalid. | ||
* | ||
* ```js | ||
* console.log(bytesFromIP('::1')) // <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01> | ||
* ``` | ||
* @param ip IP string to convert | ||
*/ | ||
function bytesFromIP(ip) { | ||
@@ -37,4 +46,11 @@ switch (net_1.isIP(ip)) { | ||
exports.bytesFromIP = bytesFromIP; | ||
// Converts 4-bytes into an IPv4 string representation or 16-bytes into | ||
// an IPv6 string representation. The bytes must be in network order. | ||
/** | ||
* Converts 4-bytes into an IPv4 string representation or 16-bytes into | ||
* an IPv6 string representation. The bytes must be in network order. | ||
* | ||
* ```js | ||
* console.log(bytesToIP(Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]))) // '::1' | ||
* ``` | ||
* @param bytes buffer to convert | ||
*/ | ||
function bytesToIP(bytes) { | ||
@@ -88,3 +104,7 @@ switch (bytes.length) { | ||
const oidReg = /^[0-9.]+$/; | ||
// getOID returns oid or '' | ||
/** | ||
* Returns Object Identifier (dot-separated numeric string) that registered by initOID function. | ||
* It will return empty string if not exists. | ||
* @param nameOrId OID name or OID | ||
*/ | ||
function getOID(nameOrId) { | ||
@@ -97,3 +117,7 @@ if (oidReg.test(nameOrId) && oids[nameOrId] !== '') { | ||
exports.getOID = getOID; | ||
// getOIDName return name or oid | ||
/** | ||
* Returns Object Identifier name that registered by initOID function. | ||
* It will return the argument nameOrId if not exists. | ||
* @param nameOrId OID name or OID | ||
*/ | ||
function getOIDName(nameOrId) { | ||
@@ -106,8 +130,10 @@ if (!oidReg.test(nameOrId) && oids[nameOrId] !== '') { | ||
exports.getOIDName = getOIDName; | ||
// set id to name mapping and name to id mapping | ||
function initOID(id, name, unidirection = false) { | ||
oids[id] = name; | ||
if (!unidirection) { | ||
oids[name] = id; | ||
} | ||
/** | ||
* Register OID and name | ||
* @param oid Object Identifier | ||
* @param name Object Identifier name | ||
*/ | ||
function initOID(oid, name) { | ||
oids[oid] = name; | ||
oids[name] = oid; | ||
} | ||
@@ -192,29 +218,29 @@ // algorithm OIDs | ||
initOID('2.16.840.1.113730.1.1', 'nsCertType'); | ||
initOID('2.5.29.2', 'keyAttributes', true); // obsolete, use .37 or .15 | ||
initOID('2.5.29.4', 'keyUsageRestriction', true); // obsolete, use .37 or .15 | ||
initOID('2.5.29.6', 'subtreesConstraint', true); // obsolete, use .30 | ||
initOID('2.5.29.9', 'subjectDirectoryAttributes', true); | ||
initOID('2.5.29.2', 'keyAttributes'); // obsolete, use .37 or .15 | ||
initOID('2.5.29.4', 'keyUsageRestriction'); // obsolete, use .37 or .15 | ||
initOID('2.5.29.6', 'subtreesConstraint'); // obsolete, use .30 | ||
initOID('2.5.29.9', 'subjectDirectoryAttributes'); | ||
initOID('2.5.29.14', 'subjectKeyIdentifier'); | ||
initOID('2.5.29.15', 'keyUsage'); | ||
initOID('2.5.29.16', 'privateKeyUsagePeriod', true); | ||
initOID('2.5.29.16', 'privateKeyUsagePeriod'); | ||
initOID('2.5.29.17', 'subjectAltName'); | ||
initOID('2.5.29.18', 'issuerAltName'); | ||
initOID('2.5.29.19', 'basicConstraints'); | ||
initOID('2.5.29.20', 'cRLNumber', true); | ||
initOID('2.5.29.21', 'cRLReason', true); | ||
initOID('2.5.29.22', 'expirationDate', true); | ||
initOID('2.5.29.23', 'instructionCode', true); | ||
initOID('2.5.29.24', 'invalidityDate', true); | ||
initOID('2.5.29.27', 'deltaCRLIndicator', true); | ||
initOID('2.5.29.28', 'issuingDistributionPoint', true); | ||
initOID('2.5.29.29', 'certificateIssuer', true); | ||
initOID('2.5.29.30', 'nameConstraints', true); | ||
initOID('2.5.29.20', 'cRLNumber'); | ||
initOID('2.5.29.21', 'cRLReason'); | ||
initOID('2.5.29.22', 'expirationDate'); | ||
initOID('2.5.29.23', 'instructionCode'); | ||
initOID('2.5.29.24', 'invalidityDate'); | ||
initOID('2.5.29.27', 'deltaCRLIndicator'); | ||
initOID('2.5.29.28', 'issuingDistributionPoint'); | ||
initOID('2.5.29.29', 'certificateIssuer'); | ||
initOID('2.5.29.30', 'nameConstraints'); | ||
initOID('2.5.29.31', 'cRLDistributionPoints'); | ||
initOID('2.5.29.32', 'certificatePolicies'); | ||
initOID('2.5.29.33', 'policyMappings', true); | ||
initOID('2.5.29.33', 'policyMappings'); | ||
initOID('2.5.29.35', 'authorityKeyIdentifier'); | ||
initOID('2.5.29.36', 'policyConstraints', true); | ||
initOID('2.5.29.36', 'policyConstraints'); | ||
initOID('2.5.29.37', 'extKeyUsage'); | ||
initOID('2.5.29.46', 'freshestCRL', true); | ||
initOID('2.5.29.54', 'inhibitAnyPolicy', true); | ||
initOID('2.5.29.46', 'freshestCRL'); | ||
initOID('2.5.29.54', 'inhibitAnyPolicy'); | ||
// extKeyUsage purposes | ||
@@ -221,0 +247,0 @@ initOID('1.3.6.1.4.1.311.60.2.1.2', 'jurisdictionST'); |
/// <reference types="node" /> | ||
import { ASN1, Template } from '@fidm/asn1'; | ||
/** | ||
* ASN.1 Template for PKCS#8 Public Key. | ||
*/ | ||
export declare const publicKeyValidator: Template; | ||
/** | ||
* ASN.1 Template for PKCS#8 Private Key. https://tools.ietf.org/html/rfc5208 | ||
*/ | ||
export declare const privateKeyValidator: Template; | ||
export declare type Verifier = (this: PublicKey, data: Buffer, signature: Buffer) => boolean; | ||
/** | ||
* PKCS#8 Public Key | ||
*/ | ||
export declare class PublicKey { | ||
/** | ||
* Parse an PublicKey for X.509 certificate from PKCS#8 PEM formatted buffer or PKCS#1 RSA PEM formatted buffer. | ||
* @param pem PEM formatted buffer | ||
*/ | ||
static fromPEM(pem: Buffer): PublicKey; | ||
/** | ||
* Registers an external Verifier with object identifier. | ||
* Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_verify | ||
* ```js | ||
* PublicKey.addVerifier(getOID('Ed25519'), function (this: PublicKey, data: Buffer, signature: Buffer): boolean { | ||
* return ed25519.detached.verify(data, signature, this.keyRaw) | ||
* }) | ||
* ``` | ||
* @param oid algorithm object identifier | ||
* @param fn Verifier function | ||
*/ | ||
static addVerifier(oid: string, fn: Verifier): void; | ||
@@ -17,7 +41,36 @@ private static _verifiers; | ||
constructor(obj: ASN1); | ||
/** | ||
* underlying key buffer | ||
*/ | ||
readonly keyRaw: Buffer; | ||
/** | ||
* Returns true if the provided data and the given signature matched. | ||
* ```js | ||
* certificate.publicKey.verify(data, signature, 'sha256') // => true or false | ||
* ``` | ||
* @param data data to verify | ||
* @param signature signature that signed by private key | ||
* @param hashAlgorithm hash algorithm, such as 'sha256', 'sha1' | ||
*/ | ||
verify(data: Buffer, signature: Buffer, hashAlgorithm: string): boolean; | ||
/** | ||
* Returns the digest of the PublicKey with given hash algorithm. | ||
* ```js | ||
* certificate.publicKey.getFingerprint('sha1', 'PublicKey') // => Buffer | ||
* ``` | ||
* @param hashAlgorithm hash algorithm, such as 'sha256', 'sha1' | ||
* @param type 'PublicKey' or 'PublicKeyInfo' | ||
*/ | ||
getFingerprint(hashAlgorithm: string, type?: string): Buffer; | ||
/** | ||
* Returns an ASN.1 object of this PublicKey | ||
*/ | ||
toASN1(): ASN1; | ||
/** | ||
* Returns an DER formatted buffer of this PublicKey | ||
*/ | ||
toDER(): Buffer; | ||
/** | ||
* Returns an PEM formatted string of this PublicKey | ||
*/ | ||
toPEM(): string; | ||
@@ -30,4 +83,26 @@ /** | ||
export declare type Signer = (this: PrivateKey, data: Buffer) => Buffer; | ||
/** | ||
* PKCS#8 Private Key | ||
*/ | ||
export declare class PrivateKey { | ||
/** | ||
* Parse an PrivateKey for X.509 certificate from PKCS#8 PEM formatted buffer or PKCS#1 RSA PEM formatted buffer. | ||
* @param pem PEM formatted buffer | ||
*/ | ||
static fromPEM(pem: Buffer): PrivateKey; | ||
/** | ||
* Registers an external Signer with object identifier. | ||
* Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_sign | ||
* ```js | ||
* PrivateKey.addSigner(getOID('Ed25519'), function (this: PrivateKey, data: Buffer): Buffer { | ||
* const key = this.keyRaw | ||
* if (key.length !== 64) { | ||
* throw new Error('Invalid signing key, should setPublicKeyRaw before sign.') | ||
* } | ||
* return Buffer.from(ed25519.detached(data, key)) | ||
* }) | ||
* ``` | ||
* @param oid algorithm object identifier | ||
* @param fn Verifier function | ||
*/ | ||
static addSigner(oid: string, fn: Signer): void; | ||
@@ -44,8 +119,33 @@ private static _signers; | ||
constructor(obj: ASN1); | ||
/** | ||
* underlying key buffer | ||
*/ | ||
readonly keyRaw: Buffer; | ||
/** | ||
* Returns publicKey buffer, it is used for Ed25519/Ed448. | ||
*/ | ||
readonly publicKeyRaw: Buffer | null; | ||
/** | ||
* Sets an PublicKey into PrivateKey. | ||
* It is used for Ed25519/Ed448. If oid not matched, an error will be thrown. | ||
* @param key public key | ||
*/ | ||
setPublicKey(key: PublicKey): void; | ||
/** | ||
* Returns signature for the given data and hash algorithm. | ||
* @param data | ||
* @param hashAlgorithm | ||
*/ | ||
sign(data: Buffer, hashAlgorithm: string): Buffer; | ||
/** | ||
* Returns an ASN.1 object of this PrivateKey | ||
*/ | ||
toASN1(): ASN1; | ||
/** | ||
* Returns an DER formatted buffer of this PrivateKey | ||
*/ | ||
toDER(): Buffer; | ||
/** | ||
* Returns an PEM formatted string of this PrivateKey | ||
*/ | ||
toPEM(): string; | ||
@@ -57,2 +157,5 @@ /** | ||
} | ||
/** | ||
* PKCS#1 RSA Public Key | ||
*/ | ||
export declare class RSAPublicKey extends PublicKey { | ||
@@ -65,10 +168,25 @@ static fromPublicKey(publicKey: PublicKey): RSAPublicKey; | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
* Returns an PKCS#1 ASN.1 object of this RSAPublicKey | ||
*/ | ||
toJSON(): any; | ||
toASN1(): ASN1; | ||
/** | ||
* Returns an PKCS#1 DER formatted buffer of this RSAPublicKey | ||
*/ | ||
toDER(): Buffer; | ||
/** | ||
* Returns an PKCS#1 PEM formatted string of this RSAPublicKey | ||
*/ | ||
toPEM(): string; | ||
/** | ||
* Returns an PKCS#8 PEM formatted string of this RSAPublicKey | ||
*/ | ||
toPublicKeyPEM(): string; | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
*/ | ||
toJSON(): any; | ||
} | ||
/** | ||
* PKCS#1 RSA Private Key | ||
*/ | ||
export declare class RSAPrivateKey extends PrivateKey { | ||
@@ -87,9 +205,21 @@ static fromPrivateKey(privateKey: PrivateKey): RSAPrivateKey; | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
* Returns an PKCS#1 ASN.1 object of this RSAPrivateKey | ||
*/ | ||
toJSON(): any; | ||
toASN1(): ASN1; | ||
/** | ||
* Returns an PKCS#1 DER formatted buffer of this RSAPrivateKey | ||
*/ | ||
toDER(): Buffer; | ||
/** | ||
* Returns an PKCS#1 PEM formatted string of this RSAPrivateKey | ||
*/ | ||
toPEM(): string; | ||
/** | ||
* Returns an PKCS#8 PEM formatted string of this RSAPrivateKey | ||
*/ | ||
toPrivateKeyPEM(): string; | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
*/ | ||
toJSON(): any; | ||
} |
204
build/pki.js
@@ -11,3 +11,5 @@ 'use strict'; | ||
const common_1 = require("./common"); | ||
// PKCS#8 Public Key | ||
/** | ||
* ASN.1 Template for PKCS#8 Public Key. | ||
*/ | ||
exports.publicKeyValidator = { | ||
@@ -35,3 +37,5 @@ name: 'PublicKeyInfo', | ||
}; | ||
// PKCS#8 Private Key, https://tools.ietf.org/html/rfc5208 | ||
/** | ||
* ASN.1 Template for PKCS#8 Private Key. https://tools.ietf.org/html/rfc5208 | ||
*/ | ||
exports.privateKeyValidator = { | ||
@@ -152,5 +156,8 @@ name: 'PrivateKeyInfo', | ||
]; | ||
/** | ||
* PKCS#8 Public Key | ||
*/ | ||
class PublicKey { | ||
constructor(obj) { | ||
const captures = Object.create(null); | ||
const captures = {}; | ||
const err = obj.validate(exports.publicKeyValidator, captures); | ||
@@ -167,3 +174,6 @@ if (err != null) { | ||
} | ||
// Parse an PublicKey for X.509 certificate from PKCS#8 PEM format buffer or PKCS#1 RSA PEM format buffer. | ||
/** | ||
* Parse an PublicKey for X.509 certificate from PKCS#8 PEM formatted buffer or PKCS#1 RSA PEM formatted buffer. | ||
* @param pem PEM formatted buffer | ||
*/ | ||
static fromPEM(pem) { | ||
@@ -195,6 +205,16 @@ const msg = asn1_1.PEM.parse(pem)[0]; | ||
} | ||
// Registers an external Verifier with object identifier. | ||
// Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_verify | ||
/** | ||
* Registers an external Verifier with object identifier. | ||
* Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_verify | ||
* ```js | ||
* PublicKey.addVerifier(getOID('Ed25519'), function (this: PublicKey, data: Buffer, signature: Buffer): boolean { | ||
* return ed25519.detached.verify(data, signature, this.keyRaw) | ||
* }) | ||
* ``` | ||
* @param oid algorithm object identifier | ||
* @param fn Verifier function | ||
*/ | ||
static addVerifier(oid, fn) { | ||
if (common_1.getOID(oid) === '') { | ||
oid = common_1.getOID(oid); | ||
if (oid === '') { | ||
throw new Error(`Invalid object identifier: ${oid}`); | ||
@@ -207,6 +227,17 @@ } | ||
} | ||
/** | ||
* underlying key buffer | ||
*/ | ||
get keyRaw() { | ||
return this._finalKey; | ||
} | ||
// Returns true if the provided data and the given signature matched. | ||
/** | ||
* Returns true if the provided data and the given signature matched. | ||
* ```js | ||
* certificate.publicKey.verify(data, signature, 'sha256') // => true or false | ||
* ``` | ||
* @param data data to verify | ||
* @param signature signature that signed by private key | ||
* @param hashAlgorithm hash algorithm, such as 'sha256', 'sha1' | ||
*/ | ||
verify(data, signature, hashAlgorithm) { | ||
@@ -222,3 +253,10 @@ const verifier = PublicKey._verifiers[this.oid]; | ||
} | ||
// Returns the digest of the PublicKey with given hash algorithm. | ||
/** | ||
* Returns the digest of the PublicKey with given hash algorithm. | ||
* ```js | ||
* certificate.publicKey.getFingerprint('sha1', 'PublicKey') // => Buffer | ||
* ``` | ||
* @param hashAlgorithm hash algorithm, such as 'sha256', 'sha1' | ||
* @param type 'PublicKey' or 'PublicKeyInfo' | ||
*/ | ||
getFingerprint(hashAlgorithm, type = 'PublicKey') { | ||
@@ -240,8 +278,17 @@ let bytes; | ||
} | ||
/** | ||
* Returns an ASN.1 object of this PublicKey | ||
*/ | ||
toASN1() { | ||
return this._pkcs8; | ||
} | ||
/** | ||
* Returns an DER formatted buffer of this PublicKey | ||
*/ | ||
toDER() { | ||
return this._pkcs8.DER; | ||
} | ||
/** | ||
* Returns an PEM formatted string of this PublicKey | ||
*/ | ||
toPEM() { | ||
@@ -269,2 +316,5 @@ if (this._finalPEM === '') { | ||
exports.PublicKey = PublicKey; | ||
/** | ||
* PKCS#8 Private Key | ||
*/ | ||
class PrivateKey { | ||
@@ -278,3 +328,3 @@ constructor(obj) { | ||
} | ||
this.version = asn1_1.ASN1.parseIntegerNum(captures.privateKeyVersion.bytes); | ||
this.version = asn1_1.ASN1.parseIntegerNum(captures.privateKeyVersion.bytes) + 1; | ||
this.oid = asn1_1.ASN1.parseOID(captures.privateKeyOID.bytes); | ||
@@ -289,3 +339,3 @@ this.algo = common_1.getOIDName(this.oid); | ||
this._finalKey = this._keyRaw = asn1_1.ASN1.parseDER(this._keyRaw, asn1_1.Class.UNIVERSAL, asn1_1.Tag.OCTETSTRING).bytes; | ||
if (this.version === 1) { | ||
if (this.version === 2) { | ||
for (const val of obj.mustCompound()) { | ||
@@ -300,3 +350,6 @@ if (val.class === asn1_1.Class.CONTEXT_SPECIFIC && val.tag === 1) { | ||
} | ||
// Parse an PrivateKey for X.509 certificate from PKCS#8 PEM format buffer or PKCS#1 RSA PEM format buffer. | ||
/** | ||
* Parse an PrivateKey for X.509 certificate from PKCS#8 PEM formatted buffer or PKCS#1 RSA PEM formatted buffer. | ||
* @param pem PEM formatted buffer | ||
*/ | ||
static fromPEM(pem) { | ||
@@ -330,6 +383,20 @@ const msg = asn1_1.PEM.parse(pem)[0]; | ||
} | ||
// Registers an external Signer with object identifier. | ||
// Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_sign | ||
/** | ||
* Registers an external Signer with object identifier. | ||
* Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_sign | ||
* ```js | ||
* PrivateKey.addSigner(getOID('Ed25519'), function (this: PrivateKey, data: Buffer): Buffer { | ||
* const key = this.keyRaw | ||
* if (key.length !== 64) { | ||
* throw new Error('Invalid signing key, should setPublicKeyRaw before sign.') | ||
* } | ||
* return Buffer.from(ed25519.detached(data, key)) | ||
* }) | ||
* ``` | ||
* @param oid algorithm object identifier | ||
* @param fn Verifier function | ||
*/ | ||
static addSigner(oid, fn) { | ||
if (common_1.getOID(oid) === '') { | ||
oid = common_1.getOID(oid); | ||
if (oid === '') { | ||
throw new Error(`Invalid object identifier: ${oid}`); | ||
@@ -342,11 +409,19 @@ } | ||
} | ||
/** | ||
* underlying key buffer | ||
*/ | ||
get keyRaw() { | ||
return this._finalKey; | ||
} | ||
// Returns publicKey buffer, it is used for Ed25519/Ed448. | ||
/** | ||
* Returns publicKey buffer, it is used for Ed25519/Ed448. | ||
*/ | ||
get publicKeyRaw() { | ||
return this._publicKeyRaw; | ||
} | ||
// Sets an PublicKey into PrivateKey. | ||
// It is used for Ed25519/Ed448. If oid not matched, an error will be thrown. | ||
/** | ||
* Sets an PublicKey into PrivateKey. | ||
* It is used for Ed25519/Ed448. If oid not matched, an error will be thrown. | ||
* @param key public key | ||
*/ | ||
setPublicKey(key) { | ||
@@ -361,3 +436,7 @@ if (this.oid !== key.oid) { | ||
} | ||
// Returns signature for the given data and hash algorithm. | ||
/** | ||
* Returns signature for the given data and hash algorithm. | ||
* @param data | ||
* @param hashAlgorithm | ||
*/ | ||
sign(data, hashAlgorithm) { | ||
@@ -373,8 +452,17 @@ const signer = PrivateKey._signers[this.oid]; | ||
} | ||
/** | ||
* Returns an ASN.1 object of this PrivateKey | ||
*/ | ||
toASN1() { | ||
return this._pkcs8; | ||
} | ||
/** | ||
* Returns an DER formatted buffer of this PrivateKey | ||
*/ | ||
toDER() { | ||
return this._pkcs8.DER; | ||
} | ||
/** | ||
* Returns an PEM formatted string of this PrivateKey | ||
*/ | ||
toPEM() { | ||
@@ -404,2 +492,5 @@ if (this._finalPEM === '') { | ||
exports.PrivateKey = PrivateKey; | ||
/** | ||
* PKCS#1 RSA Public Key | ||
*/ | ||
class RSAPublicKey extends PublicKey { | ||
@@ -425,18 +516,16 @@ static fromPublicKey(publicKey) { | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
* Returns an PKCS#1 ASN.1 object of this RSAPublicKey | ||
*/ | ||
toJSON() { | ||
return { | ||
oid: this.oid, | ||
algo: this.algo, | ||
modulus: trimLeadingZeroByte(this.modulus), | ||
exponent: this.exponent, | ||
}; | ||
} | ||
toASN1() { | ||
return this._pkcs1; | ||
} | ||
/** | ||
* Returns an PKCS#1 DER formatted buffer of this RSAPublicKey | ||
*/ | ||
toDER() { | ||
return this._keyRaw; | ||
} | ||
/** | ||
* Returns an PKCS#1 PEM formatted string of this RSAPublicKey | ||
*/ | ||
toPEM() { | ||
@@ -448,5 +537,19 @@ if (this._finalPEM === '') { | ||
} | ||
/** | ||
* Returns an PKCS#8 PEM formatted string of this RSAPublicKey | ||
*/ | ||
toPublicKeyPEM() { | ||
return new asn1_1.PEM('PUBLIC KEY', this._pkcs8.DER).toString(); | ||
} | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
*/ | ||
toJSON() { | ||
return { | ||
oid: this.oid, | ||
algo: this.algo, | ||
modulus: trimLeadingZeroByte(this.modulus), | ||
exponent: this.exponent, | ||
}; | ||
} | ||
[util_1.inspect.custom](_depth, options) { | ||
@@ -457,2 +560,5 @@ return `<${this.constructor.name} ${util_1.inspect(this.toJSON(), options)}>`; | ||
exports.RSAPublicKey = RSAPublicKey; | ||
/** | ||
* PKCS#1 RSA Private Key | ||
*/ | ||
class RSAPrivateKey extends PrivateKey { | ||
@@ -484,2 +590,29 @@ static fromPrivateKey(privateKey) { | ||
/** | ||
* Returns an PKCS#1 ASN.1 object of this RSAPrivateKey | ||
*/ | ||
toASN1() { | ||
return this._pkcs1; | ||
} | ||
/** | ||
* Returns an PKCS#1 DER formatted buffer of this RSAPrivateKey | ||
*/ | ||
toDER() { | ||
return this._keyRaw; | ||
} | ||
/** | ||
* Returns an PKCS#1 PEM formatted string of this RSAPrivateKey | ||
*/ | ||
toPEM() { | ||
if (this._finalPEM === '') { | ||
this._finalPEM = new asn1_1.PEM('RSA PRIVATE KEY', this._keyRaw).toString(); | ||
} | ||
return this._finalPEM; | ||
} | ||
/** | ||
* Returns an PKCS#8 PEM formatted string of this RSAPrivateKey | ||
*/ | ||
toPrivateKeyPEM() { | ||
return new asn1_1.PEM('PRIVATE KEY', this._pkcs8.DER).toString(); | ||
} | ||
/** | ||
* Return a friendly JSON object for debuging. | ||
@@ -502,17 +635,2 @@ */ | ||
} | ||
toASN1() { | ||
return this._pkcs1; | ||
} | ||
toDER() { | ||
return this._keyRaw; | ||
} | ||
toPEM() { | ||
if (this._finalPEM === '') { | ||
this._finalPEM = new asn1_1.PEM('RSA PRIVATE KEY', this._keyRaw).toString(); | ||
} | ||
return this._finalPEM; | ||
} | ||
toPrivateKeyPEM() { | ||
return new asn1_1.PEM('PRIVATE KEY', this._pkcs8.DER).toString(); | ||
} | ||
[util_1.inspect.custom](_depth, options) { | ||
@@ -519,0 +637,0 @@ return `<${this.constructor.name} ${util_1.inspect(this.toJSON(), options)}>`; |
/// <reference types="node" /> | ||
import { ASN1, Tag, BitString } from '@fidm/asn1'; | ||
import { PublicKey } from './pki'; | ||
/** | ||
* Attribute for X.509v3 certificate. | ||
*/ | ||
export interface Attribute { | ||
@@ -12,2 +15,5 @@ oid: string; | ||
} | ||
/** | ||
* DistinguishedName for X.509v3 certificate. | ||
*/ | ||
export declare class DistinguishedName { | ||
@@ -30,4 +36,16 @@ uniqueId: BitString | null; | ||
} | ||
/** | ||
* X.509v3 Certificate. | ||
*/ | ||
export declare class Certificate { | ||
/** | ||
* Parse one or more X.509 certificates from PEM formatted buffer. | ||
* If there is no certificate, it will throw error. | ||
* @param data PEM formatted buffer | ||
*/ | ||
static fromPEMs(data: Buffer): Certificate[]; | ||
/** | ||
* Parse an X.509 certificate from PEM formatted buffer. | ||
* @param data PEM formatted buffer | ||
*/ | ||
static fromPEM(data: Buffer): Certificate; | ||
@@ -60,6 +78,48 @@ readonly version: number; | ||
readonly tbsCertificate: ASN1; | ||
/** | ||
* Creates an X.509 certificate from an ASN.1 object | ||
* @param obj an ASN.1 object | ||
*/ | ||
constructor(obj: ASN1); | ||
/** | ||
* Gets an extension by its name or oid. | ||
* If extension exists and a key provided, it will return extension[key]. | ||
* ```js | ||
* certificate.getExtension('keyUsage') | ||
* certificate.getExtension('2.5.29.15') | ||
* // => { id: '2.5.29.15', | ||
* // critical: true, | ||
* // value: <Buffer 03 02 05 a0>, | ||
* // name: 'keyUsage', | ||
* // digitalSignature: true, | ||
* // nonRepudiation: false, | ||
* // keyEncipherment: true, | ||
* // dataEncipherment: false, | ||
* // keyAgreement: false, | ||
* // keyCertSign: false, | ||
* // cRLSign: false, | ||
* // encipherOnly: false, | ||
* // decipherOnly: false } | ||
* certificate.getExtension('keyUsage', 'keyCertSign') // => false | ||
* ``` | ||
* @param name extension name or OID | ||
* @param key key in extension | ||
*/ | ||
getExtension(name: string, key?: string): any; | ||
/** | ||
* Returns null if a subject certificate is valid, or error if invalid. | ||
* Note that it does not check validity time, DNS name, ip or others. | ||
* @param child subject's Certificate | ||
*/ | ||
checkSignature(child: Certificate): Error | null; | ||
/** | ||
* Returns true if this certificate's issuer matches the passed | ||
* certificate's subject. Note that no signature check is performed. | ||
* @param parent issuer's Certificate | ||
*/ | ||
isIssuer(parent: Certificate): boolean; | ||
/** | ||
* Verifies the subjectKeyIdentifier extension value for this certificate | ||
* against its public key. | ||
*/ | ||
verifySubjectKeyIdentifier(): boolean; | ||
@@ -66,0 +126,0 @@ /** |
@@ -158,2 +158,5 @@ 'use strict'; | ||
}; | ||
/** | ||
* DistinguishedName for X.509v3 certificate. | ||
*/ | ||
class DistinguishedName { | ||
@@ -228,5 +231,11 @@ constructor() { | ||
exports.DistinguishedName = DistinguishedName; | ||
// Creates an empty X.509v3 certificate. | ||
/** | ||
* X.509v3 Certificate. | ||
*/ | ||
class Certificate { | ||
// Parse one or more X.509 certificate from PEM format buffer. | ||
/** | ||
* Parse one or more X.509 certificates from PEM formatted buffer. | ||
* If there is no certificate, it will throw error. | ||
* @param data PEM formatted buffer | ||
*/ | ||
static fromPEMs(data) { | ||
@@ -242,3 +251,3 @@ const certs = []; | ||
if (pem.procType.includes('ENCRYPTED')) { | ||
throw new Error('Could not convert certificate from PEM; PEM is encrypted.'); | ||
throw new Error('Could not convert certificate from PEM: PEM is encrypted.'); | ||
} | ||
@@ -253,7 +262,13 @@ const obj = asn1_1.ASN1.fromDER(pem.body); | ||
} | ||
// Parse an X.509 certificate from PEM format buffer. | ||
/** | ||
* Parse an X.509 certificate from PEM formatted buffer. | ||
* @param data PEM formatted buffer | ||
*/ | ||
static fromPEM(data) { | ||
return Certificate.fromPEMs(data)[0]; | ||
} | ||
// Creates an X.509 certificate from an ASN.1 object | ||
/** | ||
* Creates an X.509 certificate from an ASN.1 object | ||
* @param obj an ASN.1 object | ||
*/ | ||
constructor(obj) { | ||
@@ -342,4 +357,26 @@ // validate certificate and capture data | ||
} | ||
// Gets an extension by its name or oid. | ||
// If extension exists and a key provided, it will return extension[key]. | ||
/** | ||
* Gets an extension by its name or oid. | ||
* If extension exists and a key provided, it will return extension[key]. | ||
* ```js | ||
* certificate.getExtension('keyUsage') | ||
* certificate.getExtension('2.5.29.15') | ||
* // => { id: '2.5.29.15', | ||
* // critical: true, | ||
* // value: <Buffer 03 02 05 a0>, | ||
* // name: 'keyUsage', | ||
* // digitalSignature: true, | ||
* // nonRepudiation: false, | ||
* // keyEncipherment: true, | ||
* // dataEncipherment: false, | ||
* // keyAgreement: false, | ||
* // keyCertSign: false, | ||
* // cRLSign: false, | ||
* // encipherOnly: false, | ||
* // decipherOnly: false } | ||
* certificate.getExtension('keyUsage', 'keyCertSign') // => false | ||
* ``` | ||
* @param name extension name or OID | ||
* @param key key in extension | ||
*/ | ||
getExtension(name, key = '') { | ||
@@ -353,4 +390,7 @@ for (const ext of this.extensions) { | ||
} | ||
// Returns null if a subject certificate is valid, or error if invalid. | ||
// Note that it does not check validity time, DNS name, ip or others. | ||
/** | ||
* Returns null if a subject certificate is valid, or error if invalid. | ||
* Note that it does not check validity time, DNS name, ip or others. | ||
* @param child subject's Certificate | ||
*/ | ||
checkSignature(child) { | ||
@@ -382,9 +422,14 @@ // RFC 5280, 4.2.1.9: | ||
} | ||
// Returns true if this certificate's issuer matches the passed | ||
// certificate's subject. Note that no signature check is performed. | ||
/** | ||
* Returns true if this certificate's issuer matches the passed | ||
* certificate's subject. Note that no signature check is performed. | ||
* @param parent issuer's Certificate | ||
*/ | ||
isIssuer(parent) { | ||
return this.issuer.getHash().equals(parent.subject.getHash()); | ||
} | ||
// Verifies the subjectKeyIdentifier extension value for this certificate | ||
// against its public key. | ||
/** | ||
* Verifies the subjectKeyIdentifier extension value for this certificate | ||
* against its public key. | ||
*/ | ||
verifySubjectKeyIdentifier() { | ||
@@ -391,0 +436,0 @@ const ski = this.publicKey.getFingerprint('sha1', 'PublicKey'); |
@@ -7,3 +7,3 @@ { | ||
], | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"main": "build/index.js", | ||
@@ -32,3 +32,3 @@ "types": "build/index.d.ts", | ||
"dependencies": { | ||
"@fidm/asn1": "^1.0.0", | ||
"@fidm/asn1": "^1.0.1", | ||
"tweetnacl": "^1.0.0" | ||
@@ -47,6 +47,7 @@ }, | ||
"scripts": { | ||
"build": "rm -rf build && tsc", | ||
"docs": "rm -rf docs && typedoc --out docs && touch docs/.nojekyll", | ||
"test": "tman -r ts-node/register 'test/**/*.ts'", | ||
"test-cov": "istanbul cover _tman -- 'test/**/*.ts' -r ts-node/register", | ||
"test": "tman -r ts-node/register 'test/**/*.ts'", | ||
"lint": "tslint -p tsconfig.json -t stylish 'src/**/*.ts' 'test/**/*.ts'", | ||
"build": "rm -rf build && tsc" | ||
"lint": "tslint -p tsconfig.json -t stylish 'src/**/*.ts' 'test/**/*.ts'" | ||
}, | ||
@@ -53,0 +54,0 @@ "files": [ |
495
README.md
@@ -1,6 +0,6 @@ | ||
# x509 | ||
# [x509](https://github.com/fidm/x509) | ||
Pure JavaScript X509 certificate tools for Node.js. | ||
[![NPM version][npm-image]][npm-url] | ||
[![Coverage Status][coveralls-image]][coveralls-url] | ||
[![Build Status][travis-image]][travis-url] | ||
[![Downloads][downloads-image]][downloads-url] | ||
@@ -11,16 +11,177 @@ | ||
## example | ||
## Install | ||
``` | ||
npm i --save @fidm/x509 | ||
``` | ||
## Documentation | ||
https://fidm.github.io/x509/ | ||
## Example | ||
### Support ed25519 certificate | ||
```js | ||
const fs = require('fs') | ||
const { Certificate, PrivateKey } = require('@fidm/x509') | ||
const ed25519Cert = Certificate.fromPEM(fs.readFileSync('./test/cert/ed25519-server-cert.pem')) | ||
const privateKey = PrivateKey.fromPEM(fs.readFileSync('./test/cert/ed25519-server-key.pem')) | ||
privateKey.setPublicKey(ed25519Cert.publicKey) | ||
const data = Buffer.allocUnsafe(100) | ||
const signature = privateKey.sign(data, 'sha256') | ||
console.log(ed25519Cert.publicKey.verify(data, signature, 'sha256')) // true | ||
``` | ||
### Parse githu.com' certificate | ||
```js | ||
const fs = require('fs') | ||
const { Certificate } = require('@fidm/x509') | ||
const issuer = Certificate.fromPEM(fs.readFileSync('./test/cert/github-issuer.crt')) | ||
const cert = Certificate.fromPEM(fs.readFileSync('./test/cert/github.crt')) | ||
console.log(cert.isIssuer(issuer)) // true | ||
console.log(issuer.verifySubjectKeyIdentifier()) // true | ||
console.log(cert.verifySubjectKeyIdentifier()) // true | ||
console.log(issuer.checkSignature(cert)) // null | ||
console.log(issuer) | ||
// <Certificate { version: 3, | ||
// serialNumber: '0c79a944b08c11952092615fe26b1d83', | ||
// signatureOID: '1.2.840.113549.1.1.11', | ||
// signatureAlgorithm: 'sha256WithRsaEncryption', | ||
// infoSignatureOID: '1.2.840.113549.1.1.11', | ||
// signature: <Buffer 9d b6 d0 90 86 e1 86 02 ed c5 a0 f0 34 1c 74 c1 8d 76 cc 86 0a a8 f0 4a 8a 42 d6 3f c8 a9 4d ad 7c 08 ad e6 b6 50 b8 a2 1a 4d 88 07 b1 29 21 dc e7 da ... >, | ||
// validFrom: '2013-10-22T12:00:00.000Z', | ||
// validTo: '2028-10-22T12:00:00.000Z', | ||
// issuer: | ||
// { C: 'US', | ||
// O: 'DigiCert Inc', | ||
// OU: 'www.digicert.com', | ||
// CN: 'DigiCert High Assurance EV Root CA', | ||
// uniqueId: null, | ||
// attributes: | ||
// [ { oid: '2.5.4.6', | ||
// value: 'US', | ||
// valueTag: 19, | ||
// name: 'countryName', | ||
// shortName: 'C' }, | ||
// { oid: '2.5.4.10', | ||
// value: 'DigiCert Inc', | ||
// valueTag: 19, | ||
// name: 'organizationName', | ||
// shortName: 'O' }, | ||
// { oid: '2.5.4.11', | ||
// value: 'www.digicert.com', | ||
// valueTag: 19, | ||
// name: 'organizationalUnitName', | ||
// shortName: 'OU' }, | ||
// { oid: '2.5.4.3', | ||
// value: 'DigiCert High Assurance EV Root CA', | ||
// valueTag: 19, | ||
// name: 'commonName', | ||
// shortName: 'CN' } ] }, | ||
// subject: | ||
// { C: 'US', | ||
// O: 'DigiCert Inc', | ||
// OU: 'www.digicert.com', | ||
// CN: 'DigiCert SHA2 Extended Validation Server CA', | ||
// uniqueId: null, | ||
// attributes: | ||
// [ { oid: '2.5.4.6', | ||
// value: 'US', | ||
// valueTag: 19, | ||
// name: 'countryName', | ||
// shortName: 'C' }, | ||
// { oid: '2.5.4.10', | ||
// value: 'DigiCert Inc', | ||
// valueTag: 19, | ||
// name: 'organizationName', | ||
// shortName: 'O' }, | ||
// { oid: '2.5.4.11', | ||
// value: 'www.digicert.com', | ||
// valueTag: 19, | ||
// name: 'organizationalUnitName', | ||
// shortName: 'OU' }, | ||
// { oid: '2.5.4.3', | ||
// value: 'DigiCert SHA2 Extended Validation Server CA', | ||
// valueTag: 19, | ||
// name: 'commonName', | ||
// shortName: 'CN' } ] }, | ||
// extensions: | ||
// [ { id: '2.5.29.19', | ||
// critical: true, | ||
// value: <Buffer 30 06 01 01 ff 02 01 00>, | ||
// name: 'basicConstraints', | ||
// isCA: true, | ||
// maxPathLen: 0, | ||
// basicConstraintsValid: true }, | ||
// { id: '2.5.29.15', | ||
// critical: true, | ||
// value: <Buffer 03 02 01 86>, | ||
// name: 'keyUsage', | ||
// keyUsage: 97, | ||
// digitalSignature: true, | ||
// nonRepudiation: false, | ||
// keyEncipherment: false, | ||
// dataEncipherment: false, | ||
// keyAgreement: false, | ||
// keyCertSign: true, | ||
// cRLSign: true, | ||
// encipherOnly: false, | ||
// decipherOnly: false }, | ||
// { id: '2.5.29.37', | ||
// critical: false, | ||
// value: <Buffer 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02>, | ||
// name: 'extKeyUsage', | ||
// serverAuth: true, | ||
// clientAuth: true }, | ||
// { id: '1.3.6.1.5.5.7.1.1', | ||
// critical: false, | ||
// value: <Buffer 30 26 30 24 06 08 2b 06 01 05 05 07 30 01 86 18 68 74 74 70 3a 2f 2f 6f 63 73 70 2e 64 69 67 69 63 65 72 74 2e 63 6f 6d>, | ||
// name: 'authorityInfoAccess', | ||
// authorityInfoAccessOcsp: 'http://ocsp.digicert.com' }, | ||
// { id: '2.5.29.31', | ||
// critical: false, | ||
// value: <Buffer 30 42 30 40 a0 3e a0 3c 86 3a 68 74 74 70 3a 2f 2f 63 72 6c 34 2e 64 69 67 69 63 65 72 74 2e 63 6f 6d 2f 44 69 67 69 43 65 72 74 48 69 67 68 41 73 73 ... >, | ||
// name: 'cRLDistributionPoints' }, | ||
// { id: '2.5.29.32', | ||
// critical: false, | ||
// value: <Buffer 30 34 30 32 06 04 55 1d 20 00 30 2a 30 28 06 08 2b 06 01 05 05 07 02 01 16 1c 68 74 74 70 73 3a 2f 2f 77 77 77 2e 64 69 67 69 63 65 72 74 2e 63 6f 6d ... >, | ||
// name: 'certificatePolicies' }, | ||
// { id: '2.5.29.14', | ||
// critical: false, | ||
// value: <Buffer 04 14 3d d3 50 a5 d6 a0 ad ee f3 4a 60 0a 65 d3 21 d4 f8 f8 d6 0f>, | ||
// name: 'subjectKeyIdentifier', | ||
// subjectKeyIdentifier: '3dd350a5d6a0adeef34a600a65d321d4f8f8d60f' }, | ||
// { id: '2.5.29.35', | ||
// critical: false, | ||
// value: <Buffer 30 16 80 14 b1 3e c3 69 03 f8 bf 47 01 d4 98 26 1a 08 02 ef 63 64 2b c3>, | ||
// name: 'authorityKeyIdentifier', | ||
// authorityKeyIdentifier: 'b13ec36903f8bf4701d498261a0802ef63642bc3' } ], | ||
// subjectKeyIdentifier: '3dd350a5d6a0adeef34a600a65d321d4f8f8d60f', | ||
// authorityKeyIdentifier: 'b13ec36903f8bf4701d498261a0802ef63642bc3', | ||
// ocspServer: 'http://ocsp.digicert.com', | ||
// issuingCertificateURL: '', | ||
// isCA: true, | ||
// maxPathLen: 0, | ||
// basicConstraintsValid: true, | ||
// keyUsage: 97, | ||
// dnsNames: [], | ||
// emailAddresses: [], | ||
// ipAddresses: [], | ||
// uris: [], | ||
// publicKey: | ||
// { oid: '1.2.840.113549.1.1.1', | ||
// algo: 'rsaEncryption', | ||
// publicKey: <Buffer 30 82 01 0a 02 82 01 01 00 d7 53 a4 04 51 f8 99 a6 16 48 4b 67 27 aa 93 49 d0 39 ed 0c b0 b0 00 87 f1 67 28 86 85 8c 8e 63 da bc b1 40 38 e2 d3 f5 ec ... > }, | ||
// publicKeyRaw: <Buffer 30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 82 01 0f 00 30 82 01 0a 02 82 01 01 00 d7 53 a4 04 51 f8 99 a6 16 48 4b 67 27 aa 93 49 d0 ... > }> | ||
const cert = Certificate.fromPEM(fs.readFileSync('./test/cert/github.crt')) | ||
console.log(cert) | ||
// <Certificate { version: 2, | ||
// <Certificate { version: 3, | ||
// serialNumber: '0a0630427f5bbced6957396593b6451f', | ||
// signatureOID: '1.2.840.113549.1.1.11', | ||
// signatureAlgorithm: 'sha256WithRSAEncryption', | ||
// signatureParameters: null, | ||
// siginfo: { algorithmOID: '1.2.840.113549.1.1.11' }, | ||
// signatureAlgorithm: 'sha256WithRsaEncryption', | ||
// infoSignatureOID: '1.2.840.113549.1.1.11', | ||
// signature: <Buffer 70 0f 5a 96 a7 58 e5 bf 8a 9d a8 27 98 2b 00 7f 26 a9 07 da ba 7b 82 54 4f af 69 cf bc f2 59 03 2b f2 d5 74 58 25 d8 1e a4 20 76 62 60 29 73 2a d7 dc ... >, | ||
@@ -135,2 +296,3 @@ // validFrom: '2018-05-08T00:00:00.000Z', | ||
// name: 'keyUsage', | ||
// keyUsage: 5, | ||
// digitalSignature: true, | ||
@@ -183,2 +345,3 @@ // nonRepudiation: false, | ||
// basicConstraintsValid: true, | ||
// keyUsage: 5, | ||
// dnsNames: [ 'github.com', 'www.github.com' ], | ||
@@ -189,314 +352,8 @@ // emailAddresses: [], | ||
// publicKey: | ||
// { n: 'c63caaf23c970c3ac14f28ad72707dd3ceb9b56073a4749b8a7746fd7a98424cc53019579aa9330be15d4d1058ca7799c393f3f97590bcbfbbe095ba2ec58d736105d31084a8b389b82f738cf02a6ebeeeae834b8211b161fd7761da9b1b9a23ff8c7ea20106ddd17f539608c15afae7c0cac8448c57a7a8615f660d57d3b896acb64a9cc1eae8fb964029f61530b504b0cc05b684c32459957fa26590e5b0b31a7559c43f31140ad5ccaa3a8505520632960761df27820cf785db6031f00950c5b71a23e1b07d02f5141ec9cbe87e2a3304f6513f529815e90b76475c4d4a6bc50815aef8d157e9ea7014ffc945b90c7cbcf46de60552f98c80bb7056910f4b', | ||
// e: 65537 }, | ||
// { oid: '1.2.840.113549.1.1.1', | ||
// algo: 'rsaEncryption', | ||
// publicKey: <Buffer 30 82 01 0a 02 82 01 01 00 c6 3c aa f2 3c 97 0c 3a c1 4f 28 ad 72 70 7d d3 ce b9 b5 60 73 a4 74 9b 8a 77 46 fd 7a 98 42 4c c5 30 19 57 9a a9 33 0b e1 ... > }, | ||
// publicKeyRaw: <Buffer 30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 82 01 0f 00 30 82 01 0a 02 82 01 01 00 c6 3c aa f2 3c 97 0c 3a c1 4f 28 ad 72 70 7d d3 ce ... > }> | ||
``` | ||
## API | ||
### Class: Certificate | ||
```js | ||
const { Certificate } = require('@fidm/x509') | ||
``` | ||
#### Certificate.fromPEMs(data: Buffer) => Certificate[] | ||
Parse one or more X.509 certificate from PEM format buffer. | ||
#### Certificate.fromPEM(data: Buffer) => Certificate | ||
Parse an X.509 certificate from PEM format buffer. | ||
#### new Certificate(obj: ASN1) | ||
Creates an X.509 certificate from an ASN.1 object. | ||
#### certificate.version: number | ||
#### certificate.serialNumber: string | ||
#### certificate.signatureOID: string | ||
#### certificate.signatureAlgorithm: string | ||
#### certificate.infoSignatureOID: string | ||
#### certificate.signature: Buffer | ||
#### certificate.subjectKeyIdentifier: string | ||
#### certificate.authorityKeyIdentifier: string | ||
#### certificate.ocspServer: string | ||
#### certificate.issuingCertificateURL: string | ||
#### certificate.isCA: boolean | ||
#### certificate.maxPathLen: number | ||
#### certificate.basicConstraintsValid: boolean | ||
#### certificate.keyUsage: number | ||
#### certificate.dnsNames: string[] | ||
#### certificate.emailAddresses: string[] | ||
#### certificate.ipAddresses: string[] | ||
#### certificate.uris: string[] | ||
#### certificate.validFrom: Date | ||
#### certificate.validTo: Date | ||
#### certificate.issuer: DistinguishedName | ||
#### certificate.subject: DistinguishedName | ||
#### certificate.extensions: Extension[] | ||
#### certificate.publicKey: PublicKey | ||
#### certificate.publicKeyRaw: Buffer | null | ||
#### certificate.tbsCertificate: ASN1 | ||
#### certificate.getExtension(name: string, key: string = '') => any | ||
Gets an extension by its name or oid. If extension exists and a key provided, it will return extension[key]. | ||
```js | ||
certificate.getExtension('keyUsage') | ||
certificate.getExtension('2.5.29.15') | ||
// => { id: '2.5.29.15', | ||
// critical: true, | ||
// value: <Buffer 03 02 05 a0>, | ||
// name: 'keyUsage', | ||
// digitalSignature: true, | ||
// nonRepudiation: false, | ||
// keyEncipherment: true, | ||
// dataEncipherment: false, | ||
// keyAgreement: false, | ||
// keyCertSign: false, | ||
// cRLSign: false, | ||
// encipherOnly: false, | ||
// decipherOnly: false } | ||
certificate.getExtension('keyUsage', 'keyCertSign') // => false | ||
``` | ||
#### certificate.checkSignature(child: Certificate) => Error | null | ||
Returns null if a subject certificate is valid, or error if invalid. | ||
Note that it does not check validity time, DNS name, ip or others. | ||
```js | ||
someRootCA.checkSignature(someCert) // => null or error | ||
``` | ||
#### certificate.isIssuer(parent: Certificate) => boolean | ||
Returns true if this certificate's issuer matches the passed certificate's subject. Note that no signature check is performed. | ||
#### certificate.verifySubjectKeyIdentifier() => boolean | ||
Verifies the subjectKeyIdentifier extension value for this certificate against it's public key. | ||
#### certificate.toJSON() => any | ||
---------- | ||
### Class: DistinguishedName | ||
```js | ||
const { DistinguishedName } = require('@fidm/x509') | ||
``` | ||
#### distinguishedName.commonName: string | ||
#### distinguishedName.organizationName: string | ||
#### distinguishedName.organizationalUnitName: string | ||
#### distinguishedName.countryName: string | ||
#### distinguishedName.localityName: string | ||
#### distinguishedName.serialName: string | ||
#### distinguishedName.getHash() => Buffer | ||
#### distinguishedName.getField(key: string) => Attribute | null | ||
#### distinguishedName.toJSON() => any | ||
---------- | ||
### Class: PublicKey | ||
```js | ||
const { PublicKey } = require('@fidm/x509') | ||
``` | ||
#### PublicKey.fromPEM(pem: Buffer) => PublicKey | ||
Parse an PublicKey for X.509 certificate from PKCS#8 PEM format buffer or PKCS#1 RSA PEM format buffer. | ||
#### PublicKey.addVerifier(oid: string, fn: Verifier) | ||
Registers an external Verifier with object identifier. | ||
Built-in verifiers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_verify | ||
```js | ||
PublicKey.addVerifier(getOID('Ed25519'), function (this: PublicKey, data: Buffer, signature: Buffer): boolean { | ||
return ed25519.detached.verify(data, signature, this.keyRaw) | ||
}) | ||
``` | ||
#### new PublicKey(obj: ASN1) | ||
#### publicKey.oid: string | ||
#### publicKey.algo: string | ||
#### publicKey.keyRaw: Buffer | ||
#### publicKey.verify(data: Buffer, signature: Buffer, hashAlgorithm: string) => boolean | ||
Returns true if the provided data and the given signature matched. | ||
```js | ||
certificate.publicKey.verify(data, signature, 'sha256') // => true or false | ||
``` | ||
#### publicKey.getFingerprint(hashAlgorithm: string, type: string = 'PublicKey') => Buffer | ||
Returns the digest of the public key with given hash algorithm. `type` should be `'PublicKey'` (for PKCS#1) or `'PublicKeyInfo'` (for PKCS#1). | ||
```js | ||
certificate.publicKey.getFingerprint('sha1', 'PublicKey') // => Buffer | ||
``` | ||
#### publicKey.toASN1() => ASN1 | ||
#### publicKey.toDER() => Buffer | ||
#### publicKey.toPEM() => string | ||
#### publicKey.toJSON() => any | ||
---------- | ||
### Class: PrivateKey | ||
```js | ||
const { PrivateKey } = require('@fidm/x509') | ||
``` | ||
#### PrivateKey.fromPEM(pem: Buffer) => PrivateKey | ||
Parse an PrivateKey for X.509 certificate from PKCS#8 PEM format buffer or PKCS#1 RSA PEM format buffer. | ||
#### PrivateKey.addSigner (oid: string, fn: Signer) | ||
Registers an external Signer with object identifier. | ||
Built-in signers: Ed25519, RSA, others see https://nodejs.org/api/crypto.html#crypto_class_sign | ||
```js | ||
PrivateKey.addSigner(getOID('Ed25519'), function (this: PrivateKey, data: Buffer): Buffer { | ||
const key = this.keyRaw | ||
if (key.length !== 64) { | ||
throw new Error('Invalid signing key, should setPublicKeyRaw before sign.') | ||
} | ||
return Buffer.from(ed25519.detached(data, key)) | ||
}) | ||
``` | ||
#### new PrivateKey(obj: ASN1) | ||
#### privateKey.version: number | ||
#### privateKey.oid: string | ||
#### privateKey.algo: string | ||
#### privateKey.keyRaw: Buffer | ||
#### privateKey.publicKeyRaw: Buffer | ||
Returns publicKey buffer, it is used for Ed25519/Ed448. If publicKeyRaw not exists, an error will be thrown. | ||
#### privateKey.setPublicKey(key: PublicKey) | ||
Sets an PublicKey into PrivateKey. It is used for Ed25519/Ed448. If oid not matched, an error will be thrown. | ||
```js | ||
const cert = Certificate.fromPEM(fs.readFileSync('./test/cert/ed25519-server-cert.pem')) | ||
const privateKey = PrivateKey.fromPEM(fs.readFileSync('./test/cert/ed25519-server-key.pem')) | ||
privateKey.setPublicKey(cert.publicKey) | ||
const signature = privateKey.sign(data, 'sha256') | ||
cert.publicKey.verify(data, signature, 'sha256') // => true | ||
``` | ||
#### privateKey.sign(data: Buffer, hashAlgorithm: string) => Buffer | ||
Returns signature for the given data and hash algorithm. | ||
#### privateKey.toASN1() => ASN1 | ||
#### privateKey.toDER() => Buffer | ||
#### privateKey.toPEM() => string | ||
#### privateKey.toJSON() => any | ||
---------- | ||
### Class: RSAPublicKey extends PublicKey | ||
```js | ||
const { RSAPublicKey } = require('@fidm/x509') | ||
``` | ||
#### RSAPublicKey.fromPublicKey(publicKey: PublicKey) => RSAPublicKey | ||
#### rsaPublicKey.exponent: number | ||
#### rsaPublicKey.modulus: string | ||
#### rsaPublicKey.toPublicKeyPEM (): string | ||
---------- | ||
### Class: RSAPrivateKey extends PrivateKey | ||
```js | ||
const { RSAPrivateKey } = require('@fidm/x509') | ||
``` | ||
#### RSAPrivateKey.fromPrivateKey(privateKey: PrivateKey): RSAPrivateKey | ||
#### rsaPublicKey.publicExponent: number | ||
#### rsaPrivateKey.privateExponent: string | ||
#### rsaPrivateKey.modulus: string | ||
#### rsaPrivateKey.prime1: string | ||
#### rsaPrivateKey.prime2: string | ||
#### rsaPrivateKey.exponent1: string | ||
#### rsaPrivateKey.exponent2: string | ||
#### rsaPrivateKey.coefficient: string | ||
#### rsaPrivateKey.toPrivateKeyPEM (): string | ||
---------- | ||
### Others | ||
```js | ||
const { bytesFromIP, bytesToIP, getOID, getOIDName } = require('@fidm/x509') | ||
``` | ||
#### function bytesFromIP (ip: string) => Buffer | null | ||
#### function bytesToIP (bytes: Buffer) => string | ||
#### function getOID (nameOrId: string) => string | ||
#### function getOIDName (nameOrId: string) => string | ||
---------- | ||
### License | ||
@@ -509,6 +366,6 @@ @fidm/x509 is licensed under the [MIT](https://github.com/fidm/x509/blob/master/LICENSE) license. | ||
[coveralls-url]: https://coveralls.io/r/fidm/x509 | ||
[coveralls-image]: https://coveralls.io/repos/fidm/x509/badge.svg | ||
[travis-url]: https://travis-ci.org/fidm/x509 | ||
[travis-image]: http://img.shields.io/travis/fidm/x509.svg | ||
[downloads-url]: https://npmjs.org/package/@fidm/x509 | ||
[downloads-image]: https://img.shields.io/npm/dm/@fidm/x509.svg?style=flat-square |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
138140
2079
367
Updated@fidm/asn1@^1.0.1