rsa-key
Version:
Converts between RSA key formats, detecting input format (PEM, DER, PKCS1, PKCS8). No OpenSSL needed.
225 lines (191 loc) • 10.6 kB
JavaScript
const { BASE64, PRIVATE, PUBLIC, PKCS1, PKCS8, UTF8 } = require('../src/constants');
const NodeRSA = require('node-rsa');
const pem = require('../src/formats/pem');
const { assert } = require('chai');
const RSAKeyError = require('../src/error');
const { get32IntFromBuffer } = require('../src/util');
describe('Format: PEM', function() {
describe('testPEM', function() {
let testKey;
before(function() {
testKey = new NodeRSA({ b: 256 });
});
it('should detect private PKCS8 PEM key', function() {
const testPEM = testKey.exportKey('pkcs8-private-pem');
const testDER = testKey.exportKey('pkcs8-private-der').toString(BASE64);
const info = pem.testPEM(testPEM);
assert.isObject(info, 'result should be an object');
assert.isNotNull(info, 'result hsould not be null');
assert.equal(info.type, PRIVATE, 'key type should match');
assert.equal(info.syntax, PKCS8, 'key syntax should match');
assert.equal(info.der, testDER, 'DER key should match');
});
it('should detect public PKCS8 PEM key', function() {
const testPEM = testKey.exportKey('pkcs8-public-pem');
const testDER = testKey.exportKey('pkcs8-public-der').toString(BASE64);
const info = pem.testPEM(testPEM);
assert.isObject(info, 'result should be an object');
assert.isNotNull(info, 'result hsould not be null');
assert.equal(info.type, PUBLIC, 'key type should match');
assert.equal(info.syntax, PKCS8, 'key syntax should match');
assert.equal(info.der, testDER, 'DER key should match');
});
it('should detect private PKCS1 PEM key', function() {
const testPEM = testKey.exportKey('pkcs1-private-pem');
const testDER = testKey.exportKey('pkcs1-private-der').toString(BASE64);
const info = pem.testPEM(testPEM);
assert.isObject(info, 'result should be an object');
assert.isNotNull(info, 'result hsould not be null');
assert.equal(info.type, PRIVATE, 'key type should match');
assert.equal(info.syntax, PKCS1, 'key syntax should match');
assert.equal(info.der, testDER, 'DER key should match');
});
it('should detect public PKCS1 PEM key', function() {
const testPEM = testKey.exportKey('pkcs1-public-pem');
const testDER = testKey.exportKey('pkcs1-public-der').toString(BASE64);
const info = pem.testPEM(testPEM);
assert.isObject(info, 'result should be an object');
assert.isNotNull(info, 'result hsould not be null');
assert.equal(info.type, PUBLIC, 'key type should match');
assert.equal(info.syntax, PKCS1, 'key syntax should match');
assert.equal(info.der, testDER, 'DER key should match');
});
it('should return null for non-PEM input', function() {
const testPEM = testKey.exportKey('pkcs1-public-der').toString(BASE64);
const info = pem.testPEM(testPEM);
assert.isNull(info);
});
it('should work with key provided in a buffer', function() {
const testPEM = testKey.exportKey('pkcs1-public-pem');
const testDER = testKey.exportKey('pkcs1-public-der').toString(BASE64);
const info = pem.testPEM(Buffer.from(testPEM, UTF8));
assert.isObject(info, 'result should be an object');
assert.isNotNull(info, 'result hsould not be null');
assert.equal(info.type, PUBLIC, 'key type should match');
assert.equal(info.syntax, PKCS1, 'key syntax should match');
assert.equal(info.der, testDER, 'DER key should match');
});
it('should fail if non-string input', function() {
assert.throws(() => {
pem.decodePEM([]);
}, RSAKeyError);
});
});
describe('decodePEM', function() {
let testKey, testComponents;
before(function() {
testKey = new NodeRSA({ b: 256 });
testComponents = testKey.exportKey('components');
});
it('should decode private PKCS8 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs8-private-pem');
const decoded = pem.decodePEM(testEncoded);
assert.isObject(decoded, 'should return an object');
assert.equal(decoded.n, testComponents.n.toString(BASE64), 'decoded modulus should match original');
assert.equal(get32IntFromBuffer(Buffer.from(decoded.e, BASE64)), testComponents.e,
'decoded public exponent should match original');
assert.equal(decoded.d, testComponents.d.toString(BASE64), 'decoded private exponent should match');
assert.equal(decoded.p, testComponents.p.toString(BASE64), 'decoded prime1 should match');
assert.equal(decoded.q, testComponents.q.toString(BASE64), 'decoded prime2 should match');
assert.equal(decoded.dp, testComponents.dmp1.toString(BASE64), 'decoded exponent1 should match');
assert.equal(decoded.dq, testComponents.dmq1.toString(BASE64), 'decoded exponent2 should match');
assert.equal(decoded.qi, testComponents.coeff.toString(BASE64), 'decoded coefficient should match');
});
it('should decode public PKCS8 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs8-public-pem');
const decoded = pem.decodePEM(testEncoded);
assert.isObject(decoded, 'should return an object');
assert.equal(decoded.n, testComponents.n.toString(BASE64), 'decoded modulus should match original');
assert.equal(get32IntFromBuffer(Buffer.from(decoded.e, BASE64)), testComponents.e,
'decoded public exponent should match original');
});
it('should decode private PKCS1 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs1-private-pem');
const decoded = pem.decodePEM(testEncoded);
assert.isObject(decoded, 'should return an object');
assert.equal(decoded.n, testComponents.n.toString(BASE64), 'decoded modulus should match original');
assert.equal(get32IntFromBuffer(Buffer.from(decoded.e, BASE64)), testComponents.e,
'decoded public exponent should match original');
assert.equal(decoded.d, testComponents.d.toString(BASE64), 'decoded private exponent should match');
assert.equal(decoded.p, testComponents.p.toString(BASE64), 'decoded prime1 should match');
assert.equal(decoded.q, testComponents.q.toString(BASE64), 'decoded prime2 should match');
assert.equal(decoded.dp, testComponents.dmp1.toString(BASE64), 'decoded exponent1 should match');
assert.equal(decoded.dq, testComponents.dmq1.toString(BASE64), 'decoded exponent2 should match');
assert.equal(decoded.qi, testComponents.coeff.toString(BASE64), 'decoded coefficient should match');
});
it('should decode public PKCS1 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs1-public-pem');
const decoded = pem.decodePEM(testEncoded);
assert.isObject(decoded, 'should return an object');
assert.equal(decoded.n, testComponents.n.toString(BASE64), 'decoded modulus should match original');
assert.equal(get32IntFromBuffer(Buffer.from(decoded.e, BASE64)), testComponents.e,
'decoded public exponent should match original');
});
it('should work with info provided', function() {
const testEncoded = testKey.exportKey('pkcs1-public-pem');
const info = pem.testPEM(testEncoded);
const decoded = pem.decodePEM(testEncoded, info);
assert.isObject(decoded, 'should return an object');
assert.equal(decoded.n, testComponents.n.toString(BASE64), 'decoded modulus should match original');
assert.equal(get32IntFromBuffer(Buffer.from(decoded.e, BASE64)), testComponents.e,
'decoded public exponent should match original');
});
it('should fail if non-PEM key was provided', function() {
assert.throws(() => {
const testEncoded = testKey.exportKey('pkcs1-public-der').toString('base64');
pem.decodePEM(testEncoded);
}, RSAKeyError);
});
it('should work with key provided in a buffer', function() {
const testEncoded = testKey.exportKey('pkcs1-private-pem');
const decoded = pem.decodePEM(Buffer.from(testEncoded, UTF8));
assert.isObject(decoded, 'should return an object');
assert.equal(decoded.n, testComponents.n.toString(BASE64), 'decoded modulus should match original');
assert.equal(get32IntFromBuffer(Buffer.from(decoded.e, BASE64)), testComponents.e,
'decoded public exponent should match original');
assert.equal(decoded.d, testComponents.d.toString(BASE64), 'decoded private exponent should match');
assert.equal(decoded.p, testComponents.p.toString(BASE64), 'decoded prime1 should match');
assert.equal(decoded.q, testComponents.q.toString(BASE64), 'decoded prime2 should match');
assert.equal(decoded.dp, testComponents.dmp1.toString(BASE64), 'decoded exponent1 should match');
assert.equal(decoded.dq, testComponents.dmq1.toString(BASE64), 'decoded exponent2 should match');
assert.equal(decoded.qi, testComponents.coeff.toString(BASE64), 'decoded coefficient should match');
});
});
describe('encodePEM', function() {
let testKey, testDecoded;
before(function() {
testKey = new NodeRSA({ b: 256 });
testDecoded = pem.decodePEM(testKey.exportKey('pkcs8-private-pem'));
});
it('should encode private PKCS8 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs8-private-pem');
const encoded = pem.encodePEM(testDecoded, PRIVATE, PKCS8);
assert.equal(encoded, testEncoded);
});
it('should encode public PKCS8 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs8-public-pem');
const encoded = pem.encodePEM(testDecoded, PUBLIC, PKCS8);
assert.equal(encoded, testEncoded);
});
it('should encode private PKCS1 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs1-private-pem');
const encoded = pem.encodePEM(testDecoded, PRIVATE, PKCS1);
assert.equal(encoded, testEncoded);
});
it('should encode public PKCS1 PEM key', function() {
const testEncoded = testKey.exportKey('pkcs1-public-pem');
const encoded = pem.encodePEM(testDecoded, PUBLIC, PKCS1);
assert.equal(encoded, testEncoded);
});
it('should fail if unknown type was specified', function() {
assert.throws(() => {
pem.encodePEM(testDecoded, 'clearly-unknown-type', PKCS1);
}, RSAKeyError);
});
it('should fail if unknown syntax was specified', function() {
assert.throws(() => {
pem.encodePEM(testDecoded, PRIVATE, 'clearly-unknown-syntax');
}, RSAKeyError);
});
});
});