Open CedarMist opened 2 weeks ago
If we're verifying ed25519 should probably migrate to @noble/curves
, and a function like:
function verifyRuntimePublicKey(pk:CallDataPublicKey, runtime_id:Uint8Array, key_pair_id:Uint8Array)
{
const PUBLIC_KEY_SIGNATURE_CONTEXT = new TextEncoder().encode("oasis-core/keymanager: pk signature");
let body = new Uint8Array([
...pk.key,
...pk.checksum,
...runtime_id,
...key_pair_id
]);
if( pk.epoch !== undefined ) {
body = new Uint8Array([...body, ...u64tobytes(pk.epoch)]);
}
if( pk.expiration !== undefined ) {
body = new Uint8Array([...body, ...u64tobytes(pk.expiration)]);
}
const ctx = sha512_256.create();
ctx.update(PUBLIC_KEY_SIGNATURE_CONTEXT);
ctx.update(body);
const digest = ctx.digest();
// TODO: verify pk.signature with digest and pk.key
}
Trying to determine the differences between https://github.com/oasisprotocol/oasis-core/blob/050a01f97be8afa6d079fda07952330035b790c1/runtime/src/common/crypto/signature.rs#L125 and the @noble/curves
ed25519 verification. It should be straightforward, but need to figure out the details.
@noble/curves
specifies ( https://github.com/paulmillr/noble-curves/blob/c1eb761af14b811822abf971b15669dacf7feec6/src/ed25519.ts#L134C1-L142C2 )
function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) {
if (ctx.length > 255) throw new Error('Context is too big');
return concatBytes(
utf8ToBytes('SigEd25519 no Ed25519 collisions'),
new Uint8Array([phflag ? 1 : 0, ctx.length]),
ctx,
data
);
}
So, presumably we need to provide our own domain function. but ed25519Defaults
isn't exported, and we can't modify the domain after:
export const ed25519ctx = /* @__PURE__ */ (() =>
twistedEdwards({
...ed25519Defaults,
domain: ed25519_domain,
}))();
A long-term keypair is used to sign the validity of the calldata pubic key.
This keypair can be hard-coded into the clients, and used to verify it.
This means the Oasis RPC servers won't be in a trusted position.
Return the runtime signing (public) key from consensus:
In go code, see: https://github.com/oasisprotocol/oasis-core/blob/050a01f97be8afa6d079fda07952330035b790c1/go/keymanager/secrets/api.go#L295-L302
In rust code, see: https://github.com/oasisprotocol/oasis-core/blob/050a01f97be8afa6d079fda07952330035b790c1/keymanager/src/crypto/types.rs#L157-L170
Verification happens via:
The hash here is a 32-bute SHA-512/256.
Note, we need the
key_pair_id
andruntime_id
from somewhere to verify the signature, these are both 32-bytes each.Note:
Sign(sk, (key || checksum || runtime id || key pair id || epoch || expiration epoch))