mirror of
https://github.com/paritytech/banana_split.git
synced 2026-09-14 11:06:18 +05:00
Merge pull request #12 from paritytech/kirushik/futureproof_qr_parsing
More ergonomic and futureproof parsing
This commit is contained in:
commit
02d2b4ffb1
@ -79,11 +79,31 @@ function parse(payload) {
|
||||
}
|
||||
}
|
||||
|
||||
function reconstruct(shards, title, passphrase, encodedNonce) {
|
||||
var encryptedSecret = SECRETS.combine(shards);
|
||||
function reconstruct(shardObjects, passphrase) {
|
||||
var shardData = shardObjects.map(shard => shard.data);
|
||||
|
||||
var shardsRequirements = shardObjects.map(shard => shard.requiredShards);
|
||||
if (!shardsRequirements.every(r => r===shardsRequirements[0])) {
|
||||
throw "Mismatching min shards requirement among shards!"
|
||||
}
|
||||
if (shardObjects.length < shardsRequirements[0]) {
|
||||
throw `Not enough shards, need ${shardsRequirements[0]} but only ${shardObjects.length} provided`
|
||||
}
|
||||
|
||||
var nonces = shardObjects.map(shard => shard.nonce);
|
||||
if (!nonces.every(n => n===nonces[0])) {
|
||||
throw "Nonces mismatch among shards!"
|
||||
}
|
||||
|
||||
var titles = shardObjects.map((shard) => shard.title);
|
||||
if (!titles.every(t => t===titles[0])) {
|
||||
throw "Titles mismatch among shards!"
|
||||
}
|
||||
|
||||
var encryptedSecret = SECRETS.combine(shardData);
|
||||
var secret = dehexify(encryptedSecret);
|
||||
var nonce = dehexify(encodedNonce);
|
||||
var salt = hashString(title);
|
||||
var nonce = dehexify(nonces[0]);
|
||||
var salt = hashString(titles[0]);
|
||||
return uint8ArrayToStr(decrypt(secret, salt, passphrase, nonce));
|
||||
}
|
||||
|
||||
|
||||
@ -68,9 +68,7 @@ export default {
|
||||
if (!this.passphrase) { return; }
|
||||
this.passphrase = this.passphrase.split(" ").filter(el => el).join('-');
|
||||
var shards = Array.from(this.shards);
|
||||
var nonce = shards[0].nonce;
|
||||
var dataShards = shards.map((shard) => shard.data)
|
||||
this.recoveredSecret = crypto.reconstruct(dataShards, this.title, this.passphrase, nonce);
|
||||
this.recoveredSecret = crypto.reconstruct(shards, this.passphrase);
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
|
||||
@ -5,7 +5,7 @@ import crypto from "../../src/util/crypto";
|
||||
test('encodes-decodes empty values', () => {
|
||||
var shards = crypto.share('', '', '', 3, 2);
|
||||
var parsed = shards.map(s => crypto.parse(s));
|
||||
var reconstructed = crypto.reconstruct(parsed.map(p => p.data), parsed[0].title, '', parsed[0].nonce);
|
||||
var reconstructed = crypto.reconstruct(parsed, '');
|
||||
expect(reconstructed).toBe('');
|
||||
})
|
||||
|
||||
@ -23,18 +23,18 @@ test('works with any 2 shards out of 3', () => {
|
||||
var shards = crypto.share('Secret message', 'Secret title', 'correct-horse-battery-staple', 3, 2);
|
||||
var parsed = shards.map(s => crypto.parse(s));
|
||||
[
|
||||
[parsed[0].data, parsed[1].data],
|
||||
[parsed[0].data, parsed[2].data],
|
||||
[parsed[1].data, parsed[2].data]
|
||||
].forEach(twoShards => {
|
||||
expect(crypto.reconstruct(twoShards, 'Secret title', 'correct-horse-battery-staple', parsed[0].nonce)).toBe('Secret message')
|
||||
|
||||
[0, 1], [0, 2], [1, 2],
|
||||
[1, 0], [2, 0], [2, 1]
|
||||
].forEach(([i, j]) => {
|
||||
expect(crypto.reconstruct([parsed[i], parsed[j]], 'correct-horse-battery-staple')).toBe('Secret message')
|
||||
});
|
||||
})
|
||||
|
||||
test('fails with incorrect password', () => {
|
||||
var shards = crypto.share('Secret message', 'Secret title', 'correct-horse-battery-staple', 5, 3);
|
||||
var parsed = shards.map(s => crypto.parse(s));
|
||||
var reconstructed = crypto.reconstruct(parsed.map(p => p.data), parsed[0].title, '', parsed[0].nonce);
|
||||
var reconstructed = crypto.reconstruct(parsed, '');
|
||||
expect(reconstructed).not.toBe('Secret message');
|
||||
expect(reconstructed).toBe('');
|
||||
})
|
||||
@ -46,21 +46,38 @@ test('works with unicode strings', () => {
|
||||
expect(message.title).toBe('Это секрет')
|
||||
});
|
||||
|
||||
var reconstructed = crypto.reconstruct(parsed.map(p => p.data), parsed[0].title, 'correct-horse-battery-staple', parsed[0].nonce);
|
||||
var reconstructed = crypto.reconstruct(parsed, 'correct-horse-battery-staple');
|
||||
expect(reconstructed).toBe('Текст сообщения');
|
||||
})
|
||||
|
||||
test('reconstructs the reference example', () => {
|
||||
test('reconstructs the reference example of v0 serialization', () => {
|
||||
var shards = [
|
||||
{"t":"Very secret info","r":2,"d":"803c12929ba469d720a63fc8ca6f6ef1cc441f8f0b830ea04f8a484169ec800e4a7","n":"29abbb2c509adedb470f6d3fd3d083362b8c1a9283adf987"},
|
||||
{"t":"Very secret info","r":2,"d":"801b4196813bb664141169f939414fec30c7f343326d8df45e557b25b0249fd43e2","n":"29abbb2c509adedb470f6d3fd3d083362b8c1a9283adf987"},
|
||||
{"t":"Very secret info","r":2,"d":"80275318760b66ee5a1d7430dbf8769fda05e9e1ff7447eaa78539fbed006f0390b","n":"29abbb2c509adedb470f6d3fd3d083362b8c1a9283adf987"}
|
||||
];
|
||||
'{"t":"Very secret info","r":2,"d":"803c12929ba469d720a63fc8ca6f6ef1cc441f8f0b830ea04f8a484169ec800e4a7","n":"29abbb2c509adedb470f6d3fd3d083362b8c1a9283adf987"}',
|
||||
'{"t":"Very secret info","r":2,"d":"801b4196813bb664141169f939414fec30c7f343326d8df45e557b25b0249fd43e2","n":"29abbb2c509adedb470f6d3fd3d083362b8c1a9283adf987"}',
|
||||
'{"t":"Very secret info","r":2,"d":"80275318760b66ee5a1d7430dbf8769fda05e9e1ff7447eaa78539fbed006f0390b","n":"29abbb2c509adedb470f6d3fd3d083362b8c1a9283adf987"}'
|
||||
].map(s => crypto.parse(s));
|
||||
|
||||
[
|
||||
[0, 1], [0, 2], [1, 2],
|
||||
[1, 0], [2, 0], [2, 1]
|
||||
].forEach(([i,j]) => {
|
||||
expect(crypto.reconstruct([shards[i].d, shards[j].d], 'Very secret info', 'amazing-daring-panda-horror', shards[i].n)).toBe('Any questions?')
|
||||
expect(crypto.reconstruct([shards[i], shards[j]], 'amazing-daring-panda-horror')).toBe('Any questions?')
|
||||
});
|
||||
})
|
||||
|
||||
test('throws an error if nonces mismatch', () => {
|
||||
var shards = crypto.share('Message', 'Title', 'correct-horse-battery-staple', 3, 2).map(s => crypto.parse(s));
|
||||
shards[0].nonce = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
expect(() => crypto.reconstruct([shards[0], shards[1]], 'correct-horse-battery-staple')).toThrow(/Nonces mismatch/)
|
||||
})
|
||||
|
||||
test('throws an error if titles mismatch', () => {
|
||||
var shards = crypto.share('Message', 'Title', 'correct-horse-battery-staple', 3, 2).map(s => crypto.parse(s));
|
||||
shards[0].title = "Completely different title"
|
||||
expect(() => crypto.reconstruct([shards[0], shards[1]], 'correct-horse-battery-staple')).toThrow(/Titles mismatch/)
|
||||
})
|
||||
|
||||
test("doesn't work if less shards than necessary are supplied", () => {
|
||||
var shards = crypto.share('Message', 'Title', 'correct-horse-battery-staple', 5, 3).map(s => crypto.parse(s));
|
||||
expect(() => crypto.reconstruct([shards[0], shards[1]], 'correct-horse-battery-staple')).toThrow(/Not enough shards/)
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user