@road-labs/ocmf-crypto 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/asn1.js +95 -0
- package/build/cjs/crypto.js +18 -0
- package/build/cjs/index.js +19 -0
- package/build/cjs/types.js +2 -0
- package/build/es2022/asn1.js +87 -0
- package/build/es2022/crypto.js +10 -0
- package/build/es2022/index.js +3 -0
- package/build/es2022/types.js +1 -0
- package/build/types/asn1.d.ts +36 -0
- package/build/types/crypto.d.ts +74 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/types.d.ts +5 -0
- package/jest.config.js +11 -0
- package/package.json +36 -0
- package/src/asn1.ts +159 -0
- package/src/crypto.ts +101 -0
- package/src/index.ts +3 -0
- package/src/types.ts +13 -0
- package/tsconfig.json +4 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.curveToOid = exports.oidToCurve = exports.oidEllipticCurveKey = void 0;
|
|
4
|
+
exports.decodePkcs8PrivateKeyInfo = decodePkcs8PrivateKeyInfo;
|
|
5
|
+
exports.encodePkixSubjectPublicKeyInfo = encodePkixSubjectPublicKeyInfo;
|
|
6
|
+
exports.decodePkixSubjectPublicKeyInfo = decodePkixSubjectPublicKeyInfo;
|
|
7
|
+
exports.encodePkixEcdsaSigValue = encodePkixEcdsaSigValue;
|
|
8
|
+
exports.decodePkixEcdsaSigValue = decodePkixEcdsaSigValue;
|
|
9
|
+
const asn1_schema_1 = require("@peculiar/asn1-schema");
|
|
10
|
+
const asn1_pkcs8_1 = require("@peculiar/asn1-pkcs8");
|
|
11
|
+
const asn1_ecc_1 = require("@peculiar/asn1-ecc");
|
|
12
|
+
const asn1_x509_1 = require("@peculiar/asn1-x509");
|
|
13
|
+
exports.oidEllipticCurveKey = asn1_ecc_1.id_ecPublicKey;
|
|
14
|
+
const id_brainpool256r1 = '1.3.36.3.3.2.8.1.1.7';
|
|
15
|
+
const id_brainpool384r1 = '1.3.36.3.3.2.8.1.1.11';
|
|
16
|
+
const id_secp192k1 = '1.3.132.0.31';
|
|
17
|
+
const id_secp256k1 = '1.3.132.0.10';
|
|
18
|
+
exports.oidToCurve = new Map([
|
|
19
|
+
[id_brainpool256r1, 'brainpool256r1'],
|
|
20
|
+
[id_brainpool384r1, 'brainpool384r1'],
|
|
21
|
+
[id_secp192k1, 'secp192k1'],
|
|
22
|
+
[asn1_ecc_1.id_secp192r1, 'secp192r1'],
|
|
23
|
+
[id_secp256k1, 'secp256k1'],
|
|
24
|
+
[asn1_ecc_1.id_secp256r1, 'secp256r1'],
|
|
25
|
+
[asn1_ecc_1.id_secp384r1, 'secp384r1'],
|
|
26
|
+
]);
|
|
27
|
+
exports.curveToOid = new Map([
|
|
28
|
+
['brainpool256r1', id_brainpool256r1],
|
|
29
|
+
['brainpool384r1', id_brainpool384r1],
|
|
30
|
+
['secp192k1', id_secp192k1],
|
|
31
|
+
['secp192r1', asn1_ecc_1.id_secp192r1],
|
|
32
|
+
['secp256k1', id_secp256k1],
|
|
33
|
+
['secp256r1', asn1_ecc_1.id_secp256r1],
|
|
34
|
+
['secp384r1', asn1_ecc_1.id_secp384r1],
|
|
35
|
+
]);
|
|
36
|
+
function decodePkcs8PrivateKeyInfo(value) {
|
|
37
|
+
const privateKeyInfo = asn1_schema_1.AsnParser.parse(value, asn1_pkcs8_1.PrivateKeyInfo);
|
|
38
|
+
if (privateKeyInfo?.privateKeyAlgorithm?.algorithm !== exports.oidEllipticCurveKey) {
|
|
39
|
+
throw new Error(`Unexpected private key algorithm: ${privateKeyInfo?.privateKeyAlgorithm?.algorithm}`);
|
|
40
|
+
}
|
|
41
|
+
const privateKey = asn1_schema_1.AsnParser.parse(privateKeyInfo.privateKey.buffer, asn1_ecc_1.ECPrivateKey);
|
|
42
|
+
return {
|
|
43
|
+
version: privateKeyInfo.version,
|
|
44
|
+
privateKeyAlgorithm: privateKeyInfo.privateKeyAlgorithm,
|
|
45
|
+
privateKey: {
|
|
46
|
+
version: privateKey.version,
|
|
47
|
+
parameters: privateKey.parameters,
|
|
48
|
+
privateKey: new Uint8Array(privateKey.privateKey.buffer),
|
|
49
|
+
publicKey: privateKey.publicKey
|
|
50
|
+
? new Uint8Array(privateKey.publicKey)
|
|
51
|
+
: undefined,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function encodePkixSubjectPublicKeyInfo(keyInfo) {
|
|
56
|
+
const asn1 = new asn1_x509_1.SubjectPublicKeyInfo({
|
|
57
|
+
algorithm: new asn1_x509_1.AlgorithmIdentifier({
|
|
58
|
+
algorithm: keyInfo.algorithm.algorithm,
|
|
59
|
+
parameters: asn1_schema_1.AsnConvert.serialize(new asn1_ecc_1.ECParameters(keyInfo.algorithm.parameters)),
|
|
60
|
+
}),
|
|
61
|
+
subjectPublicKey: keyInfo.subjectPublicKey,
|
|
62
|
+
});
|
|
63
|
+
return new Uint8Array(asn1_schema_1.AsnConvert.serialize(asn1));
|
|
64
|
+
}
|
|
65
|
+
function decodePkixSubjectPublicKeyInfo(value) {
|
|
66
|
+
const subjectPublicKeyInfo = asn1_schema_1.AsnParser.parse(value, asn1_x509_1.SubjectPublicKeyInfo);
|
|
67
|
+
if (subjectPublicKeyInfo?.algorithm?.algorithm !== exports.oidEllipticCurveKey) {
|
|
68
|
+
throw new Error(`Unexpected public key algorithm: ${subjectPublicKeyInfo?.algorithm?.algorithm}`);
|
|
69
|
+
}
|
|
70
|
+
let parameters;
|
|
71
|
+
if (subjectPublicKeyInfo.algorithm.parameters) {
|
|
72
|
+
parameters = asn1_schema_1.AsnParser.parse(subjectPublicKeyInfo.algorithm.parameters, asn1_ecc_1.ECParameters);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
algorithm: {
|
|
76
|
+
algorithm: subjectPublicKeyInfo.algorithm.algorithm,
|
|
77
|
+
parameters,
|
|
78
|
+
},
|
|
79
|
+
subjectPublicKey: new Uint8Array(subjectPublicKeyInfo.subjectPublicKey),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function encodePkixEcdsaSigValue(sigValue) {
|
|
83
|
+
const asn1 = new asn1_ecc_1.ECDSASigValue({
|
|
84
|
+
r: sigValue.r,
|
|
85
|
+
s: sigValue.s,
|
|
86
|
+
});
|
|
87
|
+
return new Uint8Array(asn1_schema_1.AsnConvert.serialize(asn1));
|
|
88
|
+
}
|
|
89
|
+
function decodePkixEcdsaSigValue(value) {
|
|
90
|
+
const subjectPublicKeyInfo = asn1_schema_1.AsnParser.parse(value, asn1_ecc_1.ECDSASigValue);
|
|
91
|
+
return {
|
|
92
|
+
r: new Uint8Array(subjectPublicKeyInfo.r),
|
|
93
|
+
s: new Uint8Array(subjectPublicKeyInfo.s),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsupportedSignatureFormatError = exports.UnsupportedPublicKeyFormatError = exports.UnsupportedPrivateKeyFormatError = exports.UnsupportedHashError = exports.UnsupportedCurveError = void 0;
|
|
4
|
+
class UnsupportedCurveError extends Error {
|
|
5
|
+
}
|
|
6
|
+
exports.UnsupportedCurveError = UnsupportedCurveError;
|
|
7
|
+
class UnsupportedHashError extends Error {
|
|
8
|
+
}
|
|
9
|
+
exports.UnsupportedHashError = UnsupportedHashError;
|
|
10
|
+
class UnsupportedPrivateKeyFormatError extends Error {
|
|
11
|
+
}
|
|
12
|
+
exports.UnsupportedPrivateKeyFormatError = UnsupportedPrivateKeyFormatError;
|
|
13
|
+
class UnsupportedPublicKeyFormatError extends Error {
|
|
14
|
+
}
|
|
15
|
+
exports.UnsupportedPublicKeyFormatError = UnsupportedPublicKeyFormatError;
|
|
16
|
+
class UnsupportedSignatureFormatError extends Error {
|
|
17
|
+
}
|
|
18
|
+
exports.UnsupportedSignatureFormatError = UnsupportedSignatureFormatError;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./asn1"), exports);
|
|
19
|
+
__exportStar(require("./crypto"), exports);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { AsnConvert, AsnParser } from '@peculiar/asn1-schema';
|
|
2
|
+
import { PrivateKeyInfo } from '@peculiar/asn1-pkcs8';
|
|
3
|
+
import { ECDSASigValue, ECParameters, ECPrivateKey, id_ecPublicKey, id_secp192r1, id_secp256r1, id_secp384r1, } from '@peculiar/asn1-ecc';
|
|
4
|
+
import { AlgorithmIdentifier, SubjectPublicKeyInfo } from '@peculiar/asn1-x509';
|
|
5
|
+
export const oidEllipticCurveKey = id_ecPublicKey;
|
|
6
|
+
const id_brainpool256r1 = '1.3.36.3.3.2.8.1.1.7';
|
|
7
|
+
const id_brainpool384r1 = '1.3.36.3.3.2.8.1.1.11';
|
|
8
|
+
const id_secp192k1 = '1.3.132.0.31';
|
|
9
|
+
const id_secp256k1 = '1.3.132.0.10';
|
|
10
|
+
export const oidToCurve = new Map([
|
|
11
|
+
[id_brainpool256r1, 'brainpool256r1'],
|
|
12
|
+
[id_brainpool384r1, 'brainpool384r1'],
|
|
13
|
+
[id_secp192k1, 'secp192k1'],
|
|
14
|
+
[id_secp192r1, 'secp192r1'],
|
|
15
|
+
[id_secp256k1, 'secp256k1'],
|
|
16
|
+
[id_secp256r1, 'secp256r1'],
|
|
17
|
+
[id_secp384r1, 'secp384r1'],
|
|
18
|
+
]);
|
|
19
|
+
export const curveToOid = new Map([
|
|
20
|
+
['brainpool256r1', id_brainpool256r1],
|
|
21
|
+
['brainpool384r1', id_brainpool384r1],
|
|
22
|
+
['secp192k1', id_secp192k1],
|
|
23
|
+
['secp192r1', id_secp192r1],
|
|
24
|
+
['secp256k1', id_secp256k1],
|
|
25
|
+
['secp256r1', id_secp256r1],
|
|
26
|
+
['secp384r1', id_secp384r1],
|
|
27
|
+
]);
|
|
28
|
+
export function decodePkcs8PrivateKeyInfo(value) {
|
|
29
|
+
const privateKeyInfo = AsnParser.parse(value, PrivateKeyInfo);
|
|
30
|
+
if (privateKeyInfo?.privateKeyAlgorithm?.algorithm !== oidEllipticCurveKey) {
|
|
31
|
+
throw new Error(`Unexpected private key algorithm: ${privateKeyInfo?.privateKeyAlgorithm?.algorithm}`);
|
|
32
|
+
}
|
|
33
|
+
const privateKey = AsnParser.parse(privateKeyInfo.privateKey.buffer, ECPrivateKey);
|
|
34
|
+
return {
|
|
35
|
+
version: privateKeyInfo.version,
|
|
36
|
+
privateKeyAlgorithm: privateKeyInfo.privateKeyAlgorithm,
|
|
37
|
+
privateKey: {
|
|
38
|
+
version: privateKey.version,
|
|
39
|
+
parameters: privateKey.parameters,
|
|
40
|
+
privateKey: new Uint8Array(privateKey.privateKey.buffer),
|
|
41
|
+
publicKey: privateKey.publicKey
|
|
42
|
+
? new Uint8Array(privateKey.publicKey)
|
|
43
|
+
: undefined,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function encodePkixSubjectPublicKeyInfo(keyInfo) {
|
|
48
|
+
const asn1 = new SubjectPublicKeyInfo({
|
|
49
|
+
algorithm: new AlgorithmIdentifier({
|
|
50
|
+
algorithm: keyInfo.algorithm.algorithm,
|
|
51
|
+
parameters: AsnConvert.serialize(new ECParameters(keyInfo.algorithm.parameters)),
|
|
52
|
+
}),
|
|
53
|
+
subjectPublicKey: keyInfo.subjectPublicKey,
|
|
54
|
+
});
|
|
55
|
+
return new Uint8Array(AsnConvert.serialize(asn1));
|
|
56
|
+
}
|
|
57
|
+
export function decodePkixSubjectPublicKeyInfo(value) {
|
|
58
|
+
const subjectPublicKeyInfo = AsnParser.parse(value, SubjectPublicKeyInfo);
|
|
59
|
+
if (subjectPublicKeyInfo?.algorithm?.algorithm !== oidEllipticCurveKey) {
|
|
60
|
+
throw new Error(`Unexpected public key algorithm: ${subjectPublicKeyInfo?.algorithm?.algorithm}`);
|
|
61
|
+
}
|
|
62
|
+
let parameters;
|
|
63
|
+
if (subjectPublicKeyInfo.algorithm.parameters) {
|
|
64
|
+
parameters = AsnParser.parse(subjectPublicKeyInfo.algorithm.parameters, ECParameters);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
algorithm: {
|
|
68
|
+
algorithm: subjectPublicKeyInfo.algorithm.algorithm,
|
|
69
|
+
parameters,
|
|
70
|
+
},
|
|
71
|
+
subjectPublicKey: new Uint8Array(subjectPublicKeyInfo.subjectPublicKey),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export function encodePkixEcdsaSigValue(sigValue) {
|
|
75
|
+
const asn1 = new ECDSASigValue({
|
|
76
|
+
r: sigValue.r,
|
|
77
|
+
s: sigValue.s,
|
|
78
|
+
});
|
|
79
|
+
return new Uint8Array(AsnConvert.serialize(asn1));
|
|
80
|
+
}
|
|
81
|
+
export function decodePkixEcdsaSigValue(value) {
|
|
82
|
+
const subjectPublicKeyInfo = AsnParser.parse(value, ECDSASigValue);
|
|
83
|
+
return {
|
|
84
|
+
r: new Uint8Array(subjectPublicKeyInfo.r),
|
|
85
|
+
s: new Uint8Array(subjectPublicKeyInfo.s),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export class UnsupportedCurveError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export class UnsupportedHashError extends Error {
|
|
4
|
+
}
|
|
5
|
+
export class UnsupportedPrivateKeyFormatError extends Error {
|
|
6
|
+
}
|
|
7
|
+
export class UnsupportedPublicKeyFormatError extends Error {
|
|
8
|
+
}
|
|
9
|
+
export class UnsupportedSignatureFormatError extends Error {
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Curve } from './types';
|
|
2
|
+
export declare const oidEllipticCurveKey = "1.2.840.10045.2.1";
|
|
3
|
+
export declare const oidToCurve: Map<string, Curve>;
|
|
4
|
+
export declare const curveToOid: Map<Curve, string>;
|
|
5
|
+
export interface Pkcs8PrivateKeyInfo {
|
|
6
|
+
version: number;
|
|
7
|
+
privateKeyAlgorithm: {
|
|
8
|
+
algorithm: string;
|
|
9
|
+
};
|
|
10
|
+
privateKey: {
|
|
11
|
+
version: number;
|
|
12
|
+
privateKey: Uint8Array;
|
|
13
|
+
parameters?: {
|
|
14
|
+
namedCurve?: string;
|
|
15
|
+
};
|
|
16
|
+
publicKey?: Uint8Array;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface PkixSubjectPublicKeyInfo {
|
|
20
|
+
algorithm: {
|
|
21
|
+
algorithm: string;
|
|
22
|
+
parameters?: {
|
|
23
|
+
namedCurve?: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
subjectPublicKey: Uint8Array;
|
|
27
|
+
}
|
|
28
|
+
export interface PkixEcdsaSigValue {
|
|
29
|
+
r: Uint8Array;
|
|
30
|
+
s: Uint8Array;
|
|
31
|
+
}
|
|
32
|
+
export declare function decodePkcs8PrivateKeyInfo(value: Uint8Array): Pkcs8PrivateKeyInfo;
|
|
33
|
+
export declare function encodePkixSubjectPublicKeyInfo(keyInfo: PkixSubjectPublicKeyInfo): Uint8Array;
|
|
34
|
+
export declare function decodePkixSubjectPublicKeyInfo(value: Uint8Array): PkixSubjectPublicKeyInfo;
|
|
35
|
+
export declare function encodePkixEcdsaSigValue(sigValue: PkixEcdsaSigValue): Uint8Array;
|
|
36
|
+
export declare function decodePkixEcdsaSigValue(value: Uint8Array): PkixEcdsaSigValue;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Curve, Hash, PrivateKeyFormat, PublicKeyFormat, SignatureFormat } from './types';
|
|
2
|
+
export declare class UnsupportedCurveError extends Error {
|
|
3
|
+
}
|
|
4
|
+
export declare class UnsupportedHashError extends Error {
|
|
5
|
+
}
|
|
6
|
+
export declare class UnsupportedPrivateKeyFormatError extends Error {
|
|
7
|
+
}
|
|
8
|
+
export declare class UnsupportedPublicKeyFormatError extends Error {
|
|
9
|
+
}
|
|
10
|
+
export declare class UnsupportedSignatureFormatError extends Error {
|
|
11
|
+
}
|
|
12
|
+
export interface CryptoAdapter {
|
|
13
|
+
/**
|
|
14
|
+
* @param value - Encoded private key value
|
|
15
|
+
* @param format - Encoding format
|
|
16
|
+
* @return A private key instance
|
|
17
|
+
* @throws UnsupportedCurveError
|
|
18
|
+
* @throws UnsupportedPrivateKeyFormatError
|
|
19
|
+
* @throws Error
|
|
20
|
+
*/
|
|
21
|
+
decodeEcPrivateKey(value: Uint8Array, format: PrivateKeyFormat): EcPrivateKey | Promise<EcPrivateKey>;
|
|
22
|
+
/**
|
|
23
|
+
* @param value - Encoded public key value
|
|
24
|
+
* @param format - Encoding format
|
|
25
|
+
* @return A public key instance
|
|
26
|
+
* @throws UnsupportedCurveError
|
|
27
|
+
* @throws UnsupportedPublicKeyFormatError
|
|
28
|
+
* @throws Error
|
|
29
|
+
*/
|
|
30
|
+
decodeEcPublicKey(value: Uint8Array, format: PublicKeyFormat): EcPublicKey | Promise<EcPublicKey>;
|
|
31
|
+
/**
|
|
32
|
+
* @param data - Data to be signed
|
|
33
|
+
* @param privateKey - Private key to use for signing
|
|
34
|
+
* @param hash - Hash to apply
|
|
35
|
+
* @param format - Format to return the signature in
|
|
36
|
+
* @return Signature encoded in the specified format
|
|
37
|
+
* @throws UnsupportedHashError
|
|
38
|
+
* @throws UnsupportedSignatureFormatError
|
|
39
|
+
* @throws Error
|
|
40
|
+
*/
|
|
41
|
+
sign(data: Uint8Array, privateKey: EcPrivateKey, hash: Hash, format: SignatureFormat): Uint8Array | Promise<Uint8Array>;
|
|
42
|
+
/**
|
|
43
|
+
* @param signature - X.509 ECDSASigValue ASN.1 type DER encoded
|
|
44
|
+
* @param data - Raw value
|
|
45
|
+
* @param key - The public key to verify against
|
|
46
|
+
* @param hash - Hash to apply
|
|
47
|
+
* @param format - Format the signature is encoded in
|
|
48
|
+
* @return true if the signature is valid
|
|
49
|
+
* @throws UnsupportedSignatureFormatError
|
|
50
|
+
* @throws Error
|
|
51
|
+
*/
|
|
52
|
+
verify(signature: Uint8Array, data: Uint8Array, key: EcPublicKey, hash: Hash, format: SignatureFormat): boolean | Promise<boolean>;
|
|
53
|
+
}
|
|
54
|
+
export interface EcPublicKey {
|
|
55
|
+
/**
|
|
56
|
+
* @return The curve of the public key
|
|
57
|
+
*/
|
|
58
|
+
getCurve(): Curve;
|
|
59
|
+
/**
|
|
60
|
+
* @param format - Format to encode with
|
|
61
|
+
* @return Encoded public key
|
|
62
|
+
*/
|
|
63
|
+
encode(format: PublicKeyFormat): Uint8Array | Promise<Uint8Array>;
|
|
64
|
+
}
|
|
65
|
+
export interface EcPrivateKey {
|
|
66
|
+
/**
|
|
67
|
+
* @return The curve of the private key
|
|
68
|
+
*/
|
|
69
|
+
getCurve(): Curve;
|
|
70
|
+
/**
|
|
71
|
+
* @return The public key, if available
|
|
72
|
+
*/
|
|
73
|
+
getPublicKey(): EcPublicKey | null;
|
|
74
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type Curve = 'brainpool256r1' | 'brainpool384r1' | 'secp192k1' | 'secp192r1' | 'secp256k1' | 'secp256r1' | 'secp384r1';
|
|
2
|
+
export type PrivateKeyFormat = 'pkcs8-der';
|
|
3
|
+
export type PublicKeyFormat = 'spki-der';
|
|
4
|
+
export type SignatureFormat = 'sigvalue-der';
|
|
5
|
+
export type Hash = 'SHA-256';
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@road-labs/ocmf-crypto",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "build/cjs/index.js",
|
|
5
|
+
"module": "build/es2022/index.js",
|
|
6
|
+
"types": "build/types/index.d.ts",
|
|
7
|
+
"keywords": [],
|
|
8
|
+
"author": "",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"description": "",
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@jest/globals": "^30.0.0",
|
|
13
|
+
"@types/node": "^22.15.30",
|
|
14
|
+
"jest": "^30.0.0",
|
|
15
|
+
"rimraf": "^6.0.1",
|
|
16
|
+
"ts-jest": "^29.4.0",
|
|
17
|
+
"ts-node": "^10.9.2",
|
|
18
|
+
"typescript": "^5.8.3"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@peculiar/asn1-ecc": "^2.3.15",
|
|
22
|
+
"@peculiar/asn1-pkcs8": "^2.3.15",
|
|
23
|
+
"@peculiar/asn1-schema": "^2.3.15",
|
|
24
|
+
"@peculiar/asn1-x509": "^2.3.15"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"clear": "rimraf build",
|
|
28
|
+
"build": "pnpm run build:module && pnpm run build:types",
|
|
29
|
+
"build:module": "pnpm run build:cjs && pnpm run build:es2022",
|
|
30
|
+
"build:cjs": "tsc -p tsconfig.json --removeComments --module commonjs --outDir build/cjs",
|
|
31
|
+
"build:es2022": "tsc -p tsconfig.json --removeComments --module es2022 --outDir build/es2022",
|
|
32
|
+
"prebuild:types": "rimraf build/types",
|
|
33
|
+
"build:types": "tsc -p tsconfig.json --outDir build/types --declaration --emitDeclarationOnly",
|
|
34
|
+
"rebuild": "pnpm run clear && pnpm run build"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/asn1.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { AsnConvert, AsnParser } from '@peculiar/asn1-schema';
|
|
2
|
+
import { PrivateKeyInfo } from '@peculiar/asn1-pkcs8';
|
|
3
|
+
import {
|
|
4
|
+
ECDSASigValue,
|
|
5
|
+
ECParameters,
|
|
6
|
+
ECPrivateKey,
|
|
7
|
+
id_ecPublicKey,
|
|
8
|
+
id_secp192r1,
|
|
9
|
+
id_secp256r1,
|
|
10
|
+
id_secp384r1,
|
|
11
|
+
} from '@peculiar/asn1-ecc';
|
|
12
|
+
import { AlgorithmIdentifier, SubjectPublicKeyInfo } from '@peculiar/asn1-x509';
|
|
13
|
+
import { Curve } from './types';
|
|
14
|
+
|
|
15
|
+
export const oidEllipticCurveKey = id_ecPublicKey;
|
|
16
|
+
|
|
17
|
+
const id_brainpool256r1 = '1.3.36.3.3.2.8.1.1.7';
|
|
18
|
+
const id_brainpool384r1 = '1.3.36.3.3.2.8.1.1.11';
|
|
19
|
+
const id_secp192k1 = '1.3.132.0.31';
|
|
20
|
+
const id_secp256k1 = '1.3.132.0.10';
|
|
21
|
+
|
|
22
|
+
export const oidToCurve = new Map<string, Curve>([
|
|
23
|
+
[id_brainpool256r1, 'brainpool256r1'],
|
|
24
|
+
[id_brainpool384r1, 'brainpool384r1'],
|
|
25
|
+
[id_secp192k1, 'secp192k1'],
|
|
26
|
+
[id_secp192r1, 'secp192r1'],
|
|
27
|
+
[id_secp256k1, 'secp256k1'],
|
|
28
|
+
[id_secp256r1, 'secp256r1'],
|
|
29
|
+
[id_secp384r1, 'secp384r1'],
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
export const curveToOid = new Map<Curve, string>([
|
|
33
|
+
['brainpool256r1', id_brainpool256r1],
|
|
34
|
+
['brainpool384r1', id_brainpool384r1],
|
|
35
|
+
['secp192k1', id_secp192k1],
|
|
36
|
+
['secp192r1', id_secp192r1],
|
|
37
|
+
['secp256k1', id_secp256k1],
|
|
38
|
+
['secp256r1', id_secp256r1],
|
|
39
|
+
['secp384r1', id_secp384r1],
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
export interface Pkcs8PrivateKeyInfo {
|
|
43
|
+
version: number;
|
|
44
|
+
privateKeyAlgorithm: {
|
|
45
|
+
algorithm: string;
|
|
46
|
+
};
|
|
47
|
+
privateKey: {
|
|
48
|
+
version: number;
|
|
49
|
+
privateKey: Uint8Array;
|
|
50
|
+
parameters?: {
|
|
51
|
+
namedCurve?: string;
|
|
52
|
+
};
|
|
53
|
+
publicKey?: Uint8Array;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface PkixSubjectPublicKeyInfo {
|
|
58
|
+
algorithm: {
|
|
59
|
+
algorithm: string;
|
|
60
|
+
parameters?: {
|
|
61
|
+
namedCurve?: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
subjectPublicKey: Uint8Array;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface PkixEcdsaSigValue {
|
|
68
|
+
r: Uint8Array;
|
|
69
|
+
s: Uint8Array;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function decodePkcs8PrivateKeyInfo(
|
|
73
|
+
value: Uint8Array
|
|
74
|
+
): Pkcs8PrivateKeyInfo {
|
|
75
|
+
const privateKeyInfo = AsnParser.parse(value, PrivateKeyInfo);
|
|
76
|
+
if (privateKeyInfo?.privateKeyAlgorithm?.algorithm !== oidEllipticCurveKey) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Unexpected private key algorithm: ${privateKeyInfo?.privateKeyAlgorithm?.algorithm}`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const privateKey = AsnParser.parse(
|
|
83
|
+
privateKeyInfo.privateKey.buffer,
|
|
84
|
+
ECPrivateKey
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
version: privateKeyInfo.version,
|
|
89
|
+
privateKeyAlgorithm: privateKeyInfo.privateKeyAlgorithm,
|
|
90
|
+
privateKey: {
|
|
91
|
+
version: privateKey.version,
|
|
92
|
+
parameters: privateKey.parameters,
|
|
93
|
+
privateKey: new Uint8Array(privateKey.privateKey.buffer),
|
|
94
|
+
publicKey: privateKey.publicKey
|
|
95
|
+
? new Uint8Array(privateKey.publicKey)
|
|
96
|
+
: undefined,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function encodePkixSubjectPublicKeyInfo(
|
|
102
|
+
keyInfo: PkixSubjectPublicKeyInfo
|
|
103
|
+
): Uint8Array {
|
|
104
|
+
const asn1 = new SubjectPublicKeyInfo({
|
|
105
|
+
algorithm: new AlgorithmIdentifier({
|
|
106
|
+
algorithm: keyInfo.algorithm.algorithm,
|
|
107
|
+
parameters: AsnConvert.serialize(
|
|
108
|
+
new ECParameters(keyInfo.algorithm.parameters)
|
|
109
|
+
),
|
|
110
|
+
}),
|
|
111
|
+
subjectPublicKey: keyInfo.subjectPublicKey,
|
|
112
|
+
});
|
|
113
|
+
return new Uint8Array(AsnConvert.serialize(asn1));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function decodePkixSubjectPublicKeyInfo(
|
|
117
|
+
value: Uint8Array
|
|
118
|
+
): PkixSubjectPublicKeyInfo {
|
|
119
|
+
const subjectPublicKeyInfo = AsnParser.parse(value, SubjectPublicKeyInfo);
|
|
120
|
+
if (subjectPublicKeyInfo?.algorithm?.algorithm !== oidEllipticCurveKey) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`Unexpected public key algorithm: ${subjectPublicKeyInfo?.algorithm?.algorithm}`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let parameters: PkixSubjectPublicKeyInfo['algorithm']['parameters'];
|
|
127
|
+
if (subjectPublicKeyInfo.algorithm.parameters) {
|
|
128
|
+
parameters = AsnParser.parse(
|
|
129
|
+
subjectPublicKeyInfo.algorithm.parameters,
|
|
130
|
+
ECParameters
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
algorithm: {
|
|
136
|
+
algorithm: subjectPublicKeyInfo.algorithm.algorithm,
|
|
137
|
+
parameters,
|
|
138
|
+
},
|
|
139
|
+
subjectPublicKey: new Uint8Array(subjectPublicKeyInfo.subjectPublicKey),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function encodePkixEcdsaSigValue(
|
|
144
|
+
sigValue: PkixEcdsaSigValue
|
|
145
|
+
): Uint8Array {
|
|
146
|
+
const asn1 = new ECDSASigValue({
|
|
147
|
+
r: sigValue.r,
|
|
148
|
+
s: sigValue.s,
|
|
149
|
+
});
|
|
150
|
+
return new Uint8Array(AsnConvert.serialize(asn1));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function decodePkixEcdsaSigValue(value: Uint8Array): PkixEcdsaSigValue {
|
|
154
|
+
const subjectPublicKeyInfo = AsnParser.parse(value, ECDSASigValue);
|
|
155
|
+
return {
|
|
156
|
+
r: new Uint8Array(subjectPublicKeyInfo.r),
|
|
157
|
+
s: new Uint8Array(subjectPublicKeyInfo.s),
|
|
158
|
+
};
|
|
159
|
+
}
|
package/src/crypto.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Curve,
|
|
3
|
+
Hash,
|
|
4
|
+
PrivateKeyFormat,
|
|
5
|
+
PublicKeyFormat,
|
|
6
|
+
SignatureFormat,
|
|
7
|
+
} from './types';
|
|
8
|
+
|
|
9
|
+
export class UnsupportedCurveError extends Error {}
|
|
10
|
+
export class UnsupportedHashError extends Error {}
|
|
11
|
+
export class UnsupportedPrivateKeyFormatError extends Error {}
|
|
12
|
+
export class UnsupportedPublicKeyFormatError extends Error {}
|
|
13
|
+
export class UnsupportedSignatureFormatError extends Error {}
|
|
14
|
+
|
|
15
|
+
export interface CryptoAdapter {
|
|
16
|
+
/**
|
|
17
|
+
* @param value - Encoded private key value
|
|
18
|
+
* @param format - Encoding format
|
|
19
|
+
* @return A private key instance
|
|
20
|
+
* @throws UnsupportedCurveError
|
|
21
|
+
* @throws UnsupportedPrivateKeyFormatError
|
|
22
|
+
* @throws Error
|
|
23
|
+
*/
|
|
24
|
+
decodeEcPrivateKey(
|
|
25
|
+
value: Uint8Array,
|
|
26
|
+
format: PrivateKeyFormat
|
|
27
|
+
): EcPrivateKey | Promise<EcPrivateKey>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param value - Encoded public key value
|
|
31
|
+
* @param format - Encoding format
|
|
32
|
+
* @return A public key instance
|
|
33
|
+
* @throws UnsupportedCurveError
|
|
34
|
+
* @throws UnsupportedPublicKeyFormatError
|
|
35
|
+
* @throws Error
|
|
36
|
+
*/
|
|
37
|
+
decodeEcPublicKey(
|
|
38
|
+
value: Uint8Array,
|
|
39
|
+
format: PublicKeyFormat
|
|
40
|
+
): EcPublicKey | Promise<EcPublicKey>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param data - Data to be signed
|
|
44
|
+
* @param privateKey - Private key to use for signing
|
|
45
|
+
* @param hash - Hash to apply
|
|
46
|
+
* @param format - Format to return the signature in
|
|
47
|
+
* @return Signature encoded in the specified format
|
|
48
|
+
* @throws UnsupportedHashError
|
|
49
|
+
* @throws UnsupportedSignatureFormatError
|
|
50
|
+
* @throws Error
|
|
51
|
+
*/
|
|
52
|
+
sign(
|
|
53
|
+
data: Uint8Array,
|
|
54
|
+
privateKey: EcPrivateKey,
|
|
55
|
+
hash: Hash,
|
|
56
|
+
format: SignatureFormat
|
|
57
|
+
): Uint8Array | Promise<Uint8Array>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param signature - X.509 ECDSASigValue ASN.1 type DER encoded
|
|
61
|
+
* @param data - Raw value
|
|
62
|
+
* @param key - The public key to verify against
|
|
63
|
+
* @param hash - Hash to apply
|
|
64
|
+
* @param format - Format the signature is encoded in
|
|
65
|
+
* @return true if the signature is valid
|
|
66
|
+
* @throws UnsupportedSignatureFormatError
|
|
67
|
+
* @throws Error
|
|
68
|
+
*/
|
|
69
|
+
verify(
|
|
70
|
+
signature: Uint8Array,
|
|
71
|
+
data: Uint8Array,
|
|
72
|
+
key: EcPublicKey,
|
|
73
|
+
hash: Hash,
|
|
74
|
+
format: SignatureFormat
|
|
75
|
+
): boolean | Promise<boolean>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface EcPublicKey {
|
|
79
|
+
/**
|
|
80
|
+
* @return The curve of the public key
|
|
81
|
+
*/
|
|
82
|
+
getCurve(): Curve;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param format - Format to encode with
|
|
86
|
+
* @return Encoded public key
|
|
87
|
+
*/
|
|
88
|
+
encode(format: PublicKeyFormat): Uint8Array | Promise<Uint8Array>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface EcPrivateKey {
|
|
92
|
+
/**
|
|
93
|
+
* @return The curve of the private key
|
|
94
|
+
*/
|
|
95
|
+
getCurve(): Curve;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @return The public key, if available
|
|
99
|
+
*/
|
|
100
|
+
getPublicKey(): EcPublicKey | null;
|
|
101
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type Curve =
|
|
2
|
+
| 'brainpool256r1'
|
|
3
|
+
| 'brainpool384r1'
|
|
4
|
+
| 'secp192k1'
|
|
5
|
+
| 'secp192r1'
|
|
6
|
+
| 'secp256k1'
|
|
7
|
+
| 'secp256r1'
|
|
8
|
+
| 'secp384r1';
|
|
9
|
+
|
|
10
|
+
export type PrivateKeyFormat = 'pkcs8-der'; // PKCS#8 PrivateKeyInfo ASN.1 type DER encoded
|
|
11
|
+
export type PublicKeyFormat = 'spki-der'; // X.509 SubjectPublicKeyInfo ASN.1 type DER encoded
|
|
12
|
+
export type SignatureFormat = 'sigvalue-der'; // X.509 ECDSASigValue ASN.1 type DER encoded
|
|
13
|
+
export type Hash = 'SHA-256';
|
package/tsconfig.json
ADDED