mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
Update TypeScript HSM sample application
- Update to Node 16. - Simplify SKI code using Node standard packages and avoiding use of jsrsasign. Signed-off-by: Mark S. Lewis <Mark.S.Lewis@outlook.com>
This commit is contained in:
parent
f2c1c59c50
commit
30f70f6e73
3 changed files with 31 additions and 31 deletions
|
|
@ -4,7 +4,7 @@
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/hsm-sample.js",
|
"main": "dist/hsm-sample.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=16"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
|
@ -17,18 +17,16 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hyperledger/fabric-gateway": "^1.1.1",
|
"@hyperledger/fabric-gateway": "^1.1.1"
|
||||||
"jsrsasign": "^10.3.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tsconfig/node14": "^1.0.1",
|
"@tsconfig/node16": "^16.1.1",
|
||||||
"@types/jsrsasign": "^9.0.3",
|
"@types/node": "^16.18.48",
|
||||||
"@types/node": "^14.17.32",
|
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
"@typescript-eslint/parser": "^6.6.0",
|
||||||
"@typescript-eslint/parser": "^5.3.0",
|
|
||||||
"eslint": "^8.1.0",
|
"eslint": "^8.1.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^5.0.1",
|
||||||
"typescript": "~4.5.4"
|
"typescript": "~5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as grpc from '@grpc/grpc-js';
|
import * as grpc from '@grpc/grpc-js';
|
||||||
import * as crypto from 'crypto';
|
|
||||||
import { connect, Gateway, HSMSigner, HSMSignerFactory, HSMSignerOptions, signers } from '@hyperledger/fabric-gateway';
|
import { connect, Gateway, HSMSigner, HSMSignerFactory, HSMSignerOptions, signers } from '@hyperledger/fabric-gateway';
|
||||||
|
import * as crypto from 'crypto';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as jsrsa from 'jsrsasign';
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { TextDecoder } from 'util';
|
import { TextDecoder } from 'util';
|
||||||
|
|
||||||
|
|
@ -42,7 +41,7 @@ async function main() {
|
||||||
|
|
||||||
// Get the signer function and a close function. The close function closes the signer
|
// Get the signer function and a close function. The close function closes the signer
|
||||||
// once there is no further need for it.
|
// once there is no further need for it.
|
||||||
hsmSigner = await newHSMSigner(hsmSignerFactory, credentials.toString());
|
hsmSigner = newHSMSigner(hsmSignerFactory, credentials);
|
||||||
gateway = connect({
|
gateway = connect({
|
||||||
client,
|
client,
|
||||||
identity: { mspId, credentials },
|
identity: { mspId, credentials },
|
||||||
|
|
@ -100,8 +99,9 @@ async function newGrpcConnection(): Promise<grpc.Client> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new HSM Signer
|
// Create a new HSM Signer
|
||||||
async function newHSMSigner(hsmSignerFactory: HSMSignerFactory, certificatePEM: string): Promise<HSMSigner> {
|
function newHSMSigner(hsmSignerFactory: HSMSignerFactory, certificatePEM: Buffer): HSMSigner {
|
||||||
const ski = getSKIFromCertificate(certificatePEM);
|
const certificate = new crypto.X509Certificate(certificatePEM);
|
||||||
|
const ski = getSKIFromCertificate(certificate);
|
||||||
|
|
||||||
// Options for the signer based on using SoftHSM with Token initialized as follows
|
// Options for the signer based on using SoftHSM with Token initialized as follows
|
||||||
// softhsm2-util --init-token --slot 0 --label "ForFabric" --pin 98765432 --so-pin 1234
|
// softhsm2-util --init-token --slot 0 --label "ForFabric" --pin 98765432 --so-pin 1234
|
||||||
|
|
@ -139,23 +139,25 @@ function findSoftHSMPKCS11Lib(): string {
|
||||||
// fabric-ca-client set's the CKA_ID of the public/private keys in the HSM to a generated SKI
|
// fabric-ca-client set's the CKA_ID of the public/private keys in the HSM to a generated SKI
|
||||||
// value. This function replicates that calculation from a certificate PEM so that the HSM
|
// value. This function replicates that calculation from a certificate PEM so that the HSM
|
||||||
// object associated with the certificate can be found
|
// object associated with the certificate can be found
|
||||||
function getSKIFromCertificate(certificatePEM: string): Buffer {
|
function getSKIFromCertificate(certificate: crypto.X509Certificate): Buffer {
|
||||||
const key = jsrsa.KEYUTIL.getKey(certificatePEM);
|
const uncompressedPoint = getUncompressedPointOnCurve(certificate.publicKey);
|
||||||
const uncompressedPoint = getUncompressedPointOnCurve(key as jsrsa.KJUR.crypto.ECDSA);
|
return crypto.createHash('sha256').update(uncompressedPoint).digest();
|
||||||
const hashBuffer = crypto.createHash('sha256');
|
|
||||||
hashBuffer.update(uncompressedPoint);
|
|
||||||
|
|
||||||
const digest = hashBuffer.digest('hex');
|
|
||||||
return Buffer.from(digest, 'hex');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUncompressedPointOnCurve(key: jsrsa.KJUR.crypto.ECDSA): Buffer {
|
function getUncompressedPointOnCurve(key: crypto.KeyObject): Buffer {
|
||||||
const xyhex = key.getPublicKeyXYHex();
|
const jwk = key.export({ format: 'jwk' });
|
||||||
const xBuffer = Buffer.from(xyhex.x, 'hex');
|
const x = Buffer.from(assertDefined(jwk.x), 'base64url');
|
||||||
const yBuffer = Buffer.from(xyhex.y, 'hex');
|
const y = Buffer.from(assertDefined(jwk.y), 'base64url');
|
||||||
const uncompressedPrefix = Buffer.from('04', 'hex');
|
const prefix = Buffer.from('04', 'hex');
|
||||||
const uncompressedPoint = Buffer.concat([uncompressedPrefix, xBuffer, yBuffer]);
|
return Buffer.concat([prefix, x, y]);
|
||||||
return uncompressedPoint;
|
}
|
||||||
|
|
||||||
|
function assertDefined<T>(value: T | undefined): T {
|
||||||
|
if (value === undefined) {
|
||||||
|
throw new Error('required value was undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
"extends": "@tsconfig/node14/tsconfig.json",
|
"extends": "@tsconfig/node16/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue