-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Expand file tree
/
Copy pathjsonid-adapter.ts
More file actions
130 lines (116 loc) · 3.93 KB
/
jsonid-adapter.ts
File metadata and controls
130 lines (116 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
import { Identity, Signer, signers } from '@hyperledger/fabric-gateway';
import * as crypto from 'crypto';
import { promises as fs } from 'fs';
import * as path from 'path';
/** 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);
}
}