Use WeakMap to protect private data

This commit is contained in:
microshine 2020-03-13 18:20:02 +03:00
parent 0dd1c1e459
commit fd98284182
19 changed files with 192 additions and 126 deletions

View File

@ -1,2 +1,2 @@
export { CryptoKey } from "./keys"; export { CryptoKey } from "webcrypto-core";
export { Crypto } from "./crypto"; export { Crypto } from "./crypto";

View File

@ -1,4 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { getCryptoKey, setCryptoKey } from "../storage";
import { AesCrypto } from "./crypto"; import { AesCrypto } from "./crypto";
import { AesCryptoKey } from "./key"; import { AesCryptoKey } from "./key";
@ -13,28 +14,29 @@ export class AesCbcProvider extends core.AesCbcProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return AesCrypto.exportKey(format, key); return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); const key = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) { if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
throw new TypeError("key: Is not a AesCryptoKey"); throw new TypeError("key: Is not a AesCryptoKey");
} }
} }

View File

@ -1,5 +1,6 @@
import * as crypto from "crypto"; import * as crypto from "crypto";
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { AesCrypto } from "./crypto"; import { AesCrypto } from "./crypto";
import { AesCryptoKey } from "./key"; import { AesCryptoKey } from "./key";
@ -121,11 +122,11 @@ export class AesCmacProvider extends core.AesCmacProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onSign(algorithm: AesCmacParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onSign(algorithm: AesCmacParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
const result = aesCmac(key.data, Buffer.from(data)); const result = aesCmac(getCryptoKey(key).data, Buffer.from(data));
return new Uint8Array(result).buffer; return new Uint8Array(result).buffer;
} }
@ -135,16 +136,17 @@ export class AesCmacProvider extends core.AesCmacProvider {
} }
public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return AesCrypto.exportKey(format, key); return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
return setCryptoKey(res);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) { if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
throw new TypeError("key: Is not a AesCryptoKey"); throw new TypeError("key: Is not a AesCryptoKey");
} }
} }

View File

@ -1,4 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { AesCrypto } from "./crypto"; import { AesCrypto } from "./crypto";
import { AesCryptoKey } from "./key"; import { AesCryptoKey } from "./key";
@ -13,28 +14,29 @@ export class AesCtrProvider extends core.AesCtrProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onEncrypt(algorithm: AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return AesCrypto.exportKey(format, key); return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
return setCryptoKey(res);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) { if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
throw new TypeError("key: Is not a AesCryptoKey"); throw new TypeError("key: Is not a AesCryptoKey");
} }
} }

View File

@ -1,4 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { AesCrypto } from "./crypto"; import { AesCrypto } from "./crypto";
import { AesCryptoKey } from "./key"; import { AesCryptoKey } from "./key";
@ -13,28 +14,29 @@ export class AesEcbProvider extends core.AesEcbProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return AesCrypto.exportKey(format, key); return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
return setCryptoKey(res);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) { if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
throw new TypeError("key: Is not a AesCryptoKey"); throw new TypeError("key: Is not a AesCryptoKey");
} }
} }

View File

@ -1,4 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { AesCrypto } from "./crypto"; import { AesCrypto } from "./crypto";
import { AesCryptoKey } from "./key"; import { AesCryptoKey } from "./key";
@ -13,28 +14,29 @@ export class AesGcmProvider extends core.AesGcmProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onEncrypt(algorithm: AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return AesCrypto.exportKey(format, key); return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
return setCryptoKey(res);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) { if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
throw new TypeError("key: Is not a AesCryptoKey"); throw new TypeError("key: Is not a AesCryptoKey");
} }
} }

View File

@ -1,11 +1,12 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { AesCrypto } from "./crypto"; import { AesCrypto } from "./crypto";
import { AesCryptoKey } from "./key"; import { AesCryptoKey } from "./key";
export class AesKwProvider extends core.AesKwProvider { export class AesKwProvider extends core.AesKwProvider {
public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return await AesCrypto.generateKey( const res = await AesCrypto.generateKey(
{ {
name: this.name, name: this.name,
length: algorithm.length, length: algorithm.length,
@ -13,27 +14,29 @@ export class AesKwProvider extends core.AesKwProvider {
extractable, extractable,
keyUsages, keyUsages,
); );
return setCryptoKey(res);
} }
public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return AesCrypto.exportKey(format, key); return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
return AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages);
return setCryptoKey(res);
} }
public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return AesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data));
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof AesCryptoKey)) { if (!(getCryptoKey(key) instanceof AesCryptoKey)) {
throw new TypeError("key: Is not a AesCryptoKey"); throw new TypeError("key: Is not a AesCryptoKey");
} }
} }

View File

@ -1,5 +1,6 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { CryptoKey } from "../../keys";
import { setCryptoKey, getCryptoKey } from "../storage";
import { DesCrypto } from "./crypto"; import { DesCrypto } from "./crypto";
import { DesCryptoKey } from "./key"; import { DesCryptoKey } from "./key";
@ -11,7 +12,7 @@ export class DesCbcProvider extends core.DesProvider {
public ivSize = 8; public ivSize = 8;
public name = "DES-CBC"; public name = "DES-CBC";
public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<core.CryptoKey> {
const key = await DesCrypto.generateKey( const key = await DesCrypto.generateKey(
{ {
name: this.name, name: this.name,
@ -20,32 +21,32 @@ export class DesCbcProvider extends core.DesProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onEncrypt(algorithm: DesCbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: DesCbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return DesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return DesCrypto.encrypt(algorithm, getCryptoKey(key) as DesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: DesCbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: DesCbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return DesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return DesCrypto.decrypt(algorithm, getCryptoKey(key) as DesCryptoKey, new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return DesCrypto.exportKey(format, key); return DesCrypto.exportKey(format, getCryptoKey(key) as DesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<core.CryptoKey> {
const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages); const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages);
if (key.data.length !== (this.keySizeBits >> 3)) { if (key.data.length !== (this.keySizeBits >> 3)) {
throw new core.OperationError("keyData: Wrong key size"); throw new core.OperationError("keyData: Wrong key size");
} }
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof DesCryptoKey)) { if (!(getCryptoKey(key) instanceof DesCryptoKey)) {
throw new TypeError("key: Is not a DesCryptoKey"); throw new TypeError("key: Is not a DesCryptoKey");
} }
} }

View File

@ -1,5 +1,6 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { CryptoKey } from "../../keys";
import { setCryptoKey, getCryptoKey } from "../storage";
import { DesCrypto } from "./crypto"; import { DesCrypto } from "./crypto";
import { DesCryptoKey } from "./key"; import { DesCryptoKey } from "./key";
@ -11,7 +12,7 @@ export class DesEde3CbcProvider extends core.DesProvider {
public ivSize = 8; public ivSize = 8;
public name = "DES-EDE3-CBC"; public name = "DES-EDE3-CBC";
public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<core.CryptoKey> {
const key = await DesCrypto.generateKey( const key = await DesCrypto.generateKey(
{ {
name: this.name, name: this.name,
@ -20,32 +21,32 @@ export class DesEde3CbcProvider extends core.DesProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return setCryptoKey(key);
} }
public async onEncrypt(algorithm: DesEde3CbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: DesEde3CbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return DesCrypto.encrypt(algorithm, key, new Uint8Array(data)); return DesCrypto.encrypt(algorithm, getCryptoKey(key) as DesCryptoKey, new Uint8Array(data));
} }
public async onDecrypt(algorithm: DesEde3CbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: DesEde3CbcParams, key: DesCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return DesCrypto.decrypt(algorithm, key, new Uint8Array(data)); return DesCrypto.decrypt(algorithm, getCryptoKey(key) as DesCryptoKey, new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return DesCrypto.exportKey(format, key); return DesCrypto.exportKey(format, getCryptoKey(key) as DesCryptoKey);
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<core.CryptoKey> {
const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages); const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages);
if (key.data.length !== (this.keySizeBits >> 3)) { if (key.data.length !== (this.keySizeBits >> 3)) {
throw new core.OperationError("keyData: Wrong key size"); throw new core.OperationError("keyData: Wrong key size");
} }
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof DesCryptoKey)) { if (!(getCryptoKey(key) instanceof DesCryptoKey)) {
throw new TypeError("key: Is not a DesCryptoKey"); throw new TypeError("key: Is not a DesCryptoKey");
} }
} }

View File

@ -1,5 +1,6 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { CryptoKey } from "../../keys";
import { setCryptoKey, getCryptoKey } from "../storage";
import { EcCrypto } from "./crypto"; import { EcCrypto } from "./crypto";
import { EcPrivateKey } from "./private_key"; import { EcPrivateKey } from "./private_key";
import { EcPublicKey } from "./public_key"; import { EcPublicKey } from "./public_key";
@ -7,7 +8,7 @@ import { EcPublicKey } from "./public_key";
export class EcdhProvider extends core.EcdhProvider { export class EcdhProvider extends core.EcdhProvider {
public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> { public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> {
const key = await EcCrypto.generateKey( const keys = await EcCrypto.generateKey(
{ {
...algorithm, ...algorithm,
name: this.name, name: this.name,
@ -15,27 +16,31 @@ export class EcdhProvider extends core.EcdhProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return {
privateKey: setCryptoKey(keys.privateKey as CryptoKey),
publicKey: setCryptoKey(keys.publicKey as CryptoKey),
};
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return EcCrypto.exportKey(format, key); return EcCrypto.exportKey(format, getCryptoKey(key));
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<core.CryptoKey> {
const key = await EcCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages); const key = await EcCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages);
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof EcPrivateKey || key instanceof EcPublicKey)) { const internalKey = getCryptoKey(key);
if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) {
throw new TypeError("key: Is not EC CryptoKey"); throw new TypeError("key: Is not EC CryptoKey");
} }
} }
public async onDeriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise<ArrayBuffer> { public async onDeriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise<ArrayBuffer> {
const bits = await EcCrypto.deriveBits(algorithm, baseKey, length); const bits = await EcCrypto.deriveBits({...algorithm, public: getCryptoKey(algorithm.public)}, getCryptoKey(baseKey), length);
return bits; return bits;
} }

View File

@ -1,5 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { setCryptoKey, getCryptoKey } from "../storage";
import { EcCrypto } from "./crypto"; import { EcCrypto } from "./crypto";
import { EcPrivateKey } from "./private_key"; import { EcPrivateKey } from "./private_key";
import { EcPublicKey } from "./public_key"; import { EcPublicKey } from "./public_key";
@ -9,7 +9,7 @@ export class EcdsaProvider extends core.EcdsaProvider {
public namedCurves = ["P-256", "P-384", "P-521", "K-256"]; public namedCurves = ["P-256", "P-384", "P-521", "K-256"];
public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> { public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> {
const key = await EcCrypto.generateKey( const keys = await EcCrypto.generateKey(
{ {
...algorithm, ...algorithm,
name: this.name, name: this.name,
@ -17,29 +17,33 @@ export class EcdsaProvider extends core.EcdsaProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return {
privateKey: setCryptoKey(keys.privateKey as EcPrivateKey),
publicKey: setCryptoKey(keys.publicKey as EcPublicKey),
};
} }
public async onSign(algorithm: EcdsaParams, key: EcPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onSign(algorithm: EcdsaParams, key: EcPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return EcCrypto.sign(algorithm, key, new Uint8Array(data)); return EcCrypto.sign(algorithm, getCryptoKey(key) as EcPrivateKey, new Uint8Array(data));
} }
public async onVerify(algorithm: EcdsaParams, key: EcPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> { public async onVerify(algorithm: EcdsaParams, key: EcPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> {
return EcCrypto.verify(algorithm, key, new Uint8Array(signature), new Uint8Array(data)); return EcCrypto.verify(algorithm, getCryptoKey(key) as EcPublicKey, new Uint8Array(signature), new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return EcCrypto.exportKey(format, key); return EcCrypto.exportKey(format, getCryptoKey(key));
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof EcPrivateKey || key instanceof EcPublicKey)) { const internalKey = getCryptoKey(key);
if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) {
throw new TypeError("key: Is not EC CryptoKey"); throw new TypeError("key: Is not EC CryptoKey");
} }
} }

View File

@ -1,6 +1,7 @@
import crypto from "crypto"; import crypto from "crypto";
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { BufferSourceConverter, CryptoKey } from "webcrypto-core"; import { BufferSourceConverter, CryptoKey } from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { HkdfCryptoKey } from "./key"; import { HkdfCryptoKey } from "./key";
export class HkdfProvider extends core.HkdfProvider { export class HkdfProvider extends core.HkdfProvider {
@ -15,7 +16,7 @@ export class HkdfProvider extends core.HkdfProvider {
key.algorithm = { name: this.name }; key.algorithm = { name: this.name };
key.extractable = extractable; key.extractable = extractable;
key.usages = keyUsages; key.usages = keyUsages;
return key; return setCryptoKey(key);
} }
public async onDeriveBits(params: HkdfParams, baseKey: HkdfCryptoKey, length: number): Promise<ArrayBuffer> { public async onDeriveBits(params: HkdfParams, baseKey: HkdfCryptoKey, length: number): Promise<ArrayBuffer> {
@ -26,7 +27,7 @@ export class HkdfProvider extends core.HkdfProvider {
const info = BufferSourceConverter.toUint8Array(params.info); const info = BufferSourceConverter.toUint8Array(params.info);
const PRK = crypto.createHmac(hash, BufferSourceConverter.toUint8Array(params.salt)) const PRK = crypto.createHmac(hash, BufferSourceConverter.toUint8Array(params.salt))
.update(BufferSourceConverter.toUint8Array(baseKey.data)) .update(BufferSourceConverter.toUint8Array(getCryptoKey(baseKey).data))
.digest(); .digest();
const blocks = [Buffer.alloc(0)]; const blocks = [Buffer.alloc(0)];
@ -44,7 +45,7 @@ export class HkdfProvider extends core.HkdfProvider {
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof HkdfCryptoKey)) { if (!(getCryptoKey(key) instanceof HkdfCryptoKey)) {
throw new TypeError("key: Is not HKDF CryptoKey"); throw new TypeError("key: Is not HKDF CryptoKey");
} }
} }

View File

@ -1,6 +1,7 @@
import crypto from "crypto"; import crypto from "crypto";
import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { HmacCryptoKey } from "./key"; import { HmacCryptoKey } from "./key";
export class HmacProvider extends core.HmacProvider { export class HmacProvider extends core.HmacProvider {
@ -16,12 +17,12 @@ export class HmacProvider extends core.HmacProvider {
key.usages = keyUsages; key.usages = keyUsages;
key.data = crypto.randomBytes(length >> 3); key.data = crypto.randomBytes(length >> 3);
return key; return setCryptoKey(key);
} }
public async onSign(algorithm: Algorithm, key: HmacCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onSign(algorithm: Algorithm, key: HmacCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
const hash = key.algorithm.hash.name.replace("-", ""); const hash = key.algorithm.hash.name.replace("-", "");
const hmac = crypto.createHmac(hash, key.data) const hmac = crypto.createHmac(hash, getCryptoKey(key).data)
.update(Buffer.from(data)).digest(); .update(Buffer.from(data)).digest();
return new Uint8Array(hmac).buffer; return new Uint8Array(hmac).buffer;
@ -29,7 +30,7 @@ export class HmacProvider extends core.HmacProvider {
public async onVerify(algorithm: Algorithm, key: HmacCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> { public async onVerify(algorithm: Algorithm, key: HmacCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> {
const hash = key.algorithm.hash.name.replace("-", ""); const hash = key.algorithm.hash.name.replace("-", "");
const hmac = crypto.createHmac(hash, key.data) const hmac = crypto.createHmac(hash, getCryptoKey(key).data)
.update(Buffer.from(data)).digest(); .update(Buffer.from(data)).digest();
return hmac.compare(Buffer.from(signature)) === 0; return hmac.compare(Buffer.from(signature)) === 0;
@ -58,15 +59,15 @@ export class HmacProvider extends core.HmacProvider {
key.extractable = extractable; key.extractable = extractable;
key.usages = keyUsages; key.usages = keyUsages;
return key; return setCryptoKey(key);
} }
public async onExportKey(format: KeyFormat, key: HmacCryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: HmacCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
switch (format.toLowerCase()) { switch (format.toLowerCase()) {
case "jwk": case "jwk":
return JsonSerializer.toJSON(key); return JsonSerializer.toJSON(getCryptoKey(key));
case "raw": case "raw":
return new Uint8Array(key.data).buffer; return new Uint8Array(getCryptoKey(key).data).buffer;
default: default:
throw new core.OperationError("format: Must be 'jwk' or 'raw'"); throw new core.OperationError("format: Must be 'jwk' or 'raw'");
} }
@ -74,7 +75,7 @@ export class HmacProvider extends core.HmacProvider {
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof HmacCryptoKey)) { if (!(getCryptoKey(key) instanceof HmacCryptoKey)) {
throw new TypeError("key: Is not HMAC CryptoKey"); throw new TypeError("key: Is not HMAC CryptoKey");
} }
} }

View File

@ -1,5 +1,6 @@
import crypto from "crypto"; import crypto from "crypto";
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { setCryptoKey, getCryptoKey } from "../storage";
import { PbkdfCryptoKey } from "./key"; import { PbkdfCryptoKey } from "./key";
export class Pbkdf2Provider extends core.Pbkdf2Provider { export class Pbkdf2Provider extends core.Pbkdf2Provider {
@ -8,7 +9,7 @@ export class Pbkdf2Provider extends core.Pbkdf2Provider {
return new Promise<ArrayBuffer>((resolve, reject) => { return new Promise<ArrayBuffer>((resolve, reject) => {
const salt = core.BufferSourceConverter.toArrayBuffer(algorithm.salt); const salt = core.BufferSourceConverter.toArrayBuffer(algorithm.salt);
const hash = (algorithm.hash as Algorithm).name.replace("-", ""); const hash = (algorithm.hash as Algorithm).name.replace("-", "");
crypto.pbkdf2(baseKey.data, Buffer.from(salt), algorithm.iterations, length >> 3, hash, (err, derivedBits) => { crypto.pbkdf2(getCryptoKey(baseKey).data, Buffer.from(salt), algorithm.iterations, length >> 3, hash, (err, derivedBits) => {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
@ -25,14 +26,14 @@ export class Pbkdf2Provider extends core.Pbkdf2Provider {
key.algorithm = { name: this.name }; key.algorithm = { name: this.name };
key.extractable = false; key.extractable = false;
key.usages = keyUsages; key.usages = keyUsages;
return key; return setCryptoKey(key);
} }
throw new core.OperationError("format: Must be 'raw'"); throw new core.OperationError("format: Must be 'raw'");
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof PbkdfCryptoKey)) { if (!(getCryptoKey(key) instanceof PbkdfCryptoKey)) {
throw new TypeError("key: Is not PBKDF CryptoKey"); throw new TypeError("key: Is not PBKDF CryptoKey");
} }
} }

View File

@ -1,7 +1,7 @@
import * as crypto from "crypto"; import * as crypto from "crypto";
import { Convert } from "pvtsutils"; import { Convert } from "pvtsutils";
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { setCryptoKey, getCryptoKey } from "../storage";
import { RsaCrypto } from "./crypto"; import { RsaCrypto } from "./crypto";
import { RsaPrivateKey } from "./private_key"; import { RsaPrivateKey } from "./private_key";
import { RsaPublicKey } from "./public_key"; import { RsaPublicKey } from "./public_key";
@ -15,7 +15,7 @@ export class RsaEsProvider extends core.ProviderCrypto {
}; };
public async onGenerateKey(algorithm: RsaKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> { public async onGenerateKey(algorithm: RsaKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> {
const key = await RsaCrypto.generateKey( const keys = await RsaCrypto.generateKey(
{ {
...algorithm, ...algorithm,
name: this.name, name: this.name,
@ -23,7 +23,10 @@ export class RsaEsProvider extends core.ProviderCrypto {
extractable, extractable,
keyUsages); keyUsages);
return key; return {
privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey),
publicKey: setCryptoKey(keys.publicKey as RsaPublicKey),
};
} }
public checkGenerateKeyParams(algorithm: RsaKeyGenParams) { public checkGenerateKeyParams(algorithm: RsaKeyGenParams) {
@ -62,17 +65,18 @@ export class RsaEsProvider extends core.ProviderCrypto {
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return RsaCrypto.exportKey(format, key); return RsaCrypto.exportKey(format, getCryptoKey(key));
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof RsaPrivateKey || key instanceof RsaPublicKey)) { const internalKey = getCryptoKey(key);
if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
throw new TypeError("key: Is not RSA CryptoKey"); throw new TypeError("key: Is not RSA CryptoKey");
} }
} }
@ -82,7 +86,7 @@ export class RsaEsProvider extends core.ProviderCrypto {
private toCryptoOptions(key: RsaPrivateKey | RsaPublicKey) { private toCryptoOptions(key: RsaPrivateKey | RsaPublicKey) {
const type = key.type.toUpperCase(); const type = key.type.toUpperCase();
return { return {
key: `-----BEGIN ${type} KEY-----\n${key.data.toString("base64")}\n-----END ${type} KEY-----`, key: `-----BEGIN ${type} KEY-----\n${getCryptoKey(key).data.toString("base64")}\n-----END ${type} KEY-----`,
// @ts-ignore // @ts-ignore
padding: crypto.constants.RSA_PKCS1_PADDING, padding: crypto.constants.RSA_PKCS1_PADDING,
}; };

View File

@ -1,7 +1,7 @@
import crypto from "crypto"; import crypto from "crypto";
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys";
import { ShaCrypto } from "../sha/crypto"; import { ShaCrypto } from "../sha/crypto";
import { setCryptoKey, getCryptoKey } from "../storage";
import { RsaCrypto } from "./crypto"; import { RsaCrypto } from "./crypto";
import { RsaPrivateKey } from "./private_key"; import { RsaPrivateKey } from "./private_key";
import { RsaPublicKey } from "./public_key"; import { RsaPublicKey } from "./public_key";
@ -16,7 +16,7 @@ import { RsaPublicKey } from "./public_key";
export class RsaOaepProvider extends core.RsaOaepProvider { export class RsaOaepProvider extends core.RsaOaepProvider {
public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> { public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> {
const key = await RsaCrypto.generateKey( const keys = await RsaCrypto.generateKey(
{ {
...algorithm, ...algorithm,
name: this.name, name: this.name,
@ -24,13 +24,17 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return {
privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey),
publicKey: setCryptoKey(keys.publicKey as RsaPublicKey),
};
} }
public async onEncrypt(algorithm: RsaOaepParams, key: RsaPublicKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onEncrypt(algorithm: RsaOaepParams, key: RsaPublicKey, data: ArrayBuffer): Promise<ArrayBuffer> {
const internalKey = getCryptoKey(key) as RsaPublicKey;
const dataView = new Uint8Array(data); const dataView = new Uint8Array(data);
const keySize = Math.ceil(key.algorithm.modulusLength >> 3); const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3);
const hashSize = ShaCrypto.size(key.algorithm.hash) >> 3; const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3;
const dataLength = dataView.byteLength; const dataLength = dataView.byteLength;
const psLength = keySize - dataLength - 2 * hashSize - 2; const psLength = keySize - dataLength - 2 * hashSize - 2;
@ -44,7 +48,7 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
dataBlock.set(dataView, hashSize + psLength + 1); dataBlock.set(dataView, hashSize + psLength + 1);
const labelHash = crypto.createHash(key.algorithm.hash.name.replace("-", "")) const labelHash = crypto.createHash(internalKey.algorithm.hash.name.replace("-", ""))
.update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) .update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0)))
.digest(); .digest();
dataBlock.set(labelHash, 0); dataBlock.set(labelHash, 0);
@ -52,22 +56,22 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
crypto.randomFillSync(seed); crypto.randomFillSync(seed);
const dataBlockMask = this.mgf1(key.algorithm.hash, seed, dataBlock.length); const dataBlockMask = this.mgf1(internalKey.algorithm.hash, seed, dataBlock.length);
for (let i = 0; i < dataBlock.length; i++) { for (let i = 0; i < dataBlock.length; i++) {
dataBlock[i] ^= dataBlockMask[i]; dataBlock[i] ^= dataBlockMask[i];
} }
const seedMask = this.mgf1(key.algorithm.hash, dataBlock, seed.length); const seedMask = this.mgf1(internalKey.algorithm.hash, dataBlock, seed.length);
for (let i = 0; i < seed.length; i++) { for (let i = 0; i < seed.length; i++) {
seed[i] ^= seedMask[i]; seed[i] ^= seedMask[i];
} }
if (!key.pem) { if (!internalKey.pem) {
key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`; internalKey.pem = `-----BEGIN PUBLIC KEY-----\n${internalKey.data.toString("base64")}\n-----END PUBLIC KEY-----`;
} }
const pkcs0 = crypto.publicEncrypt({ const pkcs0 = crypto.publicEncrypt({
key: key.pem, key: internalKey.pem,
padding: crypto.constants.RSA_NO_PADDING, padding: crypto.constants.RSA_NO_PADDING,
}, Buffer.from(message)); }, Buffer.from(message));
@ -75,20 +79,21 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
} }
public async onDecrypt(algorithm: RsaOaepParams, key: RsaPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onDecrypt(algorithm: RsaOaepParams, key: RsaPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> {
const keySize = Math.ceil(key.algorithm.modulusLength >> 3); const internalKey = getCryptoKey(key) as RsaPrivateKey;
const hashSize = ShaCrypto.size(key.algorithm.hash) >> 3; const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3);
const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3;
const dataLength = data.byteLength; const dataLength = data.byteLength;
if (dataLength !== keySize) { if (dataLength !== keySize) {
throw new Error("Bad data"); throw new Error("Bad data");
} }
if (!key.pem) { if (!internalKey.pem) {
key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`; internalKey.pem = `-----BEGIN PRIVATE KEY-----\n${internalKey.data.toString("base64")}\n-----END PRIVATE KEY-----`;
} }
let pkcs0 = crypto.privateDecrypt({ let pkcs0 = crypto.privateDecrypt({
key: key.pem, key: internalKey.pem,
padding: crypto.constants.RSA_NO_PADDING, padding: crypto.constants.RSA_NO_PADDING,
}, Buffer.from(data)); }, Buffer.from(data));
const z = pkcs0[0]; const z = pkcs0[0];
@ -99,17 +104,17 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
throw new Error("Decryption failed"); throw new Error("Decryption failed");
} }
const seedMask = this.mgf1(key.algorithm.hash, dataBlock, seed.length); const seedMask = this.mgf1(internalKey.algorithm.hash, dataBlock, seed.length);
for (let i = 0; i < seed.length; i++) { for (let i = 0; i < seed.length; i++) {
seed[i] ^= seedMask[i]; seed[i] ^= seedMask[i];
} }
const dataBlockMask = this.mgf1(key.algorithm.hash, seed, dataBlock.length); const dataBlockMask = this.mgf1(internalKey.algorithm.hash, seed, dataBlock.length);
for (let i = 0; i < dataBlock.length; i++) { for (let i = 0; i < dataBlock.length; i++) {
dataBlock[i] ^= dataBlockMask[i]; dataBlock[i] ^= dataBlockMask[i];
} }
const labelHash = crypto.createHash(key.algorithm.hash.name.replace("-", "")) const labelHash = crypto.createHash(internalKey.algorithm.hash.name.replace("-", ""))
.update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) .update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0)))
.digest(); .digest();
for (let i = 0; i < hashSize; i++) { for (let i = 0; i < hashSize; i++) {
@ -138,17 +143,18 @@ export class RsaOaepProvider extends core.RsaOaepProvider {
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return RsaCrypto.exportKey(format, key); return RsaCrypto.exportKey(format, getCryptoKey(key));
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages);
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof RsaPrivateKey || key instanceof RsaPublicKey)) { const internalKey = getCryptoKey(key);
if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
throw new TypeError("key: Is not RSA CryptoKey"); throw new TypeError("key: Is not RSA CryptoKey");
} }
} }

View File

@ -1,5 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { setCryptoKey, getCryptoKey } from "../storage";
import { RsaCrypto } from "./crypto"; import { RsaCrypto } from "./crypto";
import { RsaPrivateKey } from "./private_key"; import { RsaPrivateKey } from "./private_key";
import { RsaPublicKey } from "./public_key"; import { RsaPublicKey } from "./public_key";
@ -7,7 +7,7 @@ import { RsaPublicKey } from "./public_key";
export class RsaPssProvider extends core.RsaPssProvider { export class RsaPssProvider extends core.RsaPssProvider {
public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> { public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> {
const key = await RsaCrypto.generateKey( const keys = await RsaCrypto.generateKey(
{ {
...algorithm, ...algorithm,
name: this.name, name: this.name,
@ -15,29 +15,33 @@ export class RsaPssProvider extends core.RsaPssProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return {
privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey),
publicKey: setCryptoKey(keys.publicKey as RsaPublicKey),
};
} }
public async onSign(algorithm: RsaPssParams, key: RsaPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onSign(algorithm: RsaPssParams, key: RsaPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return RsaCrypto.sign(algorithm, key, new Uint8Array(data)); return RsaCrypto.sign(algorithm, getCryptoKey(key) as RsaPrivateKey, new Uint8Array(data));
} }
public async onVerify(algorithm: RsaPssParams, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> { public async onVerify(algorithm: RsaPssParams, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> {
return RsaCrypto.verify(algorithm, key, new Uint8Array(signature), new Uint8Array(data)); return RsaCrypto.verify(algorithm, getCryptoKey(key) as RsaPublicKey, new Uint8Array(signature), new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return RsaCrypto.exportKey(format, key); return RsaCrypto.exportKey(format, getCryptoKey(key));
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
const key = await RsaCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages); const key = await RsaCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages);
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof RsaPrivateKey || key instanceof RsaPublicKey)) { const internalKey = getCryptoKey(key);
if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
throw new TypeError("key: Is not RSA CryptoKey"); throw new TypeError("key: Is not RSA CryptoKey");
} }
} }

View File

@ -1,5 +1,5 @@
import * as core from "webcrypto-core"; import * as core from "webcrypto-core";
import { CryptoKey } from "../../keys"; import { setCryptoKey, getCryptoKey } from "../storage";
import { RsaCrypto } from "./crypto"; import { RsaCrypto } from "./crypto";
import { RsaPrivateKey } from "./private_key"; import { RsaPrivateKey } from "./private_key";
import { RsaPublicKey } from "./public_key"; import { RsaPublicKey } from "./public_key";
@ -7,7 +7,7 @@ import { RsaPublicKey } from "./public_key";
export class RsaSsaProvider extends core.RsaSsaProvider { export class RsaSsaProvider extends core.RsaSsaProvider {
public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> { public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair> {
const key = await RsaCrypto.generateKey( const keys = await RsaCrypto.generateKey(
{ {
...algorithm, ...algorithm,
name: this.name, name: this.name,
@ -15,29 +15,33 @@ export class RsaSsaProvider extends core.RsaSsaProvider {
extractable, extractable,
keyUsages); keyUsages);
return key; return {
privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey),
publicKey: setCryptoKey(keys.publicKey as RsaPublicKey),
};
} }
public async onSign(algorithm: Algorithm, key: RsaPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> { public async onSign(algorithm: Algorithm, key: RsaPrivateKey, data: ArrayBuffer): Promise<ArrayBuffer> {
return RsaCrypto.sign(algorithm, key, new Uint8Array(data)); return RsaCrypto.sign(algorithm, getCryptoKey(key) as RsaPrivateKey, new Uint8Array(data));
} }
public async onVerify(algorithm: Algorithm, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> { public async onVerify(algorithm: Algorithm, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> {
return RsaCrypto.verify(algorithm, key, new Uint8Array(signature), new Uint8Array(data)); return RsaCrypto.verify(algorithm, getCryptoKey(key) as RsaPublicKey, new Uint8Array(signature), new Uint8Array(data));
} }
public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> { public async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey | ArrayBuffer> {
return RsaCrypto.exportKey(format, key); return RsaCrypto.exportKey(format, getCryptoKey(key));
} }
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> { public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
const key = await RsaCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages); const key = await RsaCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages);
return key; return setCryptoKey(key);
} }
public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { public checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
super.checkCryptoKey(key, keyUsage); super.checkCryptoKey(key, keyUsage);
if (!(key instanceof RsaPrivateKey || key instanceof RsaPublicKey)) { const internalKey = getCryptoKey(key);
if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) {
throw new TypeError("key: Is not RSA CryptoKey"); throw new TypeError("key: Is not RSA CryptoKey");
} }
} }

21
src/mechs/storage.ts Normal file
View File

@ -0,0 +1,21 @@
import * as core from "webcrypto-core";
import { CryptoKey as InternalCryptoKey } from "../keys";
const keyStorage = new WeakMap<core.CryptoKey, InternalCryptoKey>();
export function getCryptoKey(key: core.CryptoKey) {
const res = keyStorage.get(key);
if (!res) {
throw new core.OperationError("Cannot get CryptoKey from secure storage");
}
return res;
}
export function setCryptoKey(value: InternalCryptoKey) {
const key = core.CryptoKey.create(value.algorithm, value.type, value.extractable, value.usages);
Object.freeze(key);
keyStorage.set(key, value);
return key;
}