UNPKG

@trust/keyto

Version:

A utility for translating cryptographic keys between representations

231 lines (191 loc) 5.21 kB
'use strict' /** * Dependencies * @ignore */ const bignum = require('asn1.js').bignum const EC = require('elliptic').ec const ec = new EC('secp256k1') /** * Module Dependencies * @ignore */ const KeyType = require('./KeyType') const InvalidOperationError = require('../InvalidOperationError') const Converter = require('../Converter') const asn = require('../asn1') /** * ECDSA * @class ECDSA * * @extends {KeyType} * * @description * ECDSA conversion implementation */ class ECDSA extends KeyType { /** * IMPORT * @ignore */ fromPrivatePKCS1 (key) { let ECPrivateKey = asn.normalize('ECPrivateKey') let data = ECPrivateKey.decode(key, 'der') let { privateKey: d, publicKey: { data: publicKey } } = data let hexPoint = Converter.convert(publicKey, 'raw', 'hex') let { x, y } = ECDSA.getPoint(hexPoint) return { d, x, y } } fromPrivatePKCS8 (key) { let PrivateKeyInfo = asn.normalize('PrivateKeyInfo') let ECPrivateKey = asn.normalize('ECPrivateKey') let info = PrivateKeyInfo.decode(key, 'der') let data = ECPrivateKey.decode(info.privateKey, 'der') let { privateKey: d, publicKey: { data: publicKey } } = data let hexPoint = Converter.convert(publicKey, 'raw', 'hex') let { x, y } = ECDSA.getPoint(hexPoint) return { d, x, y } } fromPublicPKCS8 (key) { let PublicKeyInfo = asn.normalize('PublicKeyInfo') let info = PublicKeyInfo.decode(key, 'der') let hexPoint = Converter.convert(info.publicKey.data, 'raw', 'hex') return ECDSA.getPoint(hexPoint) } fromPrivateBlk (key) { let privateKey = ec.keyFromPrivate(key, 'hex') let publicKey = privateKey.getPublic() return { d: Converter.convert(privateKey.priv, 'bn', 'raw'), x: Converter.convert(publicKey.getX(), 'bn', 'raw'), y: Converter.convert(publicKey.getY(), 'bn', 'raw'), } } fromPublicBlk (key) { return ECDSA.getPoint(key) } fromJwk (key) { let { d, x, y } = key return { d: Converter.convert(d, 'base64url', 'raw'), x: Converter.convert(x, 'base64url', 'raw'), y: Converter.convert(y, 'base64url', 'raw'), } } /** * EXPORT * @ignore */ toPrivatePKCS1 (key) { let { namedCurve, keyVersion: version } = this.params let { d, x, y } = key let ECPrivateKey = asn.normalize('ECPrivateKey') let publicKey = ECDSA.makePoint(x, y) let base64pem = ECPrivateKey.encode({ version, privateKey: d, parameters: { type: 'namedCurve', value: namedCurve.split('.') }, publicKey: { unused: 0, data: publicKey } }, 'der').toString('base64') return ECDSA.formatPem(base64pem, 'EC PRIVATE') } toPrivatePKCS8 (key) { let { oid, algParameters, keyVersion: version, infoVersion } = this.params let { d, x, y } = key let PrivateKeyInfo = asn.normalize('PrivateKeyInfo') let ECPrivateKey = asn.normalize('ECPrivateKey') let publicKey = ECDSA.makePoint(x, y) let privateKey = ECPrivateKey.encode({ version, privateKey: d, publicKey: { unused: 0, data: publicKey } }, 'der') let base64pem = PrivateKeyInfo.encode({ version: infoVersion, algorithm: { algorithm: oid.split('.'), parameters: Buffer.from(algParameters, 'hex') }, privateKey }, 'der').toString('base64') return ECDSA.formatPem(base64pem, 'PRIVATE') } toPublicPKCS8 (key) { let { oid, algParameters } = this.params let { x, y } = key let PublicKeyInfo = asn.normalize('PublicKeyInfo') let publicKey = ECDSA.makePoint(x, y) let base64pem = PublicKeyInfo.encode({ algorithm: { algorithm: oid.split('.'), parameters: Buffer.from(algParameters, 'hex') }, publicKey: { unused: 0, data: publicKey } }, 'der').toString('base64') return ECDSA.formatPem(base64pem, 'PUBLIC') } toPrivateBlk (key) { return key.d.toString('hex') } toPublicBlk (key) { return Converter.convert(ECDSA.makePoint(key.x, key.y), 'raw', 'hex') } toPrivateJwk (key) { let { crv, kty } = this.params let { d, x, y } = key return { kty, crv, d: Converter.convert(d, 'raw', 'base64url'), x: Converter.convert(x, 'raw', 'base64url'), y: Converter.convert(y, 'raw', 'base64url'), } } toPublicJwk (key) { let { crv, kty } = this.params let { x, y } = key return { kty, crv, x: Converter.convert(x, 'raw', 'base64url'), y: Converter.convert(y, 'raw', 'base64url'), } } /** * HELPERS * @ignore */ static getPoint (point) { let x = point.slice(2, ((point.length - 2) / 2) + 2) let y = point.slice(((point.length - 2) / 2) + 2) return { x: Converter.convert(x, 'hex', 'raw'), y: Converter.convert(y, 'hex', 'raw'), } } static makePoint (x, y) { let startBuffer = Buffer.from('04', 'hex') return Buffer.concat([ startBuffer, x, y ], startBuffer.length + x.length + y.length) } } /** * Export * @ignore */ module.exports = ECDSA