tink-crypto
Version:
A multi-language, cross-platform library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.
125 lines • 13.5 kB
JavaScript
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { InvalidArgumentsException } from '../../exception/invalid_arguments_exception';
import { SecurityException } from '../../exception/security_exception';
import * as bytes from '../../subtle/bytes';
/**
* The only supported IV size.
*
*/
export const IV_SIZE_IN_BYTES = 12;
/**
* The only supported tag size.
*
*/
const TAG_SIZE_IN_BYTES = 16;
/**
* Insecure version of `subtle/aes_gcm.ts` that allows the caller to set
* the IV.
*
* @final
*/
export class InsecureIvAesGcm {
constructor({ key, prependIv }) {
this.key = key;
this.prependIv = prependIv;
}
encrypt(iv, plaintext, associatedData) {
return __awaiter(this, void 0, void 0, function* () {
if (iv.length !== IV_SIZE_IN_BYTES) {
throw new SecurityException(`IV must be ${IV_SIZE_IN_BYTES} bytes`);
}
const alg = {
'name': 'AES-GCM',
'iv': iv,
'tagLength': TAG_SIZE_IN_BYTES * 8
};
if (associatedData) {
alg.additionalData = associatedData;
}
const ciphertext = yield self.crypto.subtle.encrypt(alg, this.key, plaintext);
return (this.prependIv ? bytes.concat(iv, new Uint8Array(ciphertext)) :
new Uint8Array(ciphertext));
});
}
decrypt(iv, ciphertext, associatedData) {
return __awaiter(this, void 0, void 0, function* () {
const expectedLength = this.prependIv ?
IV_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES :
TAG_SIZE_IN_BYTES;
if (ciphertext.length < expectedLength) {
throw new SecurityException('ciphertext too short');
}
if (iv.length !== IV_SIZE_IN_BYTES) {
throw new SecurityException(`IV must be ${IV_SIZE_IN_BYTES} bytes`);
}
const alg = {
'name': 'AES-GCM',
'iv': iv,
'tagLength': TAG_SIZE_IN_BYTES * 8
};
if (associatedData) {
alg.additionalData = associatedData;
}
const ciphertextWithoutIv = this.prependIv ?
new Uint8Array(ciphertext.subarray(IV_SIZE_IN_BYTES)) :
ciphertext;
try {
return new Uint8Array(yield self.crypto.subtle.decrypt(alg, this.key, ciphertextWithoutIv));
// Preserving old behavior when moving to
// https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables
// tslint:disable-next-line:no-any
}
catch (e) {
throw new SecurityException(e.toString());
}
});
}
}
/**
* Returns an instantiated `InsecureIvAesGcm` given a raw byte array `key`
* and `prependIv` flag.
*/
export function insecureIvAesGcmFromRawKey({ key, prependIv }) {
return __awaiter(this, void 0, void 0, function* () {
validateAesKeySize(key.length);
const webCryptoKey = yield self.crypto.subtle.importKey(
/* format */
'raw', key,
/* keyData */
{ 'name': 'AES-GCM', 'length': key.length },
/* algo */
false,
/* extractable*/
['encrypt', 'decrypt']);
/* usage */
return new InsecureIvAesGcm({ key: webCryptoKey, prependIv });
});
}
/**
* Validates AES key sizes (only 128-bit and 256-bit keys are supported).
*
* @param n the key size in bytes
* @throws {!InvalidArgumentsException}
*
* Copied from `javascript/subtle/validators`
* TODO(b/201071402#comment8): Delete once circular dependency is resolved
*/
function validateAesKeySize(n) {
if (![16, 32].includes(n)) {
throw new InvalidArgumentsException('unsupported AES key size: ${n}');
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zZWN1cmVfaXZfYWVzX2djbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2FlYWQvaW50ZXJuYWwvaW5zZWN1cmVfaXZfYWVzX2djbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHOzs7Ozs7Ozs7O0FBRUgsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0sNkNBQTZDLENBQUM7QUFDdEYsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sb0NBQW9DLENBQUM7QUFFckUsT0FBTyxLQUFLLEtBQUssTUFBTSxvQkFBb0IsQ0FBQztBQUU1Qzs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBVyxFQUFFLENBQUM7QUFFM0M7OztHQUdHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBVyxFQUFFLENBQUM7QUFFckM7Ozs7O0dBS0c7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBRzNCLFlBQVksRUFBQyxHQUFHLEVBQUUsU0FBUyxFQUMyQztRQUNwRSxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO0lBQzdCLENBQUM7SUFFSyxPQUFPLENBQ1QsRUFBYyxFQUFFLFNBQXFCLEVBQ3JDLGNBQTJCOztZQUM3QixJQUFJLEVBQUUsQ0FBQyxNQUFNLEtBQUssZ0JBQWdCLEVBQUU7Z0JBQ2xDLE1BQU0sSUFBSSxpQkFBaUIsQ0FBQyxjQUFjLGdCQUFnQixRQUFRLENBQUMsQ0FBQzthQUNyRTtZQUVELE1BQU0sR0FBRyxHQUFpQjtnQkFDeEIsTUFBTSxFQUFFLFNBQVM7Z0JBQ2pCLElBQUksRUFBRSxFQUFFO2dCQUNSLFdBQVcsRUFBRSxpQkFBaUIsR0FBRyxDQUFDO2FBQ25DLENBQUM7WUFDRixJQUFJLGNBQWMsRUFBRTtnQkFDbEIsR0FBRyxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7YUFDckM7WUFDRCxNQUFNLFVBQVUsR0FDWixNQUFN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QUN2RTtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCB7SW52YWxpZEFyZ3VtZW50c0V4Y2VwdGlvbn0gZnJvbSAnLi4vLi4vZXhjZXB0aW9uL2ludmFsaWRfYXJndW1lbnRzX2V4Y2VwdGlvbic7XG5pbXBvcnQge1NlY3VyaXR5RXhjZXB0aW9ufSBmcm9tICcuLi8uLi9leGNlcHRpb24vc2VjdXJpdHlfZXhjZXB0aW9uJztcblxuaW1wb3J0ICogYXMgYnl0ZXMgZnJvbSAnLi4vLi4vc3VidGxlL2J5dGVzJztcblxuLyoqXG4gKiBUaGUgb25seSBzdXBwb3J0ZWQgSVYgc2l6ZS5cbiAqXG4gKi9cbmV4cG9ydCBjb25zdCBJVl9TSVpFX0lOX0JZVEVTOiBudW1iZXIgPSAxMjtcblxuLyoqXG4gKiBUaGUgb25seSBzdXBwb3J0ZWQgdGFnIHNpemUuXG4gKlxuICovXG5jb25zdCBUQUdfU0laRV9JTl9CWVRFUzogbnVtYmVyID0gMTY7XG5cbi8qKlxuICogSW5zZWN1cmUgdmVyc2lvbiBvZiBgc3VidGxlL2Flc19nY20udHNgIHRoYXQgYWxsb3dzIHRoZSBjYWxsZXIgdG8gc2V0XG4gKiB0aGUgSVYuXG4gKlxuICogQGZpbmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBJbnNlY3VyZUl2QWVzR2NtIHtcbiAgcHJpdmF0ZSByZWFkb25seSBrZXk6IENyeXB0b0tleTtcbiAgcHJpdmF0ZSByZWFkb25seSBwcmVwZW5kSXY6IGJvb2xlYW47XG4gIGNvbnN0cnVjdG9yKHtrZXksIHByZXBlbmRJdn06XG4gICAgICAgICAgICAgICAgICB7cmVhZG9ubHkga2V5OiBDcnlwdG9LZXksIHJlYWRvbmx5IHByZXBlbmRJdjogYm9vbGVhbn0pIHtcbiAgICB0aGlzLmtleSA9IGtleTtcbiAgICB0aGlzLnByZXBlbmRJdiA9IHByZXBlbmRJdjtcbiAgfVxuXG4gIGFzeW5jIGVuY3J5cHQoXG4gICAgICBpdjogVWludDhBcnJheSwgcGxhaW50ZXh0OiBVaW50OEFycmF5LFxuICAgICAgYXNzb2NpYXRlZERhdGE/OiBVaW50OEFycmF5KTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gICAgaWYgKGl2Lmxlbmd0aCAhPT0gSVZfU0laRV9JTl9CWVRFUykge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKGBJViBtdXN0IGJlICR7SVZfU0laRV9JTl9CWVRFU30gYnl0ZXNgKTtcbiAgICB9XG5cbiAgICBjb25zdCBhbGc6IEFlc0djbVBhcmFtcyA9IHtcbiAgICAgICduYW1lJzogJ0FFUy1HQ00nLFxuICAgICAgJ2l2JzogaXYsXG4gICAgICAndGFnTGVuZ3RoJzogVEFHX1NJWkVfSU5fQllURVMgKiA4XG4gICAgfTtcbiAgICBpZiAoYXNzb2NpYXRlZERhdGEpIHtcbiAgICAgIGFsZy5hZGRpdGlvbmFsRGF0YSA9IGFzc29jaWF0ZWREYXRhO1xuICAgIH1cbiAgICBjb25zdCBjaXBoZXJ0ZXh0ID1cbiAgICAgICAgYXdhaXQgc2VsZi5jcnlwdG8uc3VidGxlLmVuY3J5cHQoYWxnLCB0aGlzLmtleSwgcGxhaW50ZXh0KTtcblxuICAgIHJldHVybiAoXG4gICAgICAgIHRoaXMucHJlcGVuZEl2ID8gYnl0ZXMuY29uY2F0KGl2LCBuZXcgVWludDhBcnJheShjaXBoZXJ0ZXh0KSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KGNpcGhlcnRleHQpKTtcbiAgfVxuXG4gIGFzeW5jIGRlY3J5cHQoXG4gICAgICBpdjogVWludDhBcnJheSwgY2lwaGVydGV4dDogVWludDhBcnJheSxcbiAgICAgIGFzc29jaWF0ZWREYXRhPzogVWludDhBcnJheSk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIGNvbnN0IGV4cGVjdGVkTGVuZ3RoID0gdGhpcy5wcmVwZW5kSXYgP1xuICAgICAgICBJVl9TSVpFX0lOX0JZVEVTICsgVEFHX1NJWkVfSU5fQllURVMgOlxuICAgICAgICBUQUdfU0laRV9JTl9CWVRFUztcblxuICAgIGlmIChjaXBoZXJ0ZXh0Lmxlbmd0aCA8IGV4cGVjdGVkTGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ2NpcGhlcnRleHQgdG9vIHNob3J0Jyk7XG4gICAgfVxuXG4gICAgaWYgKGl2Lmxlbmd0aCAhPT0gSVZfU0laRV9JTl9CWVRFUykge1xuICAgICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKGBJViBtdXN0IGJlICR7SVZfU0laRV9JTl9CWVRFU30gYnl0ZXNgKTtcbiAgICB9XG5cbiAgICBjb25zdCBhbGc6IEFlc0djbVBhcmFtcyA9IHtcbiAgICAgICduYW1lJzogJ0FFUy1HQ00nLFxuICAgICAgJ2l2JzogaXYsXG4gICAgICAndGFnTGVuZ3RoJzogVEFHX1NJWkVfSU5fQllURVMgKiA4XG4gICAgfTtcbiAgICBpZiAoYXNzb2NpYXRlZERhdGEpIHtcbiAgICAgIGFsZy5hZGRpdGlvbmFsRGF0YSA9IGFzc29jaWF0ZWREYXRhO1xuICAgIH1cbiAgICBjb25zdCBjaXBoZXJ0ZXh0V2l0aG91dEl2ID0gdGhpcy5wcmVwZW5kSXYgP1xuICAgICAgICBuZXcgVWludDhBcnJheShjaXBoZXJ0ZXh0LnN1YmFycmF5KElWX1NJWkVfSU5fQllURVMpKSA6XG4gICAgICAgIGNpcGhlcnRleHQ7XG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFxuICAgICAgICAgIGF3YWl0IHNlbGYuY3J5cHRvLnN1YnRsZS5kZWNyeXB0KGFsZywgdGhpcy5rZXksIGNpcGhlcnRleHRXaXRob3V0SXYpKTtcbiAgICAgIC8vIFByZXNlcnZpbmcgb2xkIGJlaGF2aW9yIHdoZW4gbW92aW5nIHRvXG4gICAgICAvLyBodHRwczovL3d3dy50eXBlc2NyaXB0bGFuZy5vcmcvdHNjb25maWcjdXNlVW5rbm93bkluQ2F0Y2hWYXJpYWJsZXNcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbihlLnRvU3RyaW5nKCkpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgYW4gaW5zdGFudGlhdGVkIGBJbnNlY3VyZUl2QWVzR2NtYCBnaXZlbiBhIHJhdyBieXRlIGFycmF5IGBrZXlgXG4gKiBhbmQgYHByZXBlbmRJdmAgZmxhZy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc2VjdXJlSXZBZXNHY21Gcm9tUmF3S2V5KFxuICAgIHtrZXksIHByZXBlbmRJdn06IHtrZXk6IFVpbnQ4QXJyYXksIHByZXBlbmRJdjogYm9vbGVhbn0pOlxuICAgIFByb21pc2U8SW5zZWN1cmVJdkFlc0djbT4ge1xuICB2YWxpZGF0ZUFlc0tleVNpemUoa2V5Lmxlbmd0aCk7XG4gIGNvbnN0IHdlYkNyeXB0b0tleSA9IGF3YWl0IHNlbGYuY3J5cHRvLnN1YnRsZS5pbXBvcnRLZXkoXG4gICAgICAvKiBmb3JtYXQgKi9cbiAgICAgICdyYXcnLCBrZXksXG4gICAgICAvKiBrZXlEYXRhICovXG4gICAgICB7J25hbWUnOiAnQUVTLUdDTScsICdsZW5ndGgnOiBrZXkubGVuZ3RofSxcbiAgICAgIC8qIGFsZ28gKi9cbiAgICAgIGZhbHNlLFxuICAgICAgLyogZXh0cmFjdGFibGUqL1xuICAgICAgWydlbmNyeXB0JywgJ2RlY3J5cHQnXSk7XG5cbiAgLyogdXNhZ2UgKi9cbiAgcmV0dXJuIG5ldyBJbnNlY3VyZUl2QWVzR2NtKHtrZXk6IHdlYkNyeXB0b0tleSwgcHJlcGVuZEl2fSk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIEFFUyBrZXkgc2l6ZXMgKG9ubHkgMTI4LWJpdCBhbmQgMjU2LWJpdCBrZXlzIGFyZSBzdXBwb3J0ZWQpLlxuICpcbiAqIEBwYXJhbSBuIHRoZSBrZXkgc2l6ZSBpbiBieXRlc1xuICogQHRocm93cyB7IUludmFsaWRBcmd1bWVudHNFeGNlcHRpb259XG4gKlxuICogQ29waWVkIGZyb20gYGphdmFzY3JpcHQvc3VidGxlL3ZhbGlkYXRvcnNgXG4gKiBUT0RPKGIvMjAxMDcxNDAyI2NvbW1lbnQ4KTogRGVsZXRlIG9uY2UgY2lyY3VsYXIgZGVwZW5kZW5jeSBpcyByZXNvbHZlZFxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUFlc0tleVNpemUobjogbnVtYmVyKSB7XG4gIGlmICghWzE2LCAzMl0uaW5jbHVkZXMobikpIHtcbiAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ3VtZW50c0V4Y2VwdGlvbigndW5zdXBwb3J0ZWQgQUVTIGtleSBzaXplOiAke259Jyk7XG4gIH1cbn1cbiJdfQ==