aboutsummaryrefslogtreecommitdiff
path: root/packages/anastasis-core/src/crypto.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/anastasis-core/src/crypto.ts')
-rw-r--r--packages/anastasis-core/src/crypto.ts50
1 files changed, 43 insertions, 7 deletions
diff --git a/packages/anastasis-core/src/crypto.ts b/packages/anastasis-core/src/crypto.ts
index 63de795b0..8df893f4b 100644
--- a/packages/anastasis-core/src/crypto.ts
+++ b/packages/anastasis-core/src/crypto.ts
@@ -9,6 +9,7 @@ import {
secretbox,
crypto_sign_keyPair_fromSeed,
stringToBytes,
+ secretbox_open,
} from "@gnu-taler/taler-util";
import { gzipSync } from "fflate";
import { argon2id } from "hash-wasm";
@@ -87,7 +88,7 @@ export function accountKeypairDerive(userId: UserIdentifier): AccountKeyPair {
/**
* Encrypt the recovery document.
- *
+ *
* The caller should first compress the recovery doc.
*/
export async function encryptRecoveryDocument(
@@ -95,12 +96,19 @@ export async function encryptRecoveryDocument(
recoveryDocData: OpaqueData,
): Promise<OpaqueData> {
const nonce = encodeCrock(getRandomBytes(nonceSize));
- return anastasisEncrypt(
- nonce,
- asOpaque(userId),
- recoveryDocData,
- "erd",
- );
+ return anastasisEncrypt(nonce, asOpaque(userId), recoveryDocData, "erd");
+}
+
+/**
+ * Encrypt the recovery document.
+ *
+ * The caller should first compress the recovery doc.
+ */
+export async function decryptRecoveryDocument(
+ userId: UserIdentifier,
+ recoveryDocData: OpaqueData,
+): Promise<OpaqueData> {
+ return anastasisDecrypt(asOpaque(userId), recoveryDocData, "erd");
}
export function typedArrayConcat(chunks: Uint8Array[]): Uint8Array {
@@ -158,6 +166,22 @@ async function anastasisEncrypt(
return encodeCrock(typedArrayConcat([nonceBuf, cipherText]));
}
+async function anastasisDecrypt(
+ keySeed: OpaqueData,
+ ciphertext: OpaqueData,
+ salt: string,
+): Promise<OpaqueData> {
+ const ctBuf = decodeCrock(ciphertext);
+ const nonceBuf = ctBuf.slice(0, nonceSize);
+ const enc = ctBuf.slice(nonceSize);
+ const key = await deriveKey(keySeed, encodeCrock(nonceBuf), salt);
+ const cipherText = secretbox_open(enc, nonceBuf, key);
+ if (!cipherText) {
+ throw Error("could not decrypt");
+ }
+ return encodeCrock(cipherText);
+}
+
export const asOpaque = (x: string): OpaqueData => x;
const asEncryptedKeyShare = (x: OpaqueData): EncryptedKeyShare => x as string;
const asEncryptedTruth = (x: OpaqueData): EncryptedTruth => x as string;
@@ -185,6 +209,18 @@ export async function encryptTruth(
);
}
+export async function decryptTruth(
+ truthEncKey: TruthKey,
+ truthEnc: EncryptedTruth,
+): Promise<OpaqueData> {
+ const salt = "ect";
+ return await anastasisDecrypt(
+ asOpaque(truthEncKey),
+ asOpaque(truthEnc),
+ salt,
+ );
+}
+
export interface CoreSecretEncResult {
encCoreSecret: EncryptedCoreSecret;
encMasterKeys: EncryptedMasterKey[];