diff options
author | Florian Dold <florian@dold.me> | 2021-10-18 21:48:22 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2021-10-18 21:48:45 +0200 |
commit | 269022a526b670d602ca146f4df02850983bb72e (patch) | |
tree | e0a66e8b15ef305c99274c76964a119d0d9512ba /packages/anastasis-core | |
parent | 3a69f27412782872c1264e8a4dd1be13d57a8a80 (diff) |
move some more crypto to taler-util package
Diffstat (limited to 'packages/anastasis-core')
-rw-r--r-- | packages/anastasis-core/src/crypto.ts | 41 | ||||
-rw-r--r-- | packages/anastasis-core/src/index.ts | 15 |
2 files changed, 55 insertions, 1 deletions
diff --git a/packages/anastasis-core/src/crypto.ts b/packages/anastasis-core/src/crypto.ts index 5da3a4cce..32cf470c4 100644 --- a/packages/anastasis-core/src/crypto.ts +++ b/packages/anastasis-core/src/crypto.ts @@ -5,7 +5,9 @@ import { encodeCrock, getRandomBytes, kdf, + kdfKw, secretbox, + crypto_sign_keyPair_fromSeed, stringToBytes, } from "@gnu-taler/taler-util"; import { argon2id } from "hash-wasm"; @@ -25,6 +27,8 @@ export type EncryptedKeyShare = Flavor<string, "EncryptedKeyShare">; export type EncryptedTruth = Flavor<string, "EncryptedTruth">; export type EncryptedCoreSecret = Flavor<string, "EncryptedCoreSecret">; export type EncryptedMasterKey = Flavor<string, "EncryptedMasterKey">; +export type EddsaPublicKey = Flavor<string, "EddsaPublicKey">; +export type EddsaPrivateKey = Flavor<string, "EddsaPrivateKey">; /** * Truth key, found in the recovery document. */ @@ -53,6 +57,43 @@ export async function userIdentifierDerive( return encodeCrock(result); } +export interface AccountKeyPair { + priv: EddsaPrivateKey; + pub: EddsaPublicKey; +} + +export function accountKeypairDerive(userId: UserIdentifier): AccountKeyPair { + // FIXME: the KDF invocation looks fishy, but that's what the C code presently does. + const d = kdfKw({ + outputLength: 32, + ikm: stringToBytes("ver"), + salt: decodeCrock(userId), + }); + // FIXME: This bit twiddling seems wrong/unnecessary. + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + const pair = crypto_sign_keyPair_fromSeed(d); + return { + priv: encodeCrock(pair.secretKey), + pub: encodeCrock(pair.publicKey), + }; +} + +export async function encryptRecoveryDocument( + userId: UserIdentifier, + recoveryDoc: any, +): Promise<OpaqueData> { + const plaintext = stringToBytes(JSON.stringify(recoveryDoc)); + const nonce = encodeCrock(getRandomBytes(nonceSize)); + return anastasisEncrypt( + nonce, + asOpaque(userId), + encodeCrock(plaintext), + "erd", + ); +} + function taConcat(chunks: Uint8Array[]): Uint8Array { let payloadLen = 0; for (const c of chunks) { diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts index f33a0be46..8921433b7 100644 --- a/packages/anastasis-core/src/index.ts +++ b/packages/anastasis-core/src/index.ts @@ -36,8 +36,10 @@ import { } from "./reducer-types.js"; import fetchPonyfill from "fetch-ponyfill"; import { + accountKeypairDerive, coreSecretEncrypt, encryptKeyshare, + encryptRecoveryDocument, encryptTruth, PolicyKey, policyKeyDerive, @@ -492,14 +494,25 @@ async function uploadSecret( policies: policies.map((x, i) => { return { master_key: csr.encMasterKeys[i], + // FIXME: ... uuid: [], - salt: + salt: undefined as any, }; }), }; for (const prov of state.policy_providers!) { + const uid = uidMap[prov.provider_url] + const acctKeypair = accountKeypairDerive(uid); + const encRecoveryDoc = await encryptRecoveryDocument(uid, rd); // FIXME: Upload recovery document. + const resp = await fetch( + new URL(`policy/${acctKeypair.pub}`, prov.provider_url).href, + { + method: "POST", + body: decodeCrock(encRecoveryDoc), + }, + ); } return { |