You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys-App/src/lib/dkc/encrypt.ts

86 lines
3.7 KiB

// The writers: encryptFiles writes a .dkc of capsule format 3, with, when
// asked, a portable .dkk (spec §61, §62, §62.1), as capsule.EncryptFiles of
// the Go reference at spec-v0.11; encrypt, as capsule.Encrypt, writes format
// 2 only for a generator of test vectors, which these options cannot ask
// for. Their random values all come from crypto.getRandomValues (§62.1 rule
// 5); the core of writer.ts, which takes them from its caller, is imported
// only here and by the helpers of the tests. Loaded on demand: index.ts does
// not re-export it.
import { cryptoWords } from './random.ts';
import {
type Draws,
type EncryptOptions,
type Encrypted,
type EncryptSource,
type FileSource,
MAX_MEMORY_DKC,
writeCapsule,
writeFiles,
} from './writer.ts';
import { newX25519Identity } from './x25519.ts';
export type { EncryptOptions, Encrypted, EncryptSource, FileSource };
export { MAX_MEMORY_DKC };
/**
* Writes a .dkc of format 3 holding `files`, and the comment and declared
* author of `opts`. It needs no network: the round is resolved locally, and
* tlock uses only the pinned public key.
*
* It reads each file twice, and writes nothing before the second reading.
* First it checks the paths and the texts with the rules of the reader,
* measures L with a head whose salt and SHA-256 are zero, as long as the
* final one, and hashes each file. Then it seals the control, with L, and
* streams PAYLOAD_AGE, reading each file again: a file whose size or SHA-256
* has changed makes it fail (§62.1 rule 18). The files go in the byte order
* of their paths, whatever the order given (R8), without the empty folders,
* which a path cannot name. The security area is the empty one of this
* library, which does not sign, in an area of 32 KiB, whatever the capsule
* holds (rule 13); `opts.publicNote` goes in PUBLIC_HEADER (§24.1).
*
* Without `opts.output` the .dkc is returned in memory, up to
* MAX_MEMORY_DKC; with it, the .dkc is streamed into the output, closed only
* once the capsule is complete and checked and aborted on any failure. The
* checks, codes and texts are those of capsule.EncryptFiles, in its order;
* `opts.length` is for encrypt, and L is the length of BODY.
*/
export function encryptFiles(files: readonly FileSource[], opts: EncryptOptions): Promise<Encrypted> {
return writeFiles(files, opts, cryptoDraws());
}
/**
* capsule.Encrypt, which writes a .dkc of format 2 only for a generator of
* test vectors (§62.1 rule 1, §70): no option of a caller asks for it, so it
* fails with the text of Go, and its output, if any, is aborted. Capsules
* are written with encryptFiles. The tests write format 2 with the helpers of
* testing/encrypt.ts, which pass the core what only they may ask.
*/
export function encrypt(src: EncryptSource, opts: EncryptOptions): Promise<Encrypted> {
return writeCapsule(src, opts, cryptoDraws());
}
/**
* The FileSource of a File or another Blob: its path in the capsule, its
* size, its modification time, File.lastModified unless given, and its
* stream, read twice.
*/
export function fileSource(path: string, blob: Blob, mtime?: number): FileSource {
const lastModified = mtime ?? (blob instanceof File ? blob.lastModified : undefined);
return { path, size: blob.size, ...(lastModified === undefined ? {} : { mtime: lastModified }), open: () => blob.stream() };
}
// Every random value of the writer from crypto.getRandomValues.
function cryptoDraws(): Draws {
const bytes = (n: number) => (): Uint8Array => crypto.getRandomValues(new Uint8Array(n));
return {
capsuleId: bytes(16),
payloadIdentity: newX25519Identity,
accessIdentity: newX25519Identity,
dummy: newX25519Identity,
words: cryptoWords(),
credentialId: bytes(16),
salt: bytes(32),
};
}

Powered by TurnKey Linux.