UNPKG

aladinnetwork-blockstack

Version:

The Aladin Javascript library for authentication, identity, and storage.

157 lines (127 loc) 6.41 kB
import test from 'tape-promise/tape' import elliptic from 'elliptic' import { encryptECIES, decryptECIES, getHexFromBN, signECDSA, verifyECDSA, encryptMnemonic, decryptMnemonic } from '../../../src/encryption' export function runEncryptionTests() { const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' const publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69' test('encrypt-to-decrypt works', (t) => { t.plan(2) const testString = 'all work and no play makes jack a dull boy' let cipherObj = encryptECIES(publicKey, testString) let deciphered = decryptECIES(privateKey, cipherObj) t.equal(deciphered, testString, 'Decrypted ciphertext does not match expected plaintext') const testBuffer = Buffer.from(testString) cipherObj = encryptECIES(publicKey, testBuffer) deciphered = decryptECIES(privateKey, cipherObj) t.equal(deciphered.toString('hex'), testBuffer.toString('hex'), 'Decrypted cipherbuffer does not match expected plainbuffer') }) test('encrypt-to-decrypt fails on bad mac', (t) => { t.plan(1) const testString = 'all work and no play makes jack a dull boy' const cipherObj = encryptECIES(publicKey, testString) const evilString = 'some work and some play makes jack a dull boy' const evilObj = encryptECIES(publicKey, evilString) cipherObj.cipherText = evilObj.cipherText try { decryptECIES(privateKey, cipherObj) t.true(false, 'Decryption should have failed when ciphertext modified') } catch (e) { t.true(true, 'Decryption correctly fails when ciphertext modified') } }) test('sign-to-verify-works', (t) => { t.plan(2) const testString = 'all work and no play makes jack a dull boy' let sigObj = signECDSA(privateKey, testString) t.true(verifyECDSA(testString, sigObj.publicKey, sigObj.signature), 'String content should be verified') const testBuffer = Buffer.from(testString) sigObj = signECDSA(privateKey, testBuffer) t.true(verifyECDSA(testBuffer, sigObj.publicKey, sigObj.signature), 'String buffer should be verified') }) test('sign-to-verify-fails', (t) => { t.plan(3) const testString = 'all work and no play makes jack a dull boy' const failString = 'I should fail' let sigObj = signECDSA(privateKey, testString) t.false(verifyECDSA(failString, sigObj.publicKey, sigObj.signature), 'String content should not be verified') const testBuffer = Buffer.from(testString) sigObj = signECDSA(privateKey, testBuffer) t.false(verifyECDSA(Buffer.from(failString), sigObj.publicKey, sigObj.signature), 'Buffer content should not be verified') const badPK = '0288580b020800f421d746f738b221d384f098e911b81939d8c94df89e74cba776' sigObj = signECDSA(privateKey, testBuffer) t.false(verifyECDSA(Buffer.from(failString), badPK, sigObj.signature), 'Buffer content should not be verified') }) test('bn-padded-to-64-bytes', (t) => { t.plan(1) const ecurve = new elliptic.ec('secp256k1') const evilHexes = ['ba40f85b152bea8c3812da187bcfcfb0dc6e15f9e27cb073633b1c787b19472f', 'e346010f923f768138152d0bad063999ff1da5361a81e6e6f9106241692a0076'] const results = evilHexes.map((hex) => { const ephemeralSK = ecurve.keyFromPrivate(hex) const ephemeralPK = ephemeralSK.getPublic() const sharedSecret = ephemeralSK.derive(ephemeralPK) return getHexFromBN(sharedSecret).length === 64 }) t.true(results.every(x => x), 'Evil hexes must all generate 64-len hex strings') }) test('encryptMnemonic & decryptMnemonic', (t) => { t.plan(4) const rawPhrase = 'march eager husband pilot waste rely exclude taste ' + 'twist donkey actress scene' const rawPassword = 'testtest' const preEncryptedPhrase = '7573f4f51089ba7ce2b95542552b7504de7305398637733' + '0579649dfbc9e664073ba614fac180d3dc237b21eba57f9aee5702ba819fe17a0752c4dc7' + '94884c9e75eb60da875f778bbc1aaca1bd373ea3' const legacyPhrase = 'vivid oxygen neutral wheat find thumb cigar wheel ' + 'board kiwi portion business' const legacyPassword = 'supersecret' const legacyEncrypted = '1c94d7de0000000304d583f007c71e6e5fef354c046e8c64b1' + 'adebd6904dcb007a1222f07313643873455ab2a3ab3819e99d518cc7d33c18bde02494aa' + '74efc35a8970b2007b2fc715f6067cee27f5c92d020b1806b0444994aab80050a6732131' + 'd2947a51bacb3952fb9286124b3c2b3196ff7edce66dee0dbd9eb59558e0044bddb3a78f' + '48a66cf8d78bb46bb472bd2d5ec420c831fc384293252459524ee2d668869f33c586a944' + '67d0ce8671260f4cc2e87140c873b6ca79fb86c6d77d134d7beb2018845a9e71e6c7ecde' + 'dacd8a676f1f873c5f9c708cc6070642d44d2505aa9cdba26c50ad6f8d3e547fb0cba710' + 'a7f7be54ff7ea7e98a809ddee5ef85f6f259b3a17a8d8dbaac618b80fe266a1e63ec19e4' + '76bee9177b51894ee' // Test encryption -> decryption. Can't be done with hard-coded values // due to random salt. // TODO: Use generators to allow for inserting the same salt for testing? encryptMnemonic(rawPhrase, rawPassword) .then(encoded => decryptMnemonic(encoded.toString('hex'), rawPassword), (err) => { t.fail(`Should encrypt mnemonic phrase, instead errored: ${err}`) }) .then((decoded: string) => { t.true(decoded.toString() === rawPhrase, 'Should encrypt & decrypt a phrase correctly') }, (err) => { t.fail(`Should decrypt encrypted phrase, instead errored: ${err}`) }) // Test valid input (No salt, so it's the same every time) decryptMnemonic(legacyEncrypted, legacyPassword).then((decoded) => { t.true(decoded.toString() === legacyPhrase, 'Should decrypt legacy encrypted phrase') }, (err) => { t.fail(`Should decrypt legacy encrypted phrase, instead errored: ${err}`) }) // Invalid inputs encryptMnemonic('not a mnemonic phrase', 'password').then(() => { t.fail('Should have thrown on invalid mnemonic input') }, () => { t.pass('Should throw on invalid mnemonic input') }) decryptMnemonic(preEncryptedPhrase, 'incorrect password').then(() => { t.fail('Should have thrown on incorrect password for decryption') }, () => { t.pass('Should throw on incorrect password') }) }) }