EdgeAIG/opencode / .opencode /node_modules /effect /src /unstable /eventlog /internal /identityRootSecretDerivation.ts
| import * as Effect from "../../../Effect.ts" | |
| import * as Redacted from "../../../Redacted.ts" | |
| import type { Identity } from "../EventLog.ts" | |
| const textEncoder = new TextEncoder() | |
| const Ed25519PublicKeyLength = 32 | |
| const Ed25519Pkcs8SeedPrefix = Uint8Array.from([ | |
| 0x30, | |
| 0x2e, | |
| 0x02, | |
| 0x01, | |
| 0x00, | |
| 0x30, | |
| 0x05, | |
| 0x06, | |
| 0x03, | |
| 0x2b, | |
| 0x65, | |
| 0x70, | |
| 0x04, | |
| 0x22, | |
| 0x04, | |
| 0x20 | |
| ]) | |
| /** @internal */ | |
| export const EncryptionDerivationLabelV1 = "effect/eventlog/identity/v1/encryption" | |
| /** @internal */ | |
| export const SigningDerivationLabelV1 = "effect/eventlog/identity/v1/signing" | |
| /** @internal */ | |
| export interface IdentityRootSecretMaterial { | |
| readonly encryptionKeyMaterial: Uint8Array<ArrayBuffer> | |
| readonly encryptionKey: CryptoKey | |
| readonly signingPublicKey: Uint8Array<ArrayBuffer> | |
| readonly signingPrivateKey: Redacted.Redacted<Uint8Array<ArrayBuffer>> | |
| } | |
| const toArrayBuffer = (data: Uint8Array): ArrayBuffer => { | |
| const copy = new Uint8Array(data.byteLength) | |
| copy.set(data) | |
| return copy.buffer | |
| } | |
| const decodeBase64Url = (value: string): Uint8Array<ArrayBuffer> => { | |
| const normalized = value.replaceAll("-", "+").replaceAll("_", "/") | |
| const remainder = normalized.length % 4 | |
| const padded = remainder === 0 ? normalized : `${normalized}${"=".repeat(4 - remainder)}` | |
| const decoded = atob(padded) | |
| const bytes = new Uint8Array(decoded.length) | |
| for (let i = 0; i < decoded.length; i++) { | |
| bytes[i] = decoded.charCodeAt(i) | |
| } | |
| return bytes | |
| } | |
| const makeEd25519Pkcs8FromSeed = (seed: Uint8Array): Uint8Array<ArrayBuffer> => { | |
| const key = new Uint8Array(Ed25519Pkcs8SeedPrefix.byteLength + seed.byteLength) | |
| key.set(Ed25519Pkcs8SeedPrefix, 0) | |
| key.set(seed, Ed25519Pkcs8SeedPrefix.byteLength) | |
| return key | |
| } | |
| const deriveSecretBytes = Effect.fnUntraced(function*(options: { | |
| readonly crypto: Crypto | |
| readonly rootSecret: Uint8Array | |
| readonly label: string | |
| }) { | |
| const labelBytes = textEncoder.encode(options.label) | |
| const derivationInput = new Uint8Array(labelBytes.byteLength + 1 + options.rootSecret.byteLength) | |
| derivationInput.set(labelBytes, 0) | |
| derivationInput[labelBytes.byteLength] = 0 | |
| derivationInput.set(options.rootSecret, labelBytes.byteLength + 1) | |
| const digest = yield* Effect.promise(() => options.crypto.subtle.digest("SHA-256", toArrayBuffer(derivationInput))) | |
| return new Uint8Array(digest) | |
| }) | |
| /** @internal */ | |
| export const deriveIdentityRootSecretMaterial = Effect.fnUntraced(function*(options: { | |
| readonly crypto: Crypto | |
| readonly rootSecret: Uint8Array | |
| }) { | |
| const encryptionKeyMaterial = yield* deriveSecretBytes({ | |
| crypto: options.crypto, | |
| rootSecret: options.rootSecret, | |
| label: EncryptionDerivationLabelV1 | |
| }) | |
| const signingSeed = yield* deriveSecretBytes({ | |
| crypto: options.crypto, | |
| rootSecret: options.rootSecret, | |
| label: SigningDerivationLabelV1 | |
| }) | |
| const signingPrivateKeyBytes = makeEd25519Pkcs8FromSeed(signingSeed) | |
| const encryptionKey = yield* Effect.promise(() => | |
| options.crypto.subtle.importKey("raw", toArrayBuffer(encryptionKeyMaterial), "AES-GCM", true, [ | |
| "encrypt", | |
| "decrypt" | |
| ]) | |
| ) | |
| const signingPrivateKey = yield* Effect.promise(() => | |
| options.crypto.subtle.importKey("pkcs8", toArrayBuffer(signingPrivateKeyBytes), "Ed25519", true, ["sign"]) | |
| ) | |
| const signingJwk = yield* Effect.promise(() => options.crypto.subtle.exportKey("jwk", signingPrivateKey)) | |
| if (typeof signingJwk.x !== "string") { | |
| return yield* Effect.die(new Error("Unable to export deterministic Ed25519 public key")) | |
| } | |
| const signingPublicKey = decodeBase64Url(signingJwk.x) | |
| if (signingPublicKey.byteLength !== Ed25519PublicKeyLength) { | |
| return yield* Effect.die( | |
| new Error(`Expected derived signing public key to be ${Ed25519PublicKeyLength} bytes`) | |
| ) | |
| } | |
| return { | |
| encryptionKeyMaterial, | |
| encryptionKey, | |
| signingPublicKey, | |
| signingPrivateKey: Redacted.make(signingPrivateKeyBytes) | |
| } satisfies IdentityRootSecretMaterial | |
| }) | |
| /** @internal */ | |
| export const makeGetIdentityRootSecretMaterial = (crypto: Crypto) => { | |
| const cache = new WeakMap<Identity["Service"], IdentityRootSecretMaterial>() | |
| return Effect.fnUntraced(function*(identity: Identity["Service"]) { | |
| const cached = cache.get(identity) | |
| if (cached !== undefined) { | |
| return cached | |
| } | |
| const derived = yield* deriveIdentityRootSecretMaterial({ | |
| crypto, | |
| rootSecret: Redacted.value(identity.privateKey) | |
| }) | |
| yield* Effect.sync(() => { | |
| cache.set(identity, derived) | |
| }) | |
| return derived | |
| }) | |
| } | |
Xet Storage Details
- Size:
- 4.56 kB
- Xet hash:
- a53418e2206a249e1fb0a5c17f74bb3b90e877d943628b952092658685d077f7
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.