// Copyright 2012 The Obvious Corporation. /* * Tests of ursa */ /* * Modules used */ "use strict"; var assert = require("assert"); var fixture = require("./fixture"); var ursa = fixture.ursa; /** * Asserts that two strings are equal, ignoring Windows newline differences */ function assertStringEqual(actual, expected, message) { assert.equal(actual.replace(/\r\n/g, '\n'), expected.replace(/\r\n/g, '\n'), message); } /* * Helper functions */ function test_getExponent(key) { var buf = key.getExponent(); assert.equal(buf.toString(fixture.HEX), fixture.EXPONENT_HEX); var result = key.getExponent(fixture.HEX); assert.equal(result, fixture.EXPONENT_HEX); result = key.getExponent(fixture.BASE64); assert.equal(result, buf.toString(fixture.BASE64)); result = key.getExponent(fixture.BINARY); assert.equal(result, buf.toString(fixture.BINARY)); result = key.getExponent(fixture.UTF8); assert.equal(result, buf.toString(fixture.UTF8)); } function test_getModulus(key) { var buf = key.getModulus(); assert.equal(buf.toString(fixture.HEX), fixture.MODULUS_HEX); var result = key.getModulus(fixture.HEX); assert.equal(result, fixture.MODULUS_HEX); result = key.getModulus(fixture.BASE64); assert.equal(result, buf.toString(fixture.BASE64)); result = key.getModulus(fixture.BINARY); assert.equal(result, buf.toString(fixture.BINARY)); result = key.getModulus(fixture.UTF8); assert.equal(result, buf.toString(fixture.UTF8)); } function test_toPublicPem(key) { var keyString = fixture.PUBLIC_KEY.toString(fixture.UTF8); var result = key.toPublicPem().toString(fixture.UTF8); assertStringEqual(result, keyString); result = key.toPublicPem(fixture.UTF8); assertStringEqual(result, keyString); } function test_toPublicSsh(key) { var keyString = fixture.SSH_PUBLIC_KEY.toString(fixture.BASE64); var result = key.toPublicSsh().toString(fixture.BASE64); assert.equal(result, keyString); result = key.toPublicSsh(fixture.BASE64); assert.equal(result, keyString); } function test_toPublicSshFingerprint(key) { var result = key.toPublicSshFingerprint().toString(fixture.HEX); assert.equal(result, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); result = key.toPublicSshFingerprint(fixture.HEX); assert.equal(result, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); } function test_encrypt(key) { // The sanest way to test this is to do a round trip. var privKey = ursa.createPrivateKey(fixture.PRIVATE_KEY) var encoded = key.encrypt(new Buffer(fixture.PLAINTEXT, fixture.UTF8)); var decoded = privKey.decrypt(encoded, undefined, fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); encoded = key.encrypt(fixture.PLAINTEXT, fixture.UTF8, fixture.BASE64); decoded = privKey.decrypt(encoded, fixture.BASE64, fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); encoded = key.encrypt(fixture.PLAINTEXT, undefined, fixture.HEX); decoded = privKey.decrypt(encoded, fixture.HEX, fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); } function test_publicDecrypt(key) { var encoded = new Buffer(fixture.PUBLIC_CIPHERTEXT_HEX, fixture.HEX); var decoded = key.publicDecrypt(encoded).toString(fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); decoded = key.publicDecrypt(fixture.PUBLIC_CIPHERTEXT_HEX, fixture.HEX, fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); decoded = key.publicDecrypt(fixture.PUBLIC_CIPHERTEXT_NP_HEX, fixture.HEX, fixture.UTF8, ursa.RSA_NO_PADDING); assert.equal(decoded, fixture.PLAINTEXT_PADDED); } function test_verify(key) { assert.equal(key.verify(fixture.SHA256, fixture.PLAINTEXT_SHA256, fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX), true); var hash = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); var sig = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); assert.equal(key.verify(fixture.SHA256, hash, sig), true); } function test_hashAndVerify(key) { assert.equal(key.hashAndVerify(fixture.SHA256, new Buffer(fixture.PLAINTEXT, fixture.UTF8), fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX), true); var key2 = ursa.createPublicKeyFromComponents( new Buffer(fixture.PSS_MODULUS_HEX, fixture.HEX), new Buffer(fixture.EXPONENT_HEX, fixture.HEX)); assert.equal(key2.hashAndVerify(fixture.SHA1, fixture.PSS_M_HEX, fixture.PSS_S_HEX, fixture.HEX, true, ursa.RSA_PKCS1_SALT_LEN_HLEN), true); assert.equal(key2.hashAndVerify(fixture.SHA1, fixture.PSS_M_HEX, fixture.PSS_S_HEX, fixture.HEX, true), true); } function testPublicKeyMethods(key) { test_getExponent(key); test_getModulus(key); test_toPublicPem(key); test_toPublicSsh(key); test_toPublicSshFingerprint(key); test_encrypt(key); test_publicDecrypt(key); test_verify(key); test_hashAndVerify(key); } function test_toPrivatePem(key) { var keyString = fixture.PRIVATE_KEY.toString(fixture.UTF8); var result = key.toPrivatePem().toString(fixture.UTF8); assertStringEqual(result, keyString); result = key.toPrivatePem(fixture.UTF8); assertStringEqual(result, keyString); } function test_toEncryptedPrivatePem(key) { var password = fixture.PASSWORD.toString(fixture.UTF8); var cipher = fixture.DES_EDE3_CBC; var keyString = fixture.PASS_PRIVATE_KEY.toString(fixture.UTF8); var pem = key.toEncryptedPrivatePem(password, cipher).toString(fixture.UTF8); var plainTextKey = ursa.createPrivateKey(pem, password); assertStringEqual(plainTextKey.toPrivatePem().toString(), fixture.PRIVATE_KEY.toString()); pem = key.toEncryptedPrivatePem(password, cipher, fixture.UTF8).toString(fixture.UTF8); plainTextKey = ursa.createPrivateKey(pem, password); assertStringEqual(plainTextKey.toPrivatePem().toString(), fixture.PRIVATE_KEY.toString()); } function test_decrypt(key) { var encoded = new Buffer(fixture.PRIVATE_CIPHERTEXT_HEX, fixture.HEX); var decoded = key.decrypt(encoded).toString(fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); decoded = key.decrypt(fixture.PRIVATE_CIPHERTEXT_HEX, fixture.HEX, fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); } function test_privateEncrypt(key) { var encoded = key.privateEncrypt( new Buffer(fixture.PLAINTEXT, fixture.UTF8)).toString(fixture.HEX); assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); encoded = key.privateEncrypt(fixture.PLAINTEXT, fixture.UTF8, fixture.HEX); assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); encoded = key.privateEncrypt(fixture.PLAINTEXT, undefined, fixture.HEX); assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); encoded = key.privateEncrypt(fixture.PLAINTEXT_PADDED, fixture.UTF8, fixture.HEX, ursa.RSA_NO_PADDING); assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_NP_HEX); } function test_sign(key) { var sig = key.sign(fixture.SHA256, fixture.PLAINTEXT_SHA256, fixture.HEX, fixture.BASE64); sig = new Buffer(sig, fixture.BASE64); assert.equal(sig.toString(fixture.HEX), fixture.PLAINTEXT_SHA256_SIGNATURE); var buf = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); sig = key.sign(fixture.SHA256, buf, undefined, fixture.HEX); assert.equal(sig, fixture.PLAINTEXT_SHA256_SIGNATURE); } function test_hashAndSign(key) { var sig = key.hashAndSign(fixture.SHA256, fixture.PLAINTEXT, fixture.UTF8, fixture.HEX); assert.equal(sig, fixture.PLAINTEXT_SHA256_SIGNATURE); // PSS uses random salt so can't have a fixture var sig = key.hashAndSign(fixture.SHA256, fixture.PLAINTEXT, fixture.UTF8, fixture.HEX, true, ursa.RSA_PKCS1_SALT_LEN_MAX); assert.equal(key.hashAndVerify( fixture.SHA256, new Buffer(fixture.PLAINTEXT).toString(fixture.HEX), sig, fixture.HEX, true, ursa.RSA_PKCS1_SALT_LEN_MAX), true); } function testPrivateKeyMethods(key) { test_toPrivatePem(key); test_toEncryptedPrivatePem(key); test_decrypt(key); test_privateEncrypt(key); test_hashAndSign(key); test_sign(key); } describe('main', function() { it('Basics', function() { ursa.createPublicKey(fixture.PUBLIC_KEY); ursa.createPrivateKey(fixture.PRIVATE_KEY); ursa.createPrivateKey(fixture.PASS_PRIVATE_KEY, fixture.PASSWORD); ursa.generatePrivateKey(512); ursa.createPublicKey(fixture.PUBLIC_KEY.toString(fixture.UTF8)); ursa.createPrivateKey(fixture.PRIVATE_KEY.toString(fixture.BASE64), undefined, fixture.BASE64); }); it('Types', function() { var pub = ursa.createPublicKey(fixture.PUBLIC_KEY); var priv = ursa.createPrivateKey(fixture.PRIVATE_KEY); var msg; msg = "Problem with isKey()"; assert.equal(ursa.isKey(pub), true, msg); assert.equal(ursa.isKey(priv), true, msg); assert.equal(ursa.isKey(undefined), false, msg); assert.equal(ursa.isKey("x"), false, msg); msg = "Problem with isPublicKey()"; assert.equal(ursa.isPublicKey(pub), true, msg); assert.equal(ursa.isPublicKey(priv), false, msg); assert.equal(ursa.isPublicKey(undefined), false, msg); assert.equal(ursa.isPublicKey("x"), false, msg); msg = "Problem with isPrivateKey()"; assert.equal(ursa.isPrivateKey(pub), false, msg); assert.equal(ursa.isPrivateKey(priv), true, msg); assert.equal(ursa.isPrivateKey(undefined), false, msg); assert.equal(ursa.isPrivateKey("x"), false, msg); assert.doesNotThrow(function () { ursa.assertKey(pub); }); assert.doesNotThrow(function () { ursa.assertKey(priv); }); assert.throws(function () { ursa.assertKey(undefined); }); assert.throws(function () { ursa.assertKey("x"); }); assert.doesNotThrow(function () { ursa.assertPublicKey(pub); }); assert.throws(function () { ursa.assertPublicKey(priv); }); assert.throws(function () { ursa.assertPublicKey(undefined); }); assert.throws(function () { ursa.assertPublicKey("x"); }); assert.throws(function () { ursa.assertPrivateKey(pub); }); assert.doesNotThrow(function () { ursa.assertPrivateKey(priv); }); assert.throws(function () { ursa.assertPrivateKey(undefined); }); assert.throws(function () { ursa.assertPrivateKey("x"); }); }); it('createKey', function() { var priv = ursa.createKey(fixture.PRIVATE_KEY); assert(ursa.isPrivateKey(priv), true); var pub = ursa.createKey(fixture.PUBLIC_KEY); assert(ursa.isPublicKey(pub), true); function f1() { ursa.createKey("yo there"); } assert.throws(f1, /Not a key\./); }); it('createPrivateKeyFromComponents', function() { var privFromComponents = ursa.createPrivateKeyFromComponents( fixture.PRIVATE_KEY_COMPONENTS.modulus, fixture.PRIVATE_KEY_COMPONENTS.exponent, fixture.PRIVATE_KEY_COMPONENTS.p, fixture.PRIVATE_KEY_COMPONENTS.q, fixture.PRIVATE_KEY_COMPONENTS.dp, fixture.PRIVATE_KEY_COMPONENTS.dq, fixture.PRIVATE_KEY_COMPONENTS.inverseQ, fixture.PRIVATE_KEY_COMPONENTS.d); assert(ursa.isPrivateKey(privFromComponents), true); var privFromPem = ursa.createPrivateKey(fixture.PRIVATE_KEY_3); assert.equal(privFromComponents.toPrivatePem('utf8'), privFromPem.toPrivatePem('utf8')); }); it('createPublicKeyFromComponents', function() { var pubFromComponents = ursa.createPublicKeyFromComponents( new Buffer(fixture.PSS_MODULUS_HEX, fixture.HEX), new Buffer(fixture.EXPONENT_HEX, fixture.HEX)); assert(ursa.isPublicKey(pubFromComponents), true); var pubFromPem = ursa.createPublicKey(fixture.PSS_PUBLIC_KEY); assert.equal(pubFromComponents.toPublicPem('utf8'), pubFromPem.toPublicPem('utf8')); }); it('fail_createPublicKey', function() { // This is mostly tested at the native level. This just tests the // extra failures added at the high level. function f1() { ursa.createPublicKey(fixture.PRIVATE_KEY); } assert.throws(f1, /Not a public key\./); }); it('fail_createPrivateKey', function() { // This is mostly tested at the native level. This just tests the // extra failures added at the high level. function f1() { ursa.createPrivateKey(fixture.PUBLIC_KEY); } assert.throws(f1, /Not a private key\./); }); it('coerceKey', function() { var priv = ursa.coerceKey(fixture.PRIVATE_KEY); assert(ursa.isPrivateKey(priv), true); priv = ursa.coerceKey(fixture.PRIVATE_KEY.toString()); assert(ursa.isPrivateKey(priv), true); var pub = ursa.coerceKey(fixture.PUBLIC_KEY); assert(ursa.isPublicKey(pub), true); pub = ursa.coerceKey(fixture.PUBLIC_KEY.toString()); assert(ursa.isPublicKey(pub), true); assert.equal(ursa.coerceKey(priv), priv); assert.equal(ursa.coerceKey(pub), pub); }); it('coercePrivateKey', function() { var priv = ursa.coercePrivateKey(fixture.PRIVATE_KEY); assert(ursa.isPrivateKey(priv), true); priv = ursa.coercePrivateKey(fixture.PRIVATE_KEY.toString()); assert(ursa.isPrivateKey(priv), true); assert.equal(ursa.coercePrivateKey(priv), priv); }); it('coercePublicKey', function() { var pub = ursa.coercePublicKey(fixture.PUBLIC_KEY); assert(ursa.isPublicKey(pub), true); pub = ursa.coercePublicKey(fixture.PUBLIC_KEY.toString()); assert(ursa.isPublicKey(pub), true); assert.equal(ursa.coercePublicKey(pub), pub); }); it('fail_coerceKey', function() { function f1() { ursa.coerceKey("foo"); } assert.throws(f1, /Not a key/); function f2() { ursa.coerceKey(new Buffer(200)); } assert.throws(f2, /Not a key/); function f3() { ursa.coerceKey([]); } assert.throws(f3, /Not a key/); }); it('fail_coercePrivateKey', function() { function f1() { ursa.coercePrivateKey("foo"); } assert.throws(f1, /Not a private key/); function f2() { ursa.coercePrivateKey(new Buffer(200)); } assert.throws(f2, /Not a private key/); function f3() { ursa.coercePrivateKey([]); } assert.throws(f3, /Not a private key/); function f4() { ursa.coercePrivateKey(fixture.PUBLIC_KEY); } assert.throws(f4, /Not a private key/); function f5() { ursa.coercePrivateKey(fixture.PUBLIC_KEY.toString()); } assert.throws(f5, /Not a private key/); }); it('fail_coercePublicKey', function() { function f1() { ursa.coercePublicKey("foo"); } assert.throws(f1, /Not a public key/); function f2() { ursa.coercePublicKey(new Buffer(200)); } assert.throws(f2, /Not a public key/); function f3() { ursa.coercePublicKey([]); } assert.throws(f3, /Not a public key/); function f4() { ursa.coercePublicKey(fixture.PRIVATE_KEY); } assert.throws(f4, /Not a public key/); function f5() { ursa.coercePublicKey(fixture.PRIVATE_KEY.toString()); } assert.throws(f5, /Not a public key/); }); it('PublicKey', function() { var key = ursa.createPublicKey(fixture.PUBLIC_KEY); testPublicKeyMethods(key); }); it('PrivateKey', function() { var key = ursa.createPrivateKey(fixture.PRIVATE_KEY); testPublicKeyMethods(key); testPrivateKeyMethods(key); }); it('GeneratedKey', function() { // Just do a round trip. If that works, then it's safe to believe // the native tests (which are more comprehensive). var key = ursa.generatePrivateKey(); var encoded = key.encrypt(fixture.PLAINTEXT, fixture.UTF8); var decoded = key.decrypt(encoded, undefined, fixture.UTF8); assert.equal(decoded, fixture.PLAINTEXT); }); it('sshFingerprint', function() { var key = fixture.SSH_PUBLIC_KEY; var finger = ursa.sshFingerprint(fixture.SSH_PUBLIC_KEY); assert.equal(finger.toString(fixture.HEX), fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); finger = ursa.sshFingerprint(fixture.SSH_PUBLIC_KEY, undefined, fixture.HEX); assert.equal(finger, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); finger = ursa.sshFingerprint( fixture.SSH_PUBLIC_KEY.toString(fixture.BASE64), fixture.BASE64, fixture.HEX); assert.equal(finger, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); }); it('equalKeys', function() { var pub = ursa.createPublicKey(fixture.PUBLIC_KEY); var priv = ursa.createPrivateKey(fixture.PRIVATE_KEY); var samePub = ursa.createPublicKey(fixture.PUBLIC_KEY); var samePriv = ursa.createPrivateKey(fixture.PRIVATE_KEY); var diffPub = ursa.createPublicKey(fixture.PUBLIC_KEY_2); var diffPriv = ursa.createPrivateKey(fixture.PRIVATE_KEY_2); assert.equal(ursa.equalKeys("1", "2"), false); assert.equal(ursa.equalKeys(123, 123), false); assert.equal(ursa.equalKeys(pub, null), false); assert.equal(ursa.equalKeys(true, pub), false); assert.equal(ursa.equalKeys(pub, pub), true); assert.equal(ursa.equalKeys(priv, priv), true); assert.equal(ursa.equalKeys(pub, priv), false); assert.equal(ursa.equalKeys(priv, pub), false); assert.equal(ursa.equalKeys(pub, samePub), true); assert.equal(ursa.equalKeys(priv, samePriv), true); assert.equal(ursa.equalKeys(pub, diffPub), false); assert.equal(ursa.equalKeys(priv, diffPriv), false); }); it('matchingPublicKeys', function() { var pub = ursa.createPublicKey(fixture.PUBLIC_KEY); var priv = ursa.createPrivateKey(fixture.PRIVATE_KEY); var samePub = ursa.createPublicKey(fixture.PUBLIC_KEY); var samePriv = ursa.createPrivateKey(fixture.PRIVATE_KEY); var diffPub = ursa.createPublicKey(fixture.PUBLIC_KEY_2); var diffPriv = ursa.createPrivateKey(fixture.PRIVATE_KEY_2); assert.equal(ursa.matchingPublicKeys("1", "2"), false); assert.equal(ursa.matchingPublicKeys(123, 123), false); assert.equal(ursa.matchingPublicKeys(pub, null), false); assert.equal(ursa.matchingPublicKeys(true, pub), false); assert.equal(ursa.matchingPublicKeys(pub, pub), true); assert.equal(ursa.matchingPublicKeys(priv, priv), true); assert.equal(ursa.matchingPublicKeys(pub, priv), true); assert.equal(ursa.matchingPublicKeys(priv, pub), true); assert.equal(ursa.matchingPublicKeys(pub, samePub), true); assert.equal(ursa.matchingPublicKeys(priv, samePriv), true); assert.equal(ursa.matchingPublicKeys(pub, samePriv), true); assert.equal(ursa.matchingPublicKeys(priv, samePub), true); assert.equal(ursa.matchingPublicKeys(pub, diffPub), false); assert.equal(ursa.matchingPublicKeys(pub, diffPriv), false); assert.equal(ursa.matchingPublicKeys(priv, diffPriv), false); assert.equal(ursa.matchingPublicKeys(priv, diffPub), false); }); it('Signer', function() { var key = ursa.createPrivateKey(fixture.PRIVATE_KEY); var signer = ursa.createSigner(fixture.SHA256); var ret = signer.update(fixture.PLAINTEXT, fixture.UTF8); assert.equal(ret === signer, true); var sig = signer.sign(key, fixture.HEX); assert.equal(sig, fixture.PLAINTEXT_SHA256_SIGNATURE); }); it('Verifier', function() { var key = ursa.createPublicKey(fixture.PUBLIC_KEY); var verifier = ursa.createVerifier(fixture.SHA256); var ret = verifier.update(fixture.PLAINTEXT, fixture.UTF8); assert.equal(ret === verifier, true); assert.equal(verifier.verify(key, fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX), true); var verifier = ursa.createVerifier(fixture.SHA256); verifier.update(new Buffer(fixture.PLAINTEXT, fixture.UTF8)); var sigBuf = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); assert.equal(verifier.verify(key, sigBuf), true); }); it('openSshPublicKey', function() { var sshKey = ursa.openSshPublicKey(fixture.SSH_PUBLIC_KEY), pubKey = ursa.createPublicKey(fixture.PUBLIC_KEY); assert.equal(ursa.equalKeys(sshKey, pubKey), true); }); })