feat(crypto): CRP-2603 Add VetKD utils in TypeScript#2
Conversation
|
Notes:
|
sdk/ic_vetkd_sdk_utils/src/index.ts
Outdated
| pk: G2Point; | ||
|
|
||
| constructor(bytes: Uint8Array) { | ||
| const pk = bls12_381.G2.ProjectivePoint.fromHex(bytes); |
There was a problem hiding this comment.
Check that the identity element is rejected
sdk/ic_vetkd_sdk_utils/src/index.ts
Outdated
|
|
||
| this.c1 = bls12_381.G1.ProjectivePoint.fromHex(bytes.subarray(0, G1_BYTES)); | ||
| this.c2 = bls12_381.G2.ProjectivePoint.fromHex(bytes.subarray(G1_BYTES, G1_BYTES + G2_BYTES)); | ||
| this.c3 = bls12_381.G1.ProjectivePoint.fromHex(bytes.subarray(G1_BYTES + G2_BYTES)); |
There was a problem hiding this comment.
Check that identity elements are rejected
|
|
||
| const calculated = augmentedHashToG1(pk, msg); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Add a randomized test with emulated replica side
| }, | ||
| "scripts": { | ||
| "build": "tsc", | ||
| "test": "jest", |
There was a problem hiding this comment.
We should add a workflow for the tests, but not necessarily in this PR. I run the tests locally and they seem to work and finish successfully.
There was a problem hiding this comment.
I imagine getting CI to work will (as typical) involve a lot of iterations, I was inclined to merge this without CI then add CI in a followup.
| * "my-app" is deriving two keys, one for usage "foo" and the other for | ||
| * "bar". You might use as domain separators "my-app-foo" and "my-app-bar". | ||
| */ | ||
| export function deriveSymmetricKey(input: Uint8Array, domainSep: string, outputLength: number): Uint8Array { |
There was a problem hiding this comment.
do we want this (and similar) function(s) to be exported? if yes, maybe we could move this into a namespace with all the stuff that is not supposed to be used my a normal developer
There was a problem hiding this comment.
It seems not unreasonable to me that a developer would use this, eg for creating a tree of symmetric keys derived from a vetkd root. But we can for the time being annotate it with @internal which apparently hides it from documentation generators and IDE tooling.
| } | ||
|
|
||
| export class EncryptedKey { | ||
| readonly #c1: G1Point; |
There was a problem hiding this comment.
is there a reference in some paper we could point to to describe what those c{i}'s are? Also a sentence about what the Key is and what it is Encrypted with could make sense.
There was a problem hiding this comment.
This is from 6.2 of https://eprint.iacr.org/2023/616.pdf but the same idea goes back to the FullIdent Boneh-Franklin IBE scheme from https://crypto.stanford.edu/~dabo/papers/bfibe.pdf section 4.2
In IBE the public key is some point in the pairing group (in the original BF-IBE proposal derived by hashing the user identifier to a point), and the secret key is that same point, multiplied by the secret scalar controlled by the trusted issuer.
In VetKD, the public keys are instead a set of points specified by the tuple of (canister id, derivation path, derivation id) [which can be accessed via vetkd_public_key] and the private keys are the signatures, from vetkd_encrypted_key.
After retrieving a users public key with vetkd_public_key with some specified context and derivation id, anyone can IBE encrypt a message. Anyone who can retrieve the VetKey associated with that context and derivation id (and thus the BLS signature) also holds the key necessary to decrypt the IBE ciphertext.
I'll add some comments with references.
|
Two more things:
|
Domain separators are typically strings in my experience eg in TLS 1.3 key scheduling, TLS key exporter, hash to curve, CPace PAKE, KMAC/ParallellHash/TupleHash, or the domain separators used in the IC Using non-ASCII/non-UTF8 bytestrings as domain separators does work just fine since all that matters for security is that they are unique. Just usually these are fairly static since the goal is to tie the output to a specific context (application, version, intended key usage, user identifiers, ...) most of which are more easily and comprehensibly expressed as strings. The higher level functions of noble-curves take the domain separators as strings as well. The low level XMD function doesn't and instead uses a bytestring for whatever reason. I'm not sure if it's even possible to call eg hash to curve with a domain separator that's not a string.
TBH I had no expected that use case. I would have expected instead to derive a random symmetric key (eg 256 bits) then stash that, and if necessary use it to derive further keys. I guess in the immediate term you could use |
But what we are doing here is essentially some sort of HKDF, no? I was thinking about it as |
I think we wanted to remove |
It is much closer to the |
355e6cd to
d5a20c8
Compare
Avoiding the difficulties of wasm deployment.
Avoiding the difficulties of wasm deployment.