UNPKG

rsa-key

Version:

Converts between RSA key formats, detecting input format (PEM, DER, PKCS1, PKCS8). No OpenSSL needed.

362 lines (284 loc) 11.4 kB
const { assert } = require('chai'); const RSAKey = require('../src'); const NodeRSA = require('node-rsa'); describe('Module entry point', function() { it('should return RSAKey class', function() { assert.equal(RSAKey.name, 'RSAKey'); }); }); describe('RSAKey', function() { let testKey, testEncodedPrivatePKCS8PEM, testEncodedPublicPKCS8PEM, pubKey, privKey; before(function() { this.timeout(10000); testKey = new NodeRSA({ b: 256 }); testEncodedPrivatePKCS8PEM = testKey.exportKey('pkcs8-private-pem'); testEncodedPublicPKCS8PEM = testKey.exportKey('pkcs8-public-pem'); pubKey = new RSAKey(testEncodedPublicPKCS8PEM); privKey = new RSAKey(testEncodedPrivatePKCS8PEM); }); describe('Creation and importing', function() { let key; it('should create an empty object', function() { key = new RSAKey(); assert.instanceOf(key, RSAKey); }); it('should have empty components property', function() { assert.isObject(key.components); assert.deepEqual(key.components, {}); }); it('hasKey should be false', function() { assert.isFalse(key.hasKey()); }); it('isEmpty should be true', function() { assert.isTrue(key.isEmpty()); }); it('getType should return null', function() { assert.isNull(key.getType()); }); it('should fail trying to export key', function() { assert.throws(() => { key.exportKey(); }, 'key is empty'); }); it('should fail trying to generate fingerprint', function() { assert.throws(() => { key.getFingerprint(); }, 'key is empty'); }); it('_requireKey should throw', function() { assert.throws(() => { key._requireKey(); }, 'key is empty'); }); it('should import a key', function() { assert.doesNotThrow(() => { key.importKey(testEncodedPrivatePKCS8PEM); assert.isObject(key.components); }); }); it('should import a key while creating RSAKey object', function() { assert.doesNotThrow(() => { const keyImported = new RSAKey(testEncodedPublicPKCS8PEM); assert.isObject(keyImported); }); }); it('should import from another RSAKey instance', function() { const newKey = new RSAKey(); newKey.importKey(key); assert.deepEqual(newKey.components, key.components); }); }); describe('Handling public keys', function() { it('hasKey should be true', function() { assert.isTrue(pubKey.hasKey()); }); it('isEmpty should be false', function() { assert.isFalse(pubKey.isEmpty()); }); it('isPublic should be true', function() { assert.isTrue(pubKey.isPublic()); }); it('isPublic(true) should be true', function() { assert.isTrue(pubKey.isPublic(true)); }); it('isPrivate should be false', function() { assert.isFalse(pubKey.isPrivate()); }); it('getType should return public', function() { assert.equal(pubKey.getType(), 'public'); }); it('_requireKey should not throw', function() { assert.doesNotThrow(() => { pubKey._requireKey(); }); }); it('_requireKey should throw if private key is required', function() { assert.throws(() => { pubKey._requireKey('test', true); }, 'this is a public key'); }); describe('exporting key', function() { it('should fail trying to export private PKCS8 PEM key', function() { assert.throws(() => { pubKey.exportKey('pkcs8', 'private', 'pem'); }, 'components are missing'); }); it('should fail trying to export private PKCS1 PEM key', function() { assert.throws(() => { pubKey.exportKey('pkcs1', 'private', 'pem'); }, 'components are missing'); }); it('should export public PKCS8 PEM key', function() { const exported = pubKey.exportKey('pkcs8', 'public', 'pem'); const correct = testKey.exportKey('pkcs8-public-pem'); assert.equal(exported, correct); }); it('should export public PKCS1 PEM key', function() { const exported = pubKey.exportKey('pkcs1', 'public', 'pem'); const correct = testKey.exportKey('pkcs1-public-pem'); assert.equal(exported, correct); }); it('should fail trying to export private PKCS8 DER key', function() { assert.throws(() => { pubKey.exportKey('pkcs8', 'private', 'der').toString('base64'); }, 'components are missing'); }); it('should fail trying to export private PKCS1 DER key', function() { assert.throws(() => { pubKey.exportKey('pkcs1', 'private', 'der').toString('base64'); }, 'components are missing'); }); it('should export public PKCS8 DER key', function() { const exported = pubKey.exportKey('pkcs8', 'public', 'der').toString('base64'); const correct = testKey.exportKey('pkcs8-public-der').toString('base64'); assert.equal(exported, correct); }); it('should export public PKCS1 DER key', function() { const exported = pubKey.exportKey('pkcs1', 'public', 'der').toString('base64'); const correct = testKey.exportKey('pkcs1-public-der').toString('base64'); assert.equal(exported, correct); }); it('should export public PKCS8 PEM key by default', function() { const exported = pubKey.exportKey(); const correct = testKey.exportKey('pkcs8-public-pem'); assert.equal(exported, correct); }); }); }); describe('Handling private keys', function() { it('hasKey should be true', function() { assert.isTrue(privKey.hasKey()); }); it('isEmpty should be false', function() { assert.isFalse(privKey.isEmpty()); }); it('isPublic should be true', function() { assert.isTrue(privKey.isPublic()); }); it('isPublic(true) should be false', function() { assert.isFalse(privKey.isPublic(true)); }); it('isPrivate should be true', function() { assert.isTrue(privKey.isPrivate()); }); it('getType should return private', function() { assert.equal(privKey.getType(), 'private'); }); it('_requireKey should not throw', function() { assert.doesNotThrow(() => { privKey._requireKey(); }); }); it('_requireKey should not throw if private key is required', function() { assert.doesNotThrow(() => { privKey._requireKey('test', true); }); }); describe('exporting key', function() { it('should export private PKCS8 PEM key', function() { const exported = privKey.exportKey('pkcs8', 'private', 'pem'); const correct = testKey.exportKey('pkcs8-private-pem'); assert.equal(exported, correct); }); it('should export private PKCS1 PEM key', function() { const exported = privKey.exportKey('pkcs1', 'private', 'pem'); const correct = testKey.exportKey('pkcs1-private-pem'); assert.equal(exported, correct); }); it('should export public PKCS8 PEM key', function() { const exported = privKey.exportKey('pkcs8', 'public', 'pem'); const correct = testKey.exportKey('pkcs8-public-pem'); assert.equal(exported, correct); }); it('should export public PKCS1 PEM key', function() { const exported = privKey.exportKey('pkcs1', 'public', 'pem'); const correct = testKey.exportKey('pkcs1-public-pem'); assert.equal(exported, correct); }); it('should export private PKCS8 DER key', function() { const exported = privKey.exportKey('pkcs8', 'private', 'der').toString('base64'); const correct = testKey.exportKey('pkcs8-private-der').toString('base64'); assert.equal(exported, correct); }); it('should export private PKCS1 DER key', function() { const exported = privKey.exportKey('pkcs1', 'private', 'der').toString('base64'); const correct = testKey.exportKey('pkcs1-private-der').toString('base64'); assert.equal(exported, correct); }); it('should export public PKCS8 DER key', function() { const exported = privKey.exportKey('pkcs8', 'public', 'der').toString('base64'); const correct = testKey.exportKey('pkcs8-public-der').toString('base64'); assert.equal(exported, correct); }); it('should export public PKCS1 DER key', function() { const exported = privKey.exportKey('pkcs1', 'public', 'der').toString('base64'); const correct = testKey.exportKey('pkcs1-public-der').toString('base64'); assert.equal(exported, correct); }); it('should export private PKCS8 PEM key by default', function() { const exported = privKey.exportKey(); const correct = testKey.exportKey('pkcs8-private-pem'); assert.equal(exported, correct); }); it('should fail trying to export key with invalid export params', function() { assert.throws(() => { privKey.exportKey('clearly-invalid-param'); }, 'Unknown key export parameter'); }); }); }); describe('Caching time-consuming operation results', function() { let key, exported; const specs = ['public', 'pkcs1', 'pem']; it('should export key', function() { key = new RSAKey(privKey); exported = key.exportKey(...specs); assert.isString(exported); }); it('should export previously cached key', function() { key.components.n = 'different value'; const newExport = key.exportKey(...specs); assert.equal(newExport, exported); }); it('should export a different key for different specs', function() { key.components.n = privKey.components.n; const newExport = key.exportKey(...specs, 'pkcs8'); assert.notEqual(newExport, exported); }); it('should clear cache when importing key', function() { key.importKey(pubKey); key.components.n = 'different value'; const newExport = key.exportKey(...specs); assert.notEqual(newExport, exported); }); }); describe('Other methods', function() { let key; before(function() { key = new RSAKey(testEncodedPrivatePKCS8PEM); }); it('getKeySize should return key size in bits', function() { const size = key.getKeySize(); assert.equal(size, testKey.getKeySize()); }); it('getKeySize should return 0 for empty key', function() { const size = new RSAKey().getKeySize(); assert.equal(size, 0); }); it('getFingerprint should return key fingerprint', function() { const keyString = '-----BEGIN PUBLIC KEY-----\n' + 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8Z9kXlY0FtPi25ZLwQnI7OamZ\n' + 'VjWSIkNRcDrzN971MNKu0Q6LjDicCYH77iZKla6OgNxAB3uBHoZ27Wz1mMlqddbg\n' + 'HXe6ToEBQCW8K0gP4zGF+osV5B8iLoqCPiqCiCGcuX6ePs01AmFLkSzsqGdVu+tX\n' + 'L/+q3MOEIa7XYlO/lwIDAQAB\n' + '-----END PUBLIC KEY-----'; const correct = 'df:bc:31:2b:9e:10:6a:b9:2e:5f:27:5a:14:41:72:6f'; const fingerprint = new RSAKey(keyString).getFingerprint(); assert.equal(fingerprint, correct); }); }); });