kalp-pkg
Version:
KALP blockchain SDK for cryptographic operations and blockchain interactions
846 lines (841 loc) • 33.4 kB
JavaScript
'use strict';
var ethers = require('ethers');
var elliptic = require('elliptic');
var jsrsasign = require('jsrsasign');
var CryptoJS = require('crypto-js');
var fetch = require('cross-fetch');
var crypto$1 = require('crypto');
//Common key const value
const P256_SIGN_CURVE = 'p256';
const SECP256R1_SIGN_CURVE = 'secp256r1';
const EXPORT_PUBLIC_KEY_FORMAT = 'spki';
const KEY_PAIR_FORMAT_TYPE = 'hex';
const EXPORT_PRIVATE_KEY_FORMAT = 'pkcs8';
const PRIVATE_KEY_TYPE = 'PKCS8PRV';
const SPECIAL_CHARACTERS = '!@#$%^&*+-=';
const UPPER_CASE_CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const LOWER_CASE_CHARACTERS = 'abcdefghijklmnopqrstuvwxyz';
const NUMBERS = '0123456789';
//For registration and certificates
const AUTHORIZATION_KEY = 'f5b1aca0717e01d0dbca408d281e9e5145250acb146ff9f0844d53e95aab30b5';
const CONTENT_TYPE = 'application/json';
const MAX_ENROLLMENTS = '-1';
const URL_CHANNEL_NAME = 'kalpstagenet';
const URL_CHANNEL_NAME_TESTNET = 'prod-test-mainnet';
const URL_CHANNEL_NAME_INTMAINNET = 'intmainnet-mailabs';
const NETWORK_GOVERNANCE_BASE_URL = 'https://dev-userreg-gov.p2eppl.com/v1';
const NETWORK_GOVERNANCE_STG_BASE_URL = 'https://stg-userreg-gov.p2eppl.com/v1';
const NETWORK_GOVERNANCE_TESTNET_BASE_URL = 'https://ngl-userreg-test.kalp.network/v1';
const REGISTER_URL = '/pki/register';
const ENROLL_CSR_URL = '/pki/enrollCsr';
const BASE_64_TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// Read and write function
const SIGN = 'sign';
const KEY_FORMAT = 'raw';
const SIGN_ALGORITHM = 'ECDSA';
const NAMED_CURVE = 'P-256';
const VERIFY_OPERATION = 'verify';
const HASH_ALGORITHM = 'SHA-256';
const SIGNATURE_ALGORITHM = 'SHA256withECDSA';
const BEGIN_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----';
const END_PRIVATE_KEY = '-----END PRIVATE KEY-----';
const KALP_GATEWAY_BASE_URL = 'https://stg-kalp-gateway.p2eppl.com/transaction/v1';
const KALP_GATEWAY_INTMAINNET_BASE_URL = 'https://intmainnet-kalp-gateway.p2eppl.com/transaction/v1';
const KALP_GATEWAY_TESTNET_BASE_URL = 'https://rpc-mumbai-test.kalp.network/transaction/v1';
const ENCRYPTION_KEY = 'asdfghjklqwyuiopzxcvbnm1234567890123456'; // Must be 32 characters for AES-256
// @ts-nocheck
//import { ethers } from 'ethers';
const EC = elliptic.ec;
// Cross-platform crypto support
let crypto;
if (typeof window !== 'undefined' && window.crypto) {
crypto = window.crypto;
}
else if (typeof global !== 'undefined') {
// Node.js environment
crypto = crypto$1.webcrypto;
}
else {
throw new Error('Crypto API not available in this environment');
}
/**
* Environment variable for the network you need to connect .
*/
const Network = {
Stagenet: 'STAGENET',
Testnet: 'TESTNET',
Mainnet: 'MAINNET',
IntegrationMainnet: 'INTEGRATIONMAINNET',
};
/**
* getSeedPhrase
*/
async function getSeedPhrase() {
try {
const wallet = ethers.Wallet.createRandom();
return wallet.mnemonic.phrase;
}
catch (error) {
throw new Error('An error occurred while getting seed phrase: ' + error.message);
}
}
/**
* getKeyPairFromSeedPhrase
* @param {string} seedPhrase - Need to give seedphrase.
*/
async function getKeyPairFromSeedPhrase(seedPhrase) {
try {
const ec = new EC(P256_SIGN_CURVE);
const mnemonic = ethers.Mnemonic.fromPhrase(seedPhrase);
const seed = await mnemonic.computeSeed();
// Generate ECDSA key pair
const key = ec.keyFromPrivate(seed);
const privateKey = key.getPrivate(KEY_PAIR_FORMAT_TYPE);
const publicKey = key.getPublic(KEY_PAIR_FORMAT_TYPE);
// Parse the hex private key
const convPrivateKey = jsrsasign.KEYUTIL.getKey({
curve: SECP256R1_SIGN_CURVE,
d: privateKey,
});
const pemPrivateKey = jsrsasign.KEYUTIL.getPEM(convPrivateKey, PRIVATE_KEY_TYPE);
const pemPublicKey = await convertPublicKeyHexToPem(publicKey);
return { pemPrivateKey, pemPublicKey };
}
catch (error) {
throw Error('An error occurred while getting keypair:' + error);
}
}
//convertPublicKeyHexToPem
async function convertPublicKeyHexToPem(pubKey) {
try {
const publicKeyBuffer = new Uint8Array(pubKey.length / 2);
for (let i = 0; i < pubKey.length; i += 2) {
publicKeyBuffer[i / 2] = parseInt(pubKey.substr(i, 2), 16);
}
const publicKey = await crypto.subtle.importKey(KEY_FORMAT, publicKeyBuffer, {
name: SIGN_ALGORITHM,
namedCurve: NAMED_CURVE,
}, true, [VERIFY_OPERATION]);
const publicKeyPem = await extractPublicKey(publicKey);
return publicKeyPem;
}
catch (error) {
throw new Error('An error occurred while converting public key hex format to pem' + error);
}
}
//extractPublicKey
async function extractPublicKey(publicKey) {
try {
const exportedKey = await crypto.subtle.exportKey(EXPORT_PUBLIC_KEY_FORMAT, publicKey); // Use SPKI format
const pemKey = await formatPublicKeyToPem(exportedKey); // Convert to PEM string
return pemKey;
}
catch (error) {
throw new Error('An error occurred while converting publicKey from cryptoKey format to pem: ' +
error);
}
}
//formatPublicKeyToPem
async function formatPublicKeyToPem(publicKey) {
try {
const publicKeyData = String.fromCharCode.apply(null, Array.from(new Uint8Array(publicKey)));
const base64Key = btoa(publicKeyData);
const pemKey = `-----BEGIN PUBLIC KEY-----\n${base64Key}\n-----END PUBLIC KEY-----\n`;
return pemKey;
}
catch (error) {
throw new Error('An error occurred while formatting base64key to pem key' + error);
}
}
/**
* getKeyPair
*/
async function getKeyPair() {
try {
const keyPair = await generateKeyPairUsingCryptoSubtle();
const privateKeyCrypto = keyPair.privateKey;
const publicKeyCrypto = keyPair.publicKey;
const pemPublicKey = await extractPublicKey(publicKeyCrypto);
const pemPrivateKey = await exportPrivateKeyAsPem(privateKeyCrypto);
return { pemPrivateKey, pemPublicKey };
}
catch (error) {
throw new Error('An error occurred while getting public and private key pair:' + error);
}
}
//generateKeyPairUsingCryptoSubtle
async function generateKeyPairUsingCryptoSubtle() {
try {
const keyPair = await crypto.subtle.generateKey({
name: SIGN_ALGORITHM,
namedCurve: NAMED_CURVE, // or "P-384" or "P-521"
}, true, [SIGN, VERIFY_OPERATION]);
return keyPair;
}
catch (error) {
throw new Error('An error occurred while generating key pair from generateKeyPairUsingCryptoSubtle function' +
error);
}
}
/**
* getEnrollmentId
* @param {string} publicKey - Provide PEM format public key.
*/
async function getEnrollmentId(publicKey) {
try {
const regex = /-----BEGIN PUBLIC KEY-----\r?\n|\r?\n?-----END PUBLIC KEY-----\r?\n?|\r?\n/g;
const pemPublicKeyString = publicKey.replace(regex, '');
const pemPublicKeyBytes = await decodeBase64String(pemPublicKeyString);
const hashedPemPublicKey = await hashByteArray(pemPublicKeyBytes);
const initialEnrollmentId = await convertByteArrayToString(hashedPemPublicKey);
const enrollmentID = initialEnrollmentId.slice(-40);
return enrollmentID;
}
catch (error) {
throw new Error('An error occurred while getting enrollmentId : ' + error);
}
}
//hashByteArray
async function hashByteArray(uint8Array) {
try {
const buffer = uint8Array.buffer.slice(uint8Array.byteOffset, uint8Array.byteOffset + uint8Array.byteLength);
const hashBuffer = await crypto.subtle.digest(HASH_ALGORITHM, buffer);
const hashUint8Array = new Uint8Array(hashBuffer);
return hashUint8Array;
}
catch (error) {
throw new Error('An error occurred while getting hashByteArray' + error);
}
}
//convertByteArrayToString
async function convertByteArrayToString(src) {
try {
const dst = new Uint8Array(src.length * 2); // Each byte will be represented by 2 characters in hexadecimal
for (let i = 0; i < src.length; i++) {
const byte = src[i];
dst[i * 2] = (byte >> 4) & 0xf; // High nibble
dst[i * 2 + 1] = byte & 0xf; // Low nibble
}
return Array.from(dst)
.map((byte) => byte.toString(16))
.join('');
}
catch (error) {
throw new Error('An error occurred in convertByteArrayToString function' + error);
}
}
/**
* createCsr
* @param {string} enrollmentID - provide enrollment id in string.
* @param {string} privateKeyPem - Provide PEM format private key.
* @param {string} publicKey - Provide PEM format public key.
*/
function createCsr(enrollmentID, privateKeyPem, publicKeyPem) {
try {
const csr = new jsrsasign.KJUR.asn1.csr.CertificationRequest({
subject: {
str: `/CN=${enrollmentID}/O=Your Organization/postalCode=Your Postal Code/L=Your Locality/ST=Your Province/C=IN`,
},
sbjpubkey: publicKeyPem,
sigalg: SIGNATURE_ALGORITHM,
sbjprvkey: privateKeyPem,
});
const pem = csr.getPEM();
return pem;
}
catch (error) {
throw new Error('An error occurred while Creating CSR :' + error);
}
}
/**
* GetNetworkGovernanceUrl - Outputs the base url of network governance layer
* @param {string} environment - provide environment detail in string format.
*/
function GetNetworkGovernanceUrl(environment) {
switch (environment) {
case Network.Stagenet:
return NETWORK_GOVERNANCE_BASE_URL;
case Network.IntegrationMainnet:
return NETWORK_GOVERNANCE_STG_BASE_URL;
case Network.Testnet:
return NETWORK_GOVERNANCE_TESTNET_BASE_URL;
default:
throw new Error('An error occurred while getting network governance url :' +
'invalid environment variable passed');
}
}
/**
* GetKalpGatewayUrl - Outputs the base url of kalp gateway
* @param {string} environment - provide environment detail in string format.
*/
function GetKalpGatewayUrl(environment) {
switch (environment) {
case Network.Stagenet:
return KALP_GATEWAY_BASE_URL;
case Network.IntegrationMainnet:
return KALP_GATEWAY_INTMAINNET_BASE_URL;
case Network.Testnet:
return KALP_GATEWAY_TESTNET_BASE_URL;
default:
throw new Error('An error occurred while getting kalp gateway url :' +
'invalid environment variable passed');
}
}
/**
* registerAndEnrollUser
* @param {string} network - provide network to which you want to register to.
* @param {string} enrollmentID - provide enrollment id in string.
* @param {string} csr - Provide certificate.
*/
async function registerAndEnrollUser(network, nglURL, channelName, enrollmentID, csr) {
try {
if (enrollmentID.length !== 40) {
throw new Error('Invalid enrollment ID: Must be 40 characters long.');
}
const encryptedWord = await getSecret(enrollmentID);
const networkGovernanceBaseUrl = nglURL || GetNetworkGovernanceUrl(network);
const endpoint = networkGovernanceBaseUrl + REGISTER_URL;
const headers = {
Authorization: AUTHORIZATION_KEY,
'Content-Type': CONTENT_TYPE,
};
const body = {
enrollmentid: enrollmentID,
secret: encryptedWord,
maxenrollments: MAX_ENROLLMENTS,
channel: channelName || getNGChannelName(network),
};
const response = await fetch(endpoint, {
method: 'POST',
headers: headers,
body: JSON.stringify(body),
});
if (!response.ok) {
const jsonData = await response.json();
const finalResponse = JSON.stringify(jsonData);
throw new Error('An error occurred while doing user registration' + finalResponse);
}
else {
const endpoint = networkGovernanceBaseUrl + ENROLL_CSR_URL;
const headers = {
Authorization: AUTHORIZATION_KEY,
'Content-Type': CONTENT_TYPE,
};
const body = {
enrollmentid: enrollmentID,
secret: encryptedWord,
csr: csr,
channel: channelName || getNGChannelName(network),
};
const response = await fetch(endpoint, {
method: 'POST',
headers: headers,
body: JSON.stringify(body),
});
if (!response.ok) {
const jsonData = await response.json();
const finalResponse = JSON.stringify(jsonData);
throw new Error('An error occurred while getting certificate' + finalResponse);
}
else {
const responseData = await response.json();
const cert = responseData.response.pubcert;
return cert;
}
}
}
catch (error) {
throw new Error('An error occurred in user registration process ' + error);
}
}
/**
* register
* @param {string} network - provide network to which you want to register to.
* @param {string} enrollmentID - provide enrollment id in string format.
* @param {string} encryptedWord - provide secret in string format.
*/
async function register(network, nglURL, channelName, enrollmentID, encryptedWord) {
try {
if (enrollmentID.length !== 40) {
throw new Error('Invalid enrollment ID: Must be 40 characters long.');
}
const networkGovernanceBaseUrl = nglURL || GetNetworkGovernanceUrl(network);
const endpoint = networkGovernanceBaseUrl + REGISTER_URL;
const headers = {
Authorization: AUTHORIZATION_KEY,
'Content-Type': CONTENT_TYPE,
};
const body = {
enrollmentid: enrollmentID,
secret: encryptedWord,
maxenrollments: MAX_ENROLLMENTS,
channel: channelName || getNGChannelName(network),
};
const response = await fetch(endpoint, {
method: 'POST',
headers: headers,
body: JSON.stringify(body),
});
if (!response.ok) {
const jsonData = await response.json();
const finalResponse = JSON.stringify(jsonData);
throw new Error('An error occurred while doing user registration' + finalResponse);
}
const jsonData = await response.json();
const responseData = JSON.stringify(jsonData);
return responseData;
}
catch (error) {
throw new Error('An error occurred while doing user registration' + error);
}
}
/**
* enrollCsr
* @param {string} network - provide network to which you want to register to.
* @param {string} enrollmentID - provide enrollment id in string format.
* @param {string} encryptedWord - provide secret in string format.
* @param {string} csr - Provide certificate.
*/
async function enrollCsr(network, nglURL, channelName, enrollmentID, encryptedWord, csr) {
try {
const networkGovernanceBaseUrl = nglURL || GetNetworkGovernanceUrl(network);
const endpoint = networkGovernanceBaseUrl + ENROLL_CSR_URL;
const headers = {
Authorization: AUTHORIZATION_KEY,
'Content-Type': CONTENT_TYPE,
};
const body = {
enrollmentid: enrollmentID,
secret: encryptedWord,
csr: csr,
channel: channelName || getNGChannelName(network),
};
const response = await fetch(endpoint, {
method: 'POST',
headers: headers,
body: JSON.stringify(body),
});
if (!response.ok) {
const jsonData = await response.json();
const finalResponse = JSON.stringify(jsonData);
throw new Error('An error occurred while getting certificate' + finalResponse);
}
else {
const responseData = await response.json();
const cert = responseData.response.pubcert;
return cert;
}
}
catch (error) {
throw new Error('An error occurred while getting certificate' + error);
}
}
/**
* getSecret
* @param {string} enrollmentID - provide enrollment id in string format.
*/
async function getSecret(enrollmentID) {
try {
function bufferToHex(buffer) {
return Array.from(new Uint8Array(buffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
}
// Encode the input string as a Uint8Array
const encoder = new TextEncoder();
const data = encoder.encode(enrollmentID);
// Hash the input using SHA-256
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hash = bufferToHex(hashBuffer);
// Define character sets
const upperCaseLetters = UPPER_CASE_CHARACTERS;
const lowerCaseLetters = LOWER_CASE_CHARACTERS;
const specialCharacters = SPECIAL_CHARACTERS;
const numbers = NUMBERS;
// Combine all characters into one string
const allCharacters = upperCaseLetters + lowerCaseLetters + specialCharacters + numbers;
// Function to get a character from allCharacters based on hash value
function getCharFromHash(hash, index) {
const charIndex = parseInt(hash.slice(index * 2, index * 2 + 2), 16) %
allCharacters.length;
return allCharacters[charIndex];
}
// Ensure at least one character from each set is included
let uniqueString = '';
uniqueString +=
upperCaseLetters[parseInt(hash.slice(0, 2), 16) % upperCaseLetters.length];
uniqueString +=
lowerCaseLetters[parseInt(hash.slice(2, 4), 16) % lowerCaseLetters.length];
uniqueString +=
specialCharacters[parseInt(hash.slice(4, 6), 16) % specialCharacters.length];
uniqueString += numbers[parseInt(hash.slice(6, 8), 16) % numbers.length];
// Fill the rest of the string with characters from the hash
for (let i = 4; i < 16; i++) {
uniqueString += getCharFromHash(hash, i);
}
return uniqueString;
}
catch (error) {
throw new Error('An error occurred while getting secret from enrollment ID ' + error);
}
}
/**
* submitTransaction
* @param {string} network - provide network to which you want to submit transaction.
* @param {string} enrollmentID - provide enrollment id in string.
* @param {string} pemPrivateKey - Provide PEM format private key.
* @param {string} cert - Provide certificate.
* @param {string} channelName - provide channelName in string.
* @param {string} chainCodeName - provide chainCodeName in string.
* @param {string} transactionName - provide transactionName in string.
* @param {Array} transactionParams - Provide transactionParams in an array.
*/
async function submitTransaction(network, gatewayURL, enrollmentID, pemPrivateKey, cert, channelName, chainCodeName, transactionName, transactionParams) {
try {
const domainName = gatewayURL || GetKalpGatewayUrl(network);
const proposalUrl = domainName + '/proposal';
const endorsementUrl = domainName + '/endorse';
const submitUrl = domainName + '/submit';
const commitSubmitUrl = domainName + '/commitstatus';
const privateKeyString = pemPrivateKey;
//try change name from privatekey to pemPrivate key
const transaction = {
enrollmentID: enrollmentID,
cert: cert,
channelName: channelName,
chainCodeName: chainCodeName,
transactionName: transactionName,
transactionParams: transactionParams,
};
//proposal
const proposalData = await restCall(proposalUrl, transaction);
let sigr = '';
let sigs = '';
const proposal = proposalData.message.proposal;
const proposalBytes = await decodeBase64String(proposal);
[sigr, sigs] = await signUsingElliptic(privateKeyString, proposalBytes);
const signedProposal = {
signedR: sigr,
signedS: sigs,
proposal: proposal,
};
//endorse
const endorseData = await restCall(endorsementUrl, signedProposal);
const endorse = endorseData.message.endorse;
const endorsedProposalBytes = await decodeBase64String(endorse);
[sigr, sigs] = await signUsingElliptic(privateKeyString, endorsedProposalBytes);
const signedEndorsedProposal = {
signedR: sigr,
signedS: sigs,
endorse: endorse,
};
//submit
const submitData = await restCall(submitUrl, signedEndorsedProposal);
const submit = submitData.message.submit;
const submitProposalBytes = await decodeBase64String(submit);
[sigr, sigs] = await signUsingElliptic(privateKeyString, submitProposalBytes);
const signedCommitProposal = {
signedR: sigr,
signedS: sigs,
submit: submit,
};
//commitstatus
const statusData = await restCall(commitSubmitUrl, signedCommitProposal);
function getTransactionId(statusData) {
return statusData.message.transaction_id;
}
const transactionId = getTransactionId(statusData);
return transactionId;
}
catch (error) {
throw new Error('An error occurred while submiting transaction ' + error);
}
}
/**
* evaluateTransaction
* @param {string} network - provide network to which you want to evaluate transaction.
* @param {string} enrollmentID - provide enrollment id in string.
* @param {string} privateKeyString - Provide PEM format private key.
* @param {string} cert - Provide certificate.
* @param {string} channelName - provide channelName in string.
* @param {string} chainCodeName - provide chainCodeName in string.
* @param {string} transactionName - provide transactionName in string.
* @param {Array} transactionParams - Provide transactionParams in an array.
*/
async function evaluateTransaction(network, gatewayURL, enrollmentID, privateKeyString, cert, channelName, chainCodeName, transactionName, transactionParams) {
try {
const domainName = gatewayURL || GetKalpGatewayUrl(network);
const proposalUrl = domainName + '/proposal';
const evaluateUrl = domainName + '/evaluate';
const transaction = {
enrollmentID: enrollmentID,
cert: cert,
channelName: channelName,
chainCodeName: chainCodeName,
transactionName: transactionName,
transactionParams: transactionParams,
};
const evaluateTransactionValue = await evaluateSignedTransaction(privateKeyString, proposalUrl, evaluateUrl, transaction);
return evaluateTransactionValue;
}
catch (error) {
throw new Error('An error occurred while evaluating transaction :' + error);
}
}
/**
* evaluateBalance
* @param {string} network - provide network to which you want to evaluate balance for.
* @param {string} enrollmentID - provide enrollment id in string.
* @param {string} privateKeyString - Provide PEM format private key.
* @param {string} cert - Provide certificate.
* @param {string} channelName - provide channelName in string.
* @param {string} chainCodeName - provide chainCodeName in string.
* @param {string} transactionName - provide transactionName in string.
* @param {Array} transactionParams - Provide transactionParams (enrollment id) in an array.
*/
const evaluateBalance = async (network, gatewayURL, enrollmentID, privateKeyString, cert, channelName, chainCodeName, transactionNameBalance, transactionParamsBalance) => {
try {
const domainName = gatewayURL || GetKalpGatewayUrl(network);
const proposalUrl = domainName + '/proposal';
const evaluateUrl = domainName + '/evaluate';
const transaction = {
enrollmentID: enrollmentID,
cert: cert,
channelName: channelName,
chainCodeName: chainCodeName,
transactionName: transactionNameBalance,
transactionParams: transactionParamsBalance,
};
const balance = await evaluateSignedTransaction(privateKeyString, proposalUrl, evaluateUrl, transaction);
return balance;
}
catch (error) {
throw new Error('An error occurred while getting balance :' + error);
}
};
//Common logic for Evaluate transaction function
async function evaluateSignedTransaction(privateKeyString, proposalUrl, evaluateUrl, transaction) {
try {
const proposalData = await restCall(proposalUrl, transaction);
let sigr = '';
let sigs = '';
const proposal = proposalData.message.proposal;
const proposalBytes = await decodeBase64String(proposal);
[sigr, sigs] = await signUsingElliptic(privateKeyString, proposalBytes);
const signedProposal = {
signedR: sigr,
signedS: sigs,
proposal: proposal,
};
const evaluateData = await restCall(evaluateUrl, signedProposal);
const transactionEvaluate = evaluateData.message.evaluate;
return transactionEvaluate;
}
catch (error) {
throw new Error('An error occurred while evaluateSignedTransaction :' + error);
}
}
//restCall
async function restCall(url, message) {
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': CONTENT_TYPE },
body: JSON.stringify(message),
});
const responseData = await response.json();
if (!response.ok) {
if (responseData !== null || '') {
throw new Error(`An error occurred while pinging url: ${url}, message: ${JSON.stringify(responseData)}`);
}
throw new Error(`An error occurred while pinging url: ${url}`);
}
else {
return responseData;
}
}
catch (error) {
throw new Error('An error occurred in restCall :' + error);
}
}
//base64string => []bytes , similar to golang
async function decodeBase64String(base64String) {
try {
const base64Table = BASE_64_TABLE;
// Prepare a map for reverse lookup
const decodeMap = {};
for (let i = 0; i < base64Table.length; i++) {
decodeMap[base64Table[i]] = i;
}
decodeMap['='] = 0;
// Decode Base64 string
const data = new Uint8Array(base64String.length);
let j = 0;
for (let i = 0; i < base64String.length; i += 4) {
const b1 = decodeMap[base64String[i]];
const b2 = decodeMap[base64String[i + 1]];
const b3 = decodeMap[base64String[i + 2]];
const b4 = decodeMap[base64String[i + 3]];
data[j] = (b1 << 2) | (b2 >> 4);
j++;
if (base64String[i + 2] !== '=') {
data[j] = (b2 << 4) | (b3 >> 2);
j++;
}
if (base64String[i + 3] !== '=') {
data[j] = (b3 << 6) | b4;
j++;
}
}
return data.slice(0, j);
}
catch (error) {
throw new Error('An error occurred in decodeBase64String function:' + error);
}
}
//exportPrivateKeyAsPem
async function exportPrivateKeyAsPem(privateKey) {
try {
// Export the key
const exportedKey = await crypto.subtle.exportKey(EXPORT_PRIVATE_KEY_FORMAT, privateKey);
// Convert the exported key to PEM format
const exportedAsString = String.fromCharCode.apply(null, Array.from(new Uint8Array(exportedKey)));
const exportedAsBase64 = btoa(exportedAsString);
const pemExportedKey = `-----BEGIN PRIVATE KEY-----\n${exportedAsBase64}\n-----END PRIVATE KEY-----\n`;
return pemExportedKey;
}
catch (error) {
throw new Error('An error occurred in exportPrivateKeyAsPem function :' + error);
}
}
//importPrivateKey
async function importPrivateKey(pem) {
try {
const pemString = pem
.replace(BEGIN_PRIVATE_KEY, '')
.replace(END_PRIVATE_KEY, '');
const binaryString = atob(pemString);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
const privateKeyData = bytes.buffer;
// Import the private key
const privateKey = await crypto.subtle.importKey(EXPORT_PRIVATE_KEY_FORMAT, privateKeyData, {
name: SIGN_ALGORITHM,
namedCurve: NAMED_CURVE, // Assuming ECDSA with P-256 curve
}, true, [SIGN]);
return privateKey;
}
catch (error) {
throw new Error('An error occurred in importPrivateKey function :' + error);
}
}
//signUsingElliptic
async function signUsingElliptic(privateKeyString, hashedBytesArray) {
try {
const { prvKeyHex } = jsrsasign.KEYUTIL.getKey(privateKeyString);
const ecdsa = new EC(P256_SIGN_CURVE);
const signKey = ecdsa.keyFromPrivate(prvKeyHex, KEY_PAIR_FORMAT_TYPE);
// Convert Uint8Array to Buffer for elliptic
const buffer = Buffer.from(hashedBytesArray);
const sig = ecdsa.sign(buffer, signKey);
const sigr = sig.r.toString();
const sigs = sig.s.toString();
return [sigr, sigs];
}
catch (error) {
throw new Error('An error occurred in signUsingElliptic function:' + error);
}
}
/**
* createRandSUsingPrivateKey
* @param {string} privateKeyString - Provide PEM format private key.
* @param {string} proposal - Proposal in string format.
*/
async function getRandSvalue(privateKeyString, proposal) {
try {
const privateKey = await importPrivateKey(privateKeyString);
let sigr = '';
let sigs = '';
const proposalBytes = await decodeBase64String(proposal);
[sigr, sigs] = await signUsingElliptic(privateKeyString, proposalBytes);
return [sigr, sigs];
}
catch (error) {
throw new Error('An error occurred while getting R and S value :' + error);
}
}
function getNGChannelName(network) {
try {
switch (network) {
case Network.IntegrationMainnet:
return URL_CHANNEL_NAME_INTMAINNET;
case Network.Stagenet:
return URL_CHANNEL_NAME;
case Network.Testnet:
return URL_CHANNEL_NAME_TESTNET;
default:
throw new Error('An error occurred while getting channel name :' +
'invalid environment variable passed');
}
}
catch (error) {
throw error;
}
}
/**
* getKeyPairFromPemPrivateKey
* @param {string} pemPrivateKey - PEM-encoded EC private key
* @returns {{ pemPrivateKey: string, pemPublicKey: string }}
*/
async function getKeyPairFromPemPrivateKey(pemPrivateKey) {
try {
const ec = new EC(P256_SIGN_CURVE);
// Parse the PEM to get the private key object
const parsedKey = jsrsasign.KEYUTIL.getKey(pemPrivateKey);
// Extract raw private key (hex string)
const privHex = parsedKey.prvKeyHex;
// Generate EC key pair from private key
const key = ec.keyFromPrivate(privHex, KEY_PAIR_FORMAT_TYPE);
// Get public key
const pubPoint = key.getPublic();
const pubHex = pubPoint.encode(KEY_PAIR_FORMAT_TYPE);
// Convert to PEM formats
const newPrivateKeyPem = jsrsasign.KEYUTIL.getPEM(parsedKey, PRIVATE_KEY_TYPE);
const newPublicKeyPem = await convertPublicKeyHexToPem(pubHex);
return {
pemPrivateKey: newPrivateKeyPem,
pemPublicKey: newPublicKeyPem,
};
}
catch (error) {
throw new Error('Failed to extract keypair from PEM private key: ' + error.message);
}
}
function encryptText(text) {
return CryptoJS.AES.encrypt(text, ENCRYPTION_KEY).toString();
}
function decryptText(ciphertext) {
const bytes = CryptoJS.AES.decrypt(ciphertext, ENCRYPTION_KEY);
return bytes.toString(CryptoJS.enc.Utf8);
}
exports.Network = Network;
exports.createCsr = createCsr;
exports.decryptText = decryptText;
exports.encryptText = encryptText;
exports.enrollCsr = enrollCsr;
exports.evaluateBalance = evaluateBalance;
exports.evaluateTransaction = evaluateTransaction;
exports.getEnrollmentId = getEnrollmentId;
exports.getKeyPair = getKeyPair;
exports.getKeyPairFromPemPrivateKey = getKeyPairFromPemPrivateKey;
exports.getKeyPairFromSeedPhrase = getKeyPairFromSeedPhrase;
exports.getRandSvalue = getRandSvalue;
exports.getSecret = getSecret;
exports.getSeedPhrase = getSeedPhrase;
exports.register = register;
exports.registerAndEnrollUser = registerAndEnrollUser;
exports.signUsingElliptic = signUsingElliptic;
exports.submitTransaction = submitTransaction;
//# sourceMappingURL=index.js.map