node-webcrypto-p11
Version:
A WebCrypto Polyfill built on PKCS11
392 lines (376 loc) • 15.1 kB
TypeScript
/*!
* The MIT License (MIT)
*
* Copyright (c) 2020 Peculiar Ventures, LLC
*
* See the full version of the license https://github.com/PeculiarVentures/node-webcrypto-p11/blob/master/LICENSE
*/
import * as core from 'webcrypto-core';
import * as graphene from 'graphene-pk11';
import * as pvtsutils from 'pvtsutils';
import * as x509 from '@peculiar/x509';
type OperationType = "decrypt" | "sign";
type ITemplate = graphene.ITemplate;
interface Pkcs11Attributes {
id?: pvtsutils.BufferSource;
token?: boolean;
sensitive?: boolean;
label?: string;
extractable?: boolean;
/**
* If `true`, the user has to supply the PIN for each use (sign or decrypt) with the key. Use `crypto.onAlwaysAuthenticate` handler to customize this behavior.
* @since v2.6.0
*/
alwaysAuthenticate?: boolean;
usages?: KeyUsage[];
}
type TemplateBuildType = "private" | "public" | "secret" | "x509" | "request";
type TemplateBuildAction = "generate" | "import" | "copy";
interface ITemplateBuildParameters {
type: TemplateBuildType;
action: TemplateBuildAction;
attributes: Pkcs11Attributes;
}
/**
* Interface of PKCS#11 template builder
*/
interface ITemplateBuilder {
/**
* Returns a PKCS#11 template
* @param params Template build parameters
*/
build(params: ITemplateBuildParameters): ITemplate;
}
type AlwaysAuthenticateHandleResult = string | null;
type AlwaysAuthenticateHandle = (key: CryptoKey, crypto: ISessionContainer, operation: OperationType) => AlwaysAuthenticateHandleResult | Promise<AlwaysAuthenticateHandleResult>;
interface ISessionContainer {
readonly session: graphene.Session;
templateBuilder: ITemplateBuilder;
/**
* Returns the PIN for the force re-authentication. Re-authentication occurs by calling sign or decrypt functions.
* @since v2.6.0
*/
onAlwaysAuthenticate?: AlwaysAuthenticateHandle;
}
interface IContainer {
readonly container: ISessionContainer;
}
interface CryptoParams {
/**
* Path to library
*/
library: string;
/**
* Name of PKCS11 module
*/
name?: string;
/**
* Index of slot
*/
slot?: number;
readWrite?: boolean;
/**
* PIN of slot
*/
pin?: string;
/**
* list of vendor json files
*/
vendors?: string[];
/**
* NSS library parameters
*/
libraryParameters?: string;
}
interface ProviderInfo {
id: string;
name: string;
reader: string;
slot: number;
serialNumber: string;
algorithms: string[];
isRemovable: boolean;
isHardware: boolean;
}
interface Pkcs11Params {
token?: boolean;
sensitive?: boolean;
label?: string;
}
interface AlwaysAuthenticateParams {
/**
* If `true`, the user has to supply the PIN for each use (sign or decrypt) with the key. Use `crypto.onAlwaysAuthenticate` handler to customize this behavior.
* @since v2.6.0
*/
alwaysAuthenticate?: boolean;
}
interface Pkcs11KeyGenParams extends Algorithm, Pkcs11Params {
}
interface Pkcs11AesKeyGenParams extends AesKeyGenParams, Pkcs11KeyGenParams {
}
interface Pkcs11HmacKeyGenParams extends HmacKeyGenParams, Pkcs11KeyGenParams {
}
interface Pkcs11EcKeyGenParams extends EcKeyGenParams, Pkcs11KeyGenParams, AlwaysAuthenticateParams {
}
interface Pkcs11RsaHashedKeyGenParams extends RsaHashedKeyGenParams, Pkcs11KeyGenParams, AlwaysAuthenticateParams {
}
interface Pkcs11KeyImportParams extends Algorithm, Pkcs11Params {
}
interface Pkcs11EcKeyImportParams extends EcKeyImportParams, Pkcs11KeyImportParams, AlwaysAuthenticateParams {
}
interface Pkcs11RsaHashedImportParams extends RsaHashedImportParams, Pkcs11KeyImportParams, AlwaysAuthenticateParams {
}
interface Pkcs11HmacKeyImportParams extends HmacImportParams, Pkcs11KeyImportParams {
}
interface Pkcs11AesKeyImportParams extends Algorithm, Pkcs11KeyImportParams {
}
interface Pkcs11KeyAlgorithm extends KeyAlgorithm {
token: boolean;
sensitive?: boolean;
label: string;
}
interface Pkcs11RsaHashedKeyAlgorithm extends RsaHashedKeyAlgorithm, Pkcs11KeyAlgorithm {
}
interface Pkcs11EcKeyAlgorithm extends EcKeyAlgorithm, Pkcs11KeyAlgorithm {
}
interface Pkcs11AesKeyAlgorithm extends AesKeyAlgorithm, Pkcs11KeyAlgorithm {
}
interface Pkcs11HmacKeyAlgorithm extends HmacKeyAlgorithm, Pkcs11KeyAlgorithm {
}
interface CryptoKeyJson<T extends Pkcs11KeyAlgorithm = Pkcs11KeyAlgorithm> {
algorithm: T;
type: KeyType;
usages: KeyUsage[];
extractable: boolean;
}
declare class CryptoKey$1<T extends Pkcs11KeyAlgorithm = Pkcs11KeyAlgorithm> extends core.CryptoKey implements AlwaysAuthenticateParams {
static defaultKeyAlgorithm(): Pkcs11KeyAlgorithm;
static getID(p11Key: graphene.Key): string;
id: string;
p11Object: graphene.Key | graphene.SecretKey | graphene.PublicKey | graphene.PrivateKey;
/**
* If `true`, the user has to supply the PIN for each use (sign or decrypt) with the key. Use `crypto.onAlwaysAuthenticate` handler to customize this behavior.
* @since v2.6.0
*/
alwaysAuthenticate?: boolean | undefined;
type: KeyType;
extractable: boolean;
algorithm: T;
usages: KeyUsage[];
get key(): graphene.Key;
constructor(key: graphene.Key, alg: T | KeyAlgorithm, usages?: KeyUsage[]);
toJSON(): CryptoKeyJson<T>;
protected initPrivateKey(key: graphene.PrivateKey): void;
protected initPublicKey(key: graphene.PublicKey): void;
protected initSecretKey(key: graphene.SecretKey): void;
protected onAssign(): void;
}
declare class Pkcs11Object {
static assertStorage(obj: graphene.Storage | undefined): asserts obj is graphene.Storage;
p11Object?: graphene.Storage;
constructor(object?: graphene.Storage);
}
interface Pkcs11CryptoCertificate extends core.CryptoCertificate {
readonly id: string;
readonly token: boolean;
readonly sensitive: boolean;
readonly label: string;
}
type Pkcs11ImportAlgorithms = core.ImportAlgorithms & Pkcs11Params;
declare abstract class CryptoCertificate extends Pkcs11Object implements Pkcs11CryptoCertificate {
crypto: Crypto;
static getID(p11Object: graphene.Storage): string;
get id(): string;
type: core.CryptoCertificateType;
publicKey: CryptoKey$1;
get token(): boolean;
get sensitive(): boolean;
get label(): string;
constructor(crypto: Crypto);
abstract importCert(data: Buffer, algorithm: Pkcs11ImportAlgorithms, keyUsages: string[]): Promise<void>;
abstract exportCert(): Promise<ArrayBuffer>;
abstract exportKey(): Promise<CryptoKey$1>;
abstract exportKey(algorithm: Algorithm, usages: KeyUsage[]): Promise<CryptoKey$1>;
/**
* Computes and returns the ID of a public key using the WebCrypto API.
* @returnsA Promise that resolves to a Buffer containing the ID of the public key.
*/
protected computeID(): Promise<Buffer>;
}
interface X509CertificateRequestJson {
publicKey: CryptoKeyJson<Pkcs11KeyAlgorithm>;
subjectName: string;
type: "request";
value: string;
}
declare class X509CertificateRequest extends CryptoCertificate implements core.CryptoX509CertificateRequest {
get subjectName(): string;
type: "request";
p11Object?: graphene.Data;
csr?: x509.Pkcs10CertificateRequest;
get value(): ArrayBuffer;
/**
* Creates new CertificateRequest in PKCS11 session
* @param data
* @param algorithm
* @param keyUsages
*/
importCert(data: Buffer, algorithm: Pkcs11ImportAlgorithms, keyUsages: KeyUsage[]): Promise<void>;
exportCert(): Promise<ArrayBuffer>;
toJSON(): X509CertificateRequestJson;
exportKey(): Promise<CryptoKey$1>;
exportKey(algorithm: Algorithm, usages: KeyUsage[]): Promise<CryptoKey$1>;
protected parse(data: ArrayBuffer): void;
/**
* returns parsed ASN1 value
*/
protected getData(): x509.Pkcs10CertificateRequest;
}
interface X509CertificateJson {
publicKey: CryptoKeyJson;
notBefore: Date;
notAfter: Date;
subjectName: string;
issuerName: string;
serialNumber: string;
type: "x509";
value: string;
}
declare class X509Certificate extends CryptoCertificate implements core.CryptoX509Certificate {
get serialNumber(): string;
get notBefore(): Date;
get notAfter(): Date;
get issuerName(): string;
get subjectName(): string;
type: "x509";
get value(): ArrayBuffer;
p11Object?: graphene.X509Certificate;
protected x509?: x509.X509Certificate;
importCert(data: Buffer, algorithm: Pkcs11ImportAlgorithms, keyUsages: KeyUsage[]): Promise<void>;
exportCert(): Promise<ArrayBuffer>;
toJSON(): X509CertificateJson;
exportKey(): Promise<CryptoKey$1>;
exportKey(algorithm: Algorithm, usages: KeyUsage[]): Promise<CryptoKey$1>;
protected parse(data: ArrayBuffer): void;
/**
* returns parsed ASN1 value
*/
protected getData(): x509.X509Certificate;
/**
* Returns name from subject of the certificate
*/
protected getName(): string;
}
declare class ParserError extends Error {
constructor(message: string);
}
interface IGetValue {
/**
* Returns item blob
* @param key Object identifier
*/
getValue(key: string): Promise<ArrayBuffer | null>;
}
declare class CertificateStorage implements core.CryptoCertificateStorage, IGetValue {
protected crypto: Crypto;
constructor(crypto: Crypto);
getValue(key: string): Promise<ArrayBuffer | null>;
indexOf(item: Pkcs11CryptoCertificate): Promise<string | null>;
keys(): Promise<string[]>;
clear(): Promise<void>;
hasItem(item: Pkcs11CryptoCertificate): Promise<boolean>;
getItem(index: string): Promise<Pkcs11CryptoCertificate>;
getItem(index: string, algorithm: core.ImportAlgorithms, keyUsages: KeyUsage[]): Promise<Pkcs11CryptoCertificate>;
removeItem(key: string): Promise<void>;
setItem(data: Pkcs11CryptoCertificate): Promise<string>;
exportCert(format: core.CryptoCertificateFormat, item: Pkcs11CryptoCertificate): Promise<ArrayBuffer | string>;
exportCert(format: "raw", item: Pkcs11CryptoCertificate): Promise<ArrayBuffer>;
exportCert(format: "pem", item: Pkcs11CryptoCertificate): Promise<string>;
importCert(format: core.CryptoCertificateFormat, data: BufferSource | string, algorithm: Pkcs11ImportAlgorithms, keyUsages: KeyUsage[]): Promise<Pkcs11CryptoCertificate>;
importCert(format: "raw", data: BufferSource, algorithm: Pkcs11ImportAlgorithms, keyUsages: KeyUsage[]): Promise<Pkcs11CryptoCertificate>;
importCert(format: "pem", data: string, algorithm: Pkcs11ImportAlgorithms, keyUsages: KeyUsage[]): Promise<Pkcs11CryptoCertificate>;
protected getItemById(id: string): graphene.SessionObject | null;
}
declare class KeyStorage implements core.CryptoKeyStorage {
protected crypto: Crypto;
constructor(crypto: Crypto);
keys(): Promise<string[]>;
indexOf(item: CryptoKey$1): Promise<string | null>;
clear(): Promise<void>;
getItem(key: string): Promise<CryptoKey$1>;
/** @deprecated Use getItem(index, algorithm, extractable, keyUsages) */
getItem(key: string, algorithm: Algorithm, usages: KeyUsage[]): Promise<CryptoKey$1>;
getItem(index: string, algorithm: core.ImportAlgorithms, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey$1>;
removeItem(key: string): Promise<void>;
setItem(data: core.NativeCryptoKey): Promise<string>;
hasItem(key: CryptoKey$1): Promise<boolean>;
protected getItemById(id: string): graphene.SessionObject | null;
}
interface CryptoKeyPair {
privateKey: CryptoKey$1;
publicKey: CryptoKey$1;
}
declare class SubtleCrypto extends core.SubtleCrypto implements IContainer {
container: ISessionContainer;
constructor(container: ISessionContainer);
generateKey(algorithm: "Ed25519", extractable: boolean, keyUsages: ReadonlyArray<"sign" | "verify">): Promise<CryptoKeyPair>;
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<globalThis.CryptoKeyPair>;
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<globalThis.CryptoKey>;
generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<globalThis.CryptoKeyPair | globalThis.CryptoKey>;
protected computeId(publicKey: CryptoKey$1<Pkcs11KeyAlgorithm>): Promise<Buffer>;
importKey(format: KeyFormat, keyData: JsonWebKey | BufferSource, algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey$1>;
}
/**
* PKCS11 with WebCrypto Interface
*/
declare class Crypto extends core.Crypto implements core.CryptoStorages, ISessionContainer {
#private;
info?: ProviderInfo;
subtle: SubtleCrypto;
keyStorage: KeyStorage;
certStorage: CertificateStorage;
isReadWrite: boolean;
isLoggedIn: boolean;
isLoginRequired: boolean;
/**
* PKCS11 Slot
* @internal
*/
slot: graphene.Slot;
/**
* PKCS11 Token
* @internal
*/
token: graphene.Token;
/**
* PKCS11 token
* @internal
*/
get session(): graphene.Session;
protected name?: string;
private initialized;
templateBuilder: ITemplateBuilder;
onAlwaysAuthenticate?: AlwaysAuthenticateHandle;
/**
* Creates an instance of WebCrypto.
* @param props PKCS11 module init parameters
*/
constructor(props: CryptoParams);
open(rw?: boolean): void;
reset(): void;
login(pin: string): void;
logout(): void;
/**
* Generates cryptographically random values
* @param array Initialize array
*/
getRandomValues<T extends ArrayBufferView | null>(array: T): T;
/**
* Close PKCS11 module
*/
close(): void;
}
declare class TemplateBuilder implements ITemplateBuilder {
build(params: ITemplateBuildParameters): ITemplate;
}
export { type AlwaysAuthenticateHandle, type AlwaysAuthenticateHandleResult, type AlwaysAuthenticateParams, CertificateStorage, Crypto, CryptoCertificate, CryptoKey$1 as CryptoKey, type CryptoKeyJson, type CryptoParams, type IContainer, type IGetValue, type ISessionContainer, type ITemplate, type ITemplateBuildParameters, type ITemplateBuilder, KeyStorage, ParserError, type Pkcs11AesKeyAlgorithm, type Pkcs11AesKeyGenParams, type Pkcs11AesKeyImportParams, type Pkcs11Attributes, type Pkcs11CryptoCertificate, type Pkcs11EcKeyAlgorithm, type Pkcs11EcKeyGenParams, type Pkcs11EcKeyImportParams, type Pkcs11HmacKeyAlgorithm, type Pkcs11HmacKeyGenParams, type Pkcs11HmacKeyImportParams, type Pkcs11ImportAlgorithms, type Pkcs11KeyAlgorithm, type Pkcs11KeyGenParams, type Pkcs11KeyImportParams, type Pkcs11Params, type Pkcs11RsaHashedImportParams, type Pkcs11RsaHashedKeyAlgorithm, type Pkcs11RsaHashedKeyGenParams, type ProviderInfo, SubtleCrypto, type TemplateBuildAction, type TemplateBuildType, TemplateBuilder, X509Certificate, X509CertificateRequest };