Skip to content

Commit 81d202c

Browse files
authored
Add pk to hash (#146)
* Add pk to hash * Get pks before decryption * redundant import * use id instead of pk in hash * tests * kdf * nanme * update
1 parent 18ec718 commit 81d202c

File tree

5 files changed

+58
-15
lines changed

5 files changed

+58
-15
lines changed

packages/seal/src/decrypt.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,12 @@ export async function decrypt({ encryptedObject, keys }: DecryptOptions): Promis
5555
const shares = inKeystore.map((i: number) => {
5656
const [objectId, index] = encryptedObject.services[i];
5757
// Use the index as the unique info parameter to allow for multiple shares per key server.
58-
const info = new Uint8Array([index]);
5958
const share = BonehFranklinBLS12381Services.decrypt(
6059
nonce,
6160
keys.get(`${fullId}:${objectId}`)!,
6261
encryptedShares[i],
6362
fromHex(fullId),
64-
info,
63+
[objectId, index],
6564
);
6665
// The Shamir secret sharing library expects the index/x-coordinate to be at the end of the share.
6766
return { index, share };

packages/seal/src/encrypt.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export async function encrypt({
7575
fromHex(fullId),
7676
shares.map(({ share, index }) => ({
7777
msg: share,
78-
info: new Uint8Array([index]),
78+
index,
7979
})),
8080
deriveKey(KeyPurpose.EncryptedRandomness, key),
8181
);
@@ -113,7 +113,7 @@ function encryptBatched(
113113
keyServers: KeyServer[],
114114
kemType: KemType,
115115
id: Uint8Array,
116-
shares: { msg: Uint8Array; info: Uint8Array }[],
116+
shares: { msg: Uint8Array; index: number }[],
117117
randomnessKey: Uint8Array,
118118
): typeof IBEEncryptions.$inferType {
119119
switch (kemType) {

packages/seal/src/ibe.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ export abstract class IBEServers {
4141
* Encrypt a batch of messages for the given identity.
4242
*
4343
* @param id The identity.
44-
* @param msgAndInfos The messages and an additional info parameter which will be included in the KDF.
44+
* @param msgAndIndices The messages and the corresponding indices of the share being encrypted.
4545
* @returns The encrypted messages.
4646
*/
4747
abstract encryptBatched(
4848
id: Uint8Array,
49-
msgAndInfos: { msg: Uint8Array; info: Uint8Array }[],
49+
msgAndIndices: { msg: Uint8Array; index: number }[],
5050
randomnessKey: Uint8Array,
5151
): typeof IBEEncryptions.$inferType;
5252
}
@@ -65,15 +65,15 @@ export class BonehFranklinBLS12381Services extends IBEServers {
6565

6666
encryptBatched(
6767
id: Uint8Array,
68-
msgAndInfos: { msg: Uint8Array; info: Uint8Array }[],
68+
msgAndIndices: { msg: Uint8Array; index: number }[],
6969
randomnessKey: Uint8Array,
7070
): typeof IBEEncryptions.$inferType {
71-
if (this.publicKeys.length === 0 || this.publicKeys.length !== msgAndInfos.length) {
71+
if (this.publicKeys.length === 0 || this.publicKeys.length !== msgAndIndices.length) {
7272
throw new Error('Invalid public keys');
7373
}
7474
const [r, nonce, keys] = encapBatched(this.publicKeys, id);
75-
const encryptedShares = msgAndInfos.map((msgAndInfo, i) =>
76-
xor(msgAndInfo.msg, kdf(keys[i], nonce, id, msgAndInfo.info)),
75+
const encryptedShares = msgAndIndices.map((msgAndIndex, i) =>
76+
xor(msgAndIndex.msg, kdf(keys[i], nonce, id, this.objectIds[i], msgAndIndex.index)),
7777
);
7878
const encryptedRandomness = xor(randomnessKey, r.toBytes());
7979

@@ -114,9 +114,9 @@ export class BonehFranklinBLS12381Services extends IBEServers {
114114
sk: G1Element,
115115
ciphertext: Uint8Array,
116116
id: Uint8Array,
117-
info: Uint8Array,
117+
[objectId, index]: [string, number],
118118
): Uint8Array {
119-
return xor(ciphertext, kdf(decap(nonce, sk), nonce, id, info));
119+
return xor(ciphertext, kdf(decap(nonce, sk), nonce, id, objectId, index));
120120
}
121121
}
122122

packages/seal/src/kdf.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Mysten Labs, Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { fromHex } from '@mysten/bcs';
45
import { hkdf } from '@noble/hashes/hkdf';
56
import { hmac } from '@noble/hashes/hmac';
67
import { sha3_256 } from '@noble/hashes/sha3';
@@ -19,7 +20,8 @@ export function kdf(
1920
element: GTElement,
2021
nonce: G2Element,
2122
id: Uint8Array,
22-
info: Uint8Array,
23+
objectId: string,
24+
index: number,
2325
): Uint8Array {
2426
// This permutation flips the order of 6 pairs of coefficients of the GT element.
2527
// The permutation may be computed as:
@@ -45,6 +47,7 @@ export function kdf(
4547
...nonce.toBytes(),
4648
...G1Element.hashToCurve(id).toBytes(),
4749
]);
50+
const info = new Uint8Array([...fromHex(objectId), index]);
4851
return hkdf(sha3_256, inputBytes, '', info, 32);
4952
}
5053

packages/seal/test/unit/encrypt.test.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,51 @@ describe('Seal encryption tests', () => {
356356
G2Element.generator().multiply(Scalar.fromNumber(12345)),
357357
);
358358
const nonce = G2Element.generator().multiply(Scalar.fromNumber(12345));
359-
const key = kdf(x, nonce, new Uint8Array([0]), new Uint8Array([]));
359+
const key = kdf(
360+
x,
361+
nonce,
362+
new Uint8Array([0]),
363+
'0x0000000000000000000000000000000000000000000000000000000000000000',
364+
42,
365+
);
360366
expect(key).toEqual(
361-
fromHex('57d43441a0b561088d4162a1b38ea8a2d443dd2c50ec4aca0610a1a79c057f74'),
367+
fromHex('1963b93f076d0dc97cbb38c3864b2d6baeb87c7eb99139100fd775b0b09f668b'),
368+
);
369+
});
370+
371+
it('Rust test vector decryption', async () => {
372+
// Test created with seal-cli using the command:
373+
// cargo run --bin seal-cli encrypt-hmac --message 48656C6C6F2C20776F726C6421 --aad 0x0000000000000000000000000000000000000000000000000000000000000001 --package-id 0x0 --id 0x381dd9078c322a4663c392761a0211b527c127b29583851217f948d62131f409 --threshold 2 aeb258b9fb9a2f29f74eb0a1a895860bb1c6ba3f9ea7075366de159e4764413e9ec0597ac9c0dad409723935440a45f40eee4728630ae3ea40a68a819375bba1d78d7810f901d8a469d785d00cfed6bd28f01d41e49c5652d924e9d19fddcf62 b1076a26f4f82f39d0e767fcd2118659362afe40bce4e8d553258c86756bb74f888bca79f2d6b71edf6e25af89efa83713a223b48a19d2e551897ac92ac7458336cd489be3be025e348ca93f4c94d22594f96f0e08990e51a7de9da8ff29c98f 95fcb465af3791f31d53d80db6c8dcf9f83a419b2570614ecfbb068f47613da17cb9ffc66bb052b9546f17196929538f0bd2d38e1f515d9916e2db13dc43e0ccbd4cb3d7cbb13ffecc0b68b37481ebaaaa17cad18096a9c2c27a797f17d78623 -- 0x34401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab96 0xd726ecf6f7036ee3557cd6c7b93a49b231070e8eecada9cfa157e40e3f02e5d3 0xdba72804cc9504a82bbaa13ed4a83a0e2c6219d7e45125cf57fd10cbab957a97
374+
const encryptedObject = fromHex(
375+
'00000000000000000000000000000000000000000000000000000000000000000020381dd9078c322a4663c392761a0211b527c127b29583851217f948d62131f40903034401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab9601d726ecf6f7036ee3557cd6c7b93a49b231070e8eecada9cfa157e40e3f02e5d302dba72804cc9504a82bbaa13ed4a83a0e2c6219d7e45125cf57fd10cbab957a97030200b7f57f44e5302b684737612ebf4561ce4b4c5fea496731914f78d402db1c3c712fae396125a150e8eb1582e05a1f98140afc3214db2060c80471d6d97a173407c41fa4ca58396f6f879826e4f78b7f58282c8e48c664c9f8c953ab2e7a727125030fbf02ffa94172ae1a5c5b1be1b8bddb20ea698d49150aa361ed56504daa3c8f6f7bc1e58f024dff40892db134da0b61e58fa82317afa6884ae14f5d739b5e95fc1b56d645b75d60302775aac94d1bf52a103eefbad9cecd61fbbad37c9dbccceeb9007861ee3f34e4a546b7fe6b5b195ef1fee6ba8080d5d228bd721904b0d5010dab6e4eca9b82653721946aac8401200000000000000000000000000000000000000000000000000000000000000001a5fb3bfe499a0fa285e7129a88962e278fc65e821851d4234ada909ac72a77e5',
376+
);
377+
const parsed = EncryptedObject.parse(encryptedObject);
378+
const id = createFullId(DST, parsed.packageId, parsed.id);
379+
380+
let usk0 = G1Element.fromBytes(
381+
fromHex(
382+
'8244fcbe49870a4d4aa947b7034a873e168580e18b5834ea34940dc9f492eda03a9b20c3c3c120b1a462f1642575e0cc',
383+
),
384+
);
385+
let usk1 = G1Element.fromBytes(
386+
fromHex(
387+
'a0f04b759ed2ff477f0fe5b672992235205d2af502f659d4bbb484b745e35fd7a9ff11e37e12111023a891c3fa98a2d3',
388+
),
362389
);
390+
391+
const objectId0 = '0x034401905bebdf8c04f3cd5f04f442a39372c8dc321c29edfb4f9cb30b23ab96';
392+
const objectId1 = '0xd726ecf6f7036ee3557cd6c7b93a49b231070e8eecada9cfa157e40e3f02e5d3';
393+
394+
const msg = new TextEncoder().encode('Hello, world!');
395+
await expect(
396+
decrypt({
397+
encryptedObject: parsed,
398+
keys: new Map<KeyCacheKey, G1Element>([
399+
[`${id}:${objectId0}`, usk0],
400+
[`${id}:${objectId1}`, usk1],
401+
]),
402+
}),
403+
).resolves.toEqual(msg);
363404
});
364405

365406
it('test single key server', async () => {

0 commit comments

Comments
 (0)