mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-18 07:55:10 +00:00
* Import Full Stack Asset Transfer Guide at commit fb554befdbbeff9e69159b54fce0b811603f29c7 Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * Update the workshop with a new WORKSHOP_PATH under fabric-samples Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * Update the workshop with a new WORKSHOP_PATH under fabric-samples Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * missed a .git ignored directory on add Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * Updates to run the workshop on the Apple M1 Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * Workaround for https://github.com/eslint/eslint/issues/15299 in the contract tslinter Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * Build an arch-specific CC images on M1 Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * empty commit - force a build Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> * revert an accidental commit that was building the top-level asset-transfer as arm64 Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com> Signed-off-by: Josh Kneubuhl <jkneubuh@us.ibm.com>
131 lines
4 KiB
TypeScript
131 lines
4 KiB
TypeScript
/*
|
|
* Copyright IBM Corp. All Rights Reserved.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { Identity, Signer, signers } from '@hyperledger/fabric-gateway';
|
|
import { promises as fs } from 'fs';
|
|
import * as path from 'path';
|
|
import * as crypto from 'crypto';
|
|
import { errorMonitor } from 'events';
|
|
|
|
/** Internal interface used to describe all the possible components
|
|
* of the identity
|
|
*/
|
|
interface JSONID {
|
|
name: string;
|
|
cert: string;
|
|
ca: string;
|
|
hsm: boolean;
|
|
private_key?: string;
|
|
privateKey?: string;
|
|
mspId: string;
|
|
}
|
|
|
|
/**
|
|
* This class can be used to map identities in a variety of JSON formats to the Identity and Signers required
|
|
* for the gateway. For example if you have an application wallet, or have exported IDs from SaaS
|
|
*
|
|
* ```
|
|
* const jsonAdapter: JSONIDAdapter = new JSONIDAdapter(path.resolve(__dirname,'..','wallet'))
|
|
*
|
|
* const gateway = connect({
|
|
* client,
|
|
* identity: await jsonAdapter.getIdentity("appuser"),
|
|
* signer: await jsonAdapter.getSigner("appuser"),
|
|
* });
|
|
* ```
|
|
*
|
|
* Though they are JSON files, typically they files will have the .id extension. Therefore
|
|
* if no extension is provided `.id` is added
|
|
*/
|
|
export default class JSONIDAdapter {
|
|
private idFilesDir: string;
|
|
private mspId = '';
|
|
|
|
/**
|
|
* @param idFilesDir Directory to load the files from
|
|
* @param mspId optional MSPID to apply to all identities returned if they are missing it
|
|
*/
|
|
public constructor(idFilesDir: string, mspId?: string) {
|
|
this.idFilesDir = path.resolve(idFilesDir);
|
|
|
|
if (mspId) {
|
|
this.mspId = mspId;
|
|
}
|
|
}
|
|
|
|
private async readIDFile(idFile: string): Promise<JSONID> {
|
|
let idJsonFile = path.resolve(path.join(this.idFilesDir, idFile));
|
|
|
|
// check if there's no extension probably means it's a waller id file
|
|
if (path.extname(idJsonFile) === '') {
|
|
idJsonFile = `${idJsonFile}.id`;
|
|
}
|
|
|
|
let id: JSONID;
|
|
const json = JSON.parse(await fs.readFile(idJsonFile, 'utf-8'));
|
|
|
|
// look for the nested credentials element
|
|
const credentials = json['credentials'];
|
|
|
|
if (credentials) {
|
|
// v2 SDK Wallet format
|
|
id = {
|
|
name: idFile,
|
|
cert: credentials['certificate'],
|
|
ca: '',
|
|
hsm: false,
|
|
private_key: credentials['privateKey'],
|
|
mspId: json.mspId,
|
|
};
|
|
} else {
|
|
// IBP exported ID style format
|
|
id = {
|
|
name: json.name,
|
|
cert: Buffer.from(json.cert, 'base64').toString(),
|
|
ca: Buffer.from(json.ca, 'base64').toString(),
|
|
hsm: json.js,
|
|
private_key: Buffer.from(json.private_key, 'base64').toString(),
|
|
mspId: this.mspId,
|
|
};
|
|
}
|
|
return id;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param idFile the name of the identity to load (if no extension is provided `.id` is added)
|
|
* @returns Identity to use with the GatewayBuilder
|
|
*/
|
|
public async getIdentity(idFile: string): Promise<Identity> {
|
|
const id = await this.readIDFile(idFile);
|
|
|
|
const identity: Identity = {
|
|
credentials: Buffer.from(id.cert),
|
|
mspId: id.mspId,
|
|
};
|
|
|
|
return identity;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param idFile the name of the identity to load (if no extension is provided `.id` is added)
|
|
* @returns Signer to use with the GatewayBuilder
|
|
*/
|
|
public async getSigner(idFile: string): Promise<Signer> {
|
|
const id = await this.readIDFile(idFile);
|
|
let pk;
|
|
if (id.private_key) {
|
|
pk = id.private_key;
|
|
} else if ('privateKey' in id) {
|
|
pk = id['privateKey'];
|
|
} else {
|
|
throw new Error('Unable to parse the identity json file');
|
|
}
|
|
const privateKey = crypto.createPrivateKey(pk as string);
|
|
return signers.newPrivateKeySigner(privateKey);
|
|
}
|
|
}
|