Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions backend/rs/ic_vetkeys/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,17 @@ impl EncryptedVetKey {
}
}

/// Serialize the encrypted VetKey
pub fn serialize(&self) -> Vec<u8> {
let mut result = vec![];

result.extend_from_slice(&self.c1.to_compressed());
result.extend_from_slice(&self.c2.to_compressed());
result.extend_from_slice(&self.c3.to_compressed());

result
}

/// Deserializes an encrypted key from a byte vector
pub fn deserialize(bytes: &[u8]) -> Result<EncryptedVetKey, String> {
let ek_bytes: &[u8; Self::BYTES] = bytes.try_into().map_err(|_e: TryFromSliceError| {
Expand Down
4 changes: 3 additions & 1 deletion examples/basic_ibe/frontend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ async function getMyIbePrivateKey(): Promise<VetKey> {
transportSecretKey.publicKeyBytes(),
),
);
ibePrivateKey = new EncryptedVetKey(encryptedKey).decryptAndVerify(
ibePrivateKey = EncryptedVetKey.deserialize(
encryptedKey,
).decryptAndVerify(
transportSecretKey,
await getIbePublicKey(),
new Uint8Array(myPrincipal.toUint8Array()),
Expand Down
7 changes: 5 additions & 2 deletions frontend/ic_vetkeys/src/encrypted_maps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,8 @@ export class EncryptedMaps {
...mapName,
]);

const encryptedVetKey = new EncryptedVetKey(encryptedKeyBytes);
const encryptedVetKey =
EncryptedVetKey.deserialize(encryptedKeyBytes);
const derivedPublicKey =
DerivedPublicKey.deserialize(verificationKey);
const vetKey = encryptedVetKey.decryptAndVerify(
Expand Down Expand Up @@ -638,7 +639,9 @@ export class EncryptedMaps {
mapName,
]);
if (cachedRawDerivedKeyMaterial) {
return new DerivedKeyMaterial(cachedRawDerivedKeyMaterial);
return DerivedKeyMaterial.fromCryptoKey(
cachedRawDerivedKeyMaterial,
);
}

const derivedKeyMaterial = await this.getDerivedKeyMaterial(
Expand Down
6 changes: 3 additions & 3 deletions frontend/ic_vetkeys/src/key_manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ export class KeyManager {
vetkeyName: Uint8Array,
): Promise<Uint8Array> {
// create a random transport key
const seed = globalThis.crypto.getRandomValues(new Uint8Array(32));
const tsk = new TransportSecretKey(seed);
const tsk = TransportSecretKey.random();
const encryptedVetkey = await this.canisterClient.get_encrypted_vetkey(
keyOwner,
arrayToByteBuf(vetkeyName),
Expand All @@ -143,7 +142,8 @@ export class KeyManager {
...keyOwner.toUint8Array(),
...vetkeyName,
]);
const encryptedDetkey = new EncryptedVetKey(encryptedKeyBytes);
const encryptedDetkey =
EncryptedVetKey.deserialize(encryptedKeyBytes);
const vetkey = encryptedDetkey.decryptAndVerify(
tsk,
derivedPublicKey,
Expand Down
4 changes: 2 additions & 2 deletions frontend/ic_vetkeys/src/utils/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ test("BLS signature verification", () => {
});

test("protocol flow with precomputed data", () => {
const tsk = new TransportSecretKey(
const tsk = TransportSecretKey.deserialize(
hexToBytes(
"167b736e44a1c134bd46ca834220c75c186768612568ac264a01554c46633e76",
),
Expand All @@ -170,7 +170,7 @@ test("protocol flow with precomputed data", () => {
),
);

const ek = new EncryptedVetKey(
const ek = EncryptedVetKey.deserialize(
hexToBytes(
"b1a13757eaae15a3c8884fc1a3453f8a29b88984418e65f1bd21042ce1d6809b2f8a49f7326c1327f2a3921e8ff1d6c3adde2a801f1f88de98ccb40c62e366a279e7aec5875a0ce2f2a9f3e109d9cb193f0197eadb2c5f5568ee4d6a87e115910662e01e604087246be8b081fc6b8a06b4b0100ed1935d8c8d18d9f70d61718c5dba23a641487e72b3b25884eeede8feb3c71599bfbcebe60d29408795c85b4bdf19588c034d898e7fc513be8dbd04cac702a1672f5625f5833d063b05df7503",
),
Expand Down
78 changes: 54 additions & 24 deletions frontend/ic_vetkeys/src/utils/utils.ts
Comment thread
randombit marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,24 @@ export class TransportSecretKey {
readonly #pk: G1Point;

/**
* Construct a new TransportSecretKey from a bytestring
*
* The bytestring should be randomly generated by a cryptographically
* secure random number generator.
* Create a random transport secret key
*/
static random() {
return new TransportSecretKey(bls12_381.utils.randomPrivateKey());
}

/**
* Deserialize TransportSecretKey from a bytestring
*
* For most applications, prefer using the static method random
* The passed value would typically be a string previously returned
* by calling getSecretKey on a randomly-created TransportSecretKey.
Comment thread
randombit marked this conversation as resolved.
Outdated
*/
constructor(sk: Uint8Array) {
static deserialize(sk: Uint8Array) {
if (sk.length !== 32) {
throw new Error("Invalid size for transport secret key");
}

this.#sk = sk;

const pk = bls12_381.G1.ProjectivePoint.fromPrivateKey(this.#sk);
this.#pk = pk;
}

/**
* Create a random transport secret key
*/
static random() {
return new TransportSecretKey(bls12_381.utils.randomPrivateKey());
return new TransportSecretKey(sk);
}

/**
Expand All @@ -66,6 +61,15 @@ export class TransportSecretKey {
getSecretKey(): Uint8Array {
return this.#sk;
}

/**
* @internal constructor
*/
private constructor(sk: Uint8Array) {
this.#sk = sk;
const pk = bls12_381.G1.ProjectivePoint.fromPrivateKey(this.#sk);
this.#pk = pk;
}
}

/**
Expand Down Expand Up @@ -164,7 +168,7 @@ export class MasterPublicKey {
/**
* @internal constructor
*/
constructor(pk: G2Point) {
private constructor(pk: G2Point) {
this.#pk = pk;
}
}
Expand Down Expand Up @@ -245,6 +249,9 @@ export class DerivedPublicKey {

/**
* @internal constructor
*
* This is public for typing reasons but there should be no need
* for an application to call this.
*/
constructor(pk: G2Point) {
this.#pk = pk;
Expand Down Expand Up @@ -393,6 +400,15 @@ export class VetKey {
return this.#bytes;
}

/**
* Return the serialization of the VetKey
*
* This is the byte encoding of the unencrypted VetKey.
*/
serialize(): Uint8Array {
return this.#bytes;
}

/**
* Derive a symmetric key of the requested length from the VetKey
*
Expand Down Expand Up @@ -423,7 +439,7 @@ export class VetKey {
/**
* Deserialize a VetKey from the 48 byte encoding of the BLS signature
*
* This deserializes the same value as returned by signatureBytes
* This deserializes the same value as returned by serialize (or signatureBytes)
Comment thread
randombit marked this conversation as resolved.
*/
static deserialize(bytes: Uint8Array): VetKey {
return new VetKey(bls12_381.G1.ProjectivePoint.fromHex(bytes));
Expand Down Expand Up @@ -459,10 +475,14 @@ export class DerivedKeyMaterial {
/**
* @internal constructor
*/
constructor(cryptokey: CryptoKey) {
private constructor(cryptokey: CryptoKey) {
this.#hkdf = cryptokey;
}

static fromCryptoKey(cryptokey: CryptoKey): DerivedKeyMaterial {
return new DerivedKeyMaterial(cryptokey);
}

/**
* @internal constructor
*/
Expand Down Expand Up @@ -591,20 +611,21 @@ export class EncryptedVetKey {
* Parse an encrypted key returned by the `vetkd_derive_encrypted_key`
* managment canister interface
*/
constructor(bytes: Uint8Array) {
static deserialize(bytes: Uint8Array): EncryptedVetKey {
if (bytes.length !== G1_BYTES + G2_BYTES + G1_BYTES) {
throw new Error("Invalid EncryptedVetKey serialization");
}

this.#c1 = bls12_381.G1.ProjectivePoint.fromHex(
const c1 = bls12_381.G1.ProjectivePoint.fromHex(
bytes.subarray(0, G1_BYTES),
);
this.#c2 = bls12_381.G2.ProjectivePoint.fromHex(
const c2 = bls12_381.G2.ProjectivePoint.fromHex(
bytes.subarray(G1_BYTES, G1_BYTES + G2_BYTES),
);
this.#c3 = bls12_381.G1.ProjectivePoint.fromHex(
const c3 = bls12_381.G1.ProjectivePoint.fromHex(
bytes.subarray(G1_BYTES + G2_BYTES),
);
return new EncryptedVetKey(c1, c2, c3);
}

/**
Expand Down Expand Up @@ -643,6 +664,15 @@ export class EncryptedVetKey {
throw new Error("Invalid VetKey");
}
}

/**
* @internal constructor
*/
private constructor(c1: G1Point, c2: G2Point, c3: G1Point) {
this.#c1 = c1;
this.#c2 = c2;
this.#c3 = c3;
}
}

/* IBE (Identity Based Encryption) helper functions, not exported */
Expand Down