Skip to content

Commit

Permalink
Merge pull request input-output-hk#13 from input-output-hk/fix/paper-…
Browse files Browse the repository at this point in the history
…wallet-api

Fix paper wallets api
  • Loading branch information
NicolasDP authored Mar 12, 2018
2 parents 59be27a + 8ee868a commit 66d246a
Show file tree
Hide file tree
Showing 7 changed files with 870 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Cargo.lock
node_modules/
dist
.idea
npm-debug.log
18 changes: 18 additions & 0 deletions js/Bip39.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import bip39 from 'bip39';
import { Buffer } from 'safe-buffer';
import RustModule from './RustModule';
import Blake2b from './Blake2b';
import { apply } from './utils/functions';

export const mnemonicToEntropy = (mnemonic) => (
Buffer.from(bip39.mnemonicToEntropy(mnemonic), 'hex')
);

export const entropyToMnenomic = (entropy) => (
bip39.entropyToMnemonic(entropy)
);

export default {
mnemonicToEntropy,
entropyToMnenomic,
}
31 changes: 31 additions & 0 deletions js/PaperWallet.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import iconv from 'iconv-lite';
import RustModule from './RustModule';
import { newArray, newArray0, copyArray } from './utils/arrays';
import { apply } from './utils/functions';
import Bip39 from './Bip39';

export const scramble = (module, iv, password, input) => {
if (iv.length !== 4) {
Expand All @@ -19,6 +21,20 @@ export const scramble = (module, iv, password, input) => {
return result;
};

/**
* A sugar method on top of `scramble` that expects string params.
* @param module - the WASM module that is used for crypto operations
* @param iv: Uint8Array - 4 random bytes of entropy
* @param password: string
* @param mnenomics: string (12 word mnemonics which should be scrambled))
* @returns {*} - the scrambled 15 words
*/
export const scrambleStrings = (module, iv, password, mnenomics) => (
Bip39.entropyToMnenomic(
scramble(module, iv, iconv.encode(password, 'utf8'), Bip39.mnemonicToEntropy(mnenomics))
)
);

export const unscramble = (module, password, input) => {
if (input.length < 4) {
throw new Error('input must be at least 4 bytes');
Expand All @@ -34,7 +50,22 @@ export const unscramble = (module, password, input) => {
return result;
};

/**
* A sugar method on top of `unscramble` that expects string params.
* @param module - the WASM module that is used for crypto operations
* @param password: string
* @param mnenomics: string (15 words that have been generated by `scrambleStrings`)
* @returns {*} - the original 12 words mnemonics used for `scrambleStrings`
*/
export const unscrambleStrings = (module, password, mnenomics) => (
Bip39.entropyToMnenomic(
unscramble(module, iconv.encode(password, 'utf8'), Bip39.mnemonicToEntropy(mnenomics))
)
);

export default {
scramble: apply(scramble, RustModule),
scrambleStrings: apply(scrambleStrings, RustModule),
unscramble: apply(unscramble, RustModule),
unscrambleStrings: apply(unscrambleStrings, RustModule),
}
81 changes: 81 additions & 0 deletions js/tests/paper-wallets-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const expect = require('chai').expect;
const CardanoCrypto = require('../../dist/index.js');

// Implemented proposal: https://github.com/input-output-hk/cardano-specs/blob/master/proposals/0001-PaperWallet.md
const TEST_VECTORS = [
{
iv: new Uint8Array([0x00, 0x00, 0x00, 0x00]),
input: 'legal winner thank year wave sausage worth useful legal winner thank yellow',
passphrase: '',
scrambledWords: 'abandon abandon abandon win nest chef want salt join shove minor december miss oak name'
},
{
iv: new Uint8Array([0x00, 0x01, 0x02, 0x03]),
input: 'fold parrot feature figure stay blanket woman grain huge orphan key exile',
passphrase: 'Cardano Ada',
scrambledWords: 'abandon amount liar jump crouch mesh token control someone wheel purity initial choice bullet embark'
},
{
iv: new Uint8Array([0x2a, 0x2a, 0x2a, 0x2a]),
input: 'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong',
passphrase: 'This is a very long passphrase. This is a very long passphrase. This is a very long passphrase. This is a very long passphrase.',
scrambledWords: 'clay eyebrow melt enroll lend fold card pledge allow bottom dirt road frame fatal arch'
}
];

describe('PaperWallet', function() {

describe('#scramble', function() {

describe('Test Vector 1: without passphrase', function() {

it('generates the correct 15 words mnenomics from 12 words input', function() {
const { iv, input, passphrase, scrambledWords } = TEST_VECTORS[0];
expect(CardanoCrypto.PaperWallet.scrambleStrings(iv, passphrase, input)).equal(scrambledWords);
});
});

describe('Test Vector 2: short passphrase', function() {

it('generates the correct 15 words mnenomics from 12 words input', function() {
const { iv, input, passphrase, scrambledWords } = TEST_VECTORS[1];
expect(CardanoCrypto.PaperWallet.scrambleStrings(iv, passphrase, input)).equal(scrambledWords);
});
});

describe('Test Vector 3: long passphrase', function() {

it('generates the correct 15 words mnenomics from 12 words input', function() {
const { iv, input, passphrase, scrambledWords } = TEST_VECTORS[2];
expect(CardanoCrypto.PaperWallet.scrambleStrings(iv, passphrase, input)).equal(scrambledWords);
});
});
});

describe('#unscramble', function() {

describe('Test Vector 1: without passphrase', function() {

it('retrieves the original 12 words mnenomics from scrambled 15 words input', function() {
const { input, passphrase, scrambledWords } = TEST_VECTORS[0];
expect(CardanoCrypto.PaperWallet.unscrambleStrings(passphrase, scrambledWords)).equal(input);
});
});

describe('Test Vector 2: short passphrase', function() {

it('retrieves the original 12 words mnenomics from scrambled 15 words input', function() {
const { input, passphrase, scrambledWords } = TEST_VECTORS[1];
expect(CardanoCrypto.PaperWallet.unscrambleStrings(passphrase, scrambledWords)).equal(input);
});
});

describe('Test Vector 3: long passphrase', function() {

it('retrieves the original 12 words mnenomics from scrambled 15 words input', function() {
const { input, passphrase, scrambledWords } = TEST_VECTORS[2];
expect(CardanoCrypto.PaperWallet.unscrambleStrings(passphrase, scrambledWords)).equal(input);
});
});
});
});
Loading

0 comments on commit 66d246a

Please sign in to comment.