rsa-key
Version:
Converts between RSA key formats, detecting input format (PEM, DER, PKCS1, PKCS8). No OpenSSL needed.
166 lines (136 loc) • 6.99 kB
JavaScript
const { assert } = require('chai');
const { BASE64 } = require('../src/constants');
const NodeRSA = require('node-rsa');
const pkcs1 = require('../src/formats/pkcs1');
const RSAKeyError = require('../src/error');
const { get32IntFromBuffer } = require('../src/util');
describe('Format: PKCS1', function() {
describe('decodePrivatePKCS1DER', function() {
let testKey, testComponents;
before(function() {
testKey = new NodeRSA({ b: 256 });
testComponents = testKey.exportKey('components');
});
it('should decode private PKCS1 DER key', function() {
const testEncoded = testKey.exportKey('pkcs1-private-der');
const decoded = pkcs1.decodePrivatePKCS1DER(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 fail with public PKCS1 DER key', function() {
assert.throws(() => {
pkcs1.decodePrivatePKCS1DER(testKey.exportKey('pkcs1-public-der'));
}, RSAKeyError);
});
it('should fail with private PKCS8 DER key', function() {
assert.throws(() => {
pkcs1.decodePrivatePKCS1DER(testKey.exportKey('pkcs8-private-der'));
}, RSAKeyError);
});
it('should fail with public PKCS8 DER key', function() {
assert.throws(() => {
pkcs1.decodePrivatePKCS1DER(testKey.exportKey('pkcs8-public-der'));
}, RSAKeyError);
});
it('should fail with non-DER key', function() {
assert.throws(() => {
pkcs1.decodePrivatePKCS1DER(testKey.exportKey('pkcs8-public-pem'));
}, RSAKeyError);
});
});
describe('decodePublicPKCS1DER', function() {
let testKey, testComponents;
before(function() {
testKey = new NodeRSA({ b: 256 });
testComponents = testKey.exportKey('components');
});
it('should decode public PKCS1 DER key', function() {
const testEncoded = testKey.exportKey('pkcs1-public-der');
const decoded = pkcs1.decodePublicPKCS1DER(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 also decode private PKCS1 DER key', function() {
const testEncoded = testKey.exportKey('pkcs1-private-der');
const decoded = pkcs1.decodePublicPKCS1DER(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.isUndefined(decoded.d, 'should not include private exponent');
assert.isUndefined(decoded.p, 'should not include prime1');
assert.isUndefined(decoded.q, 'should not include prime2');
assert.isUndefined(decoded.d, 'should not include exponent1');
assert.isUndefined(decoded.d, 'should not include exponent2');
assert.isUndefined(decoded.qi, 'should not include coefficient');
});
it('should fail with private PKCS8 DER key', function() {
assert.throws(() => {
pkcs1.decodePublicPKCS1DER(testKey.exportKey('pkcs8-private-der'));
}, RSAKeyError);
});
it('should fail with public PKCS8 DER key', function() {
assert.throws(() => {
pkcs1.decodePublicPKCS1DER(testKey.exportKey('pkcs8-public-der'));
}, RSAKeyError);
});
it('should fail with non-DER key', function() {
assert.throws(() => {
pkcs1.decodePublicPKCS1DER(testKey.exportKey('pkcs8-public-pem'));
}, RSAKeyError);
});
});
describe('encodePrivatePKCS1DER', function() {
it('should encode private PKCS1 DER key', function() {
const testEncoded = new NodeRSA({ b: 256 }).exportKey('pkcs1-private-der');
const decoded = pkcs1.decodePrivatePKCS1DER(testEncoded);
const encoded = pkcs1.encodePrivatePKCS1DER(decoded);
assert.instanceOf(encoded, Buffer, 'result should be a buffer');
assert.equal(encoded.toString(BASE64), testEncoded.toString(BASE64), 'encoded key should match original');
});
it('should fail if private components are missing', function() {
const testEncoded = new NodeRSA({ b: 256 }).exportKey('pkcs1-public-der');
const decoded = pkcs1.decodePublicPKCS1DER(testEncoded);
assert.throws(() => {
pkcs1.encodePrivatePKCS1DER(decoded);
}, RSAKeyError);
});
it('should fail if components are invalid', function() {
const testEncoded = new NodeRSA({ b: 256 }).exportKey('pkcs1-private-der');
const decoded = pkcs1.decodePrivatePKCS1DER(testEncoded);
assert.throws(() => {
pkcs1.encodePrivatePKCS1DER({ ...decoded, n: null});
}, RSAKeyError);
});
});
describe('encodePublicPKCS1DER', function() {
it('should encode public PKCS1 DER key', function() {
const testEncoded = new NodeRSA({ b: 256 }).exportKey('pkcs1-public-der');
const decoded = pkcs1.decodePublicPKCS1DER(testEncoded);
const encoded = pkcs1.encodePublicPKCS1DER(decoded);
assert.instanceOf(encoded, Buffer, 'result should be a buffer');
assert.equal(encoded.toString(BASE64), testEncoded.toString(BASE64), 'encoded key should match original');
});
it('should fail if components are missing', function() {
const testEncoded = new NodeRSA({ b: 256 }).exportKey('pkcs1-public-der');
const decoded = pkcs1.decodePublicPKCS1DER(testEncoded);
assert.throws(() => {
pkcs1.encodePublicPKCS1DER({ ...decoded, e: undefined });
}, RSAKeyError);
});
it('should fail if components are invalid', function() {
const testEncoded = new NodeRSA({ b: 256 }).exportKey('pkcs1-private-der');
const decoded = pkcs1.decodePrivatePKCS1DER(testEncoded);
assert.throws(() => {
pkcs1.encodePublicPKCS1DER({ ...decoded, n: null});
}, RSAKeyError);
});
});
});