Files
grin-web-wallet/scripts/crypto.js
2024-12-20 18:08:44 -08:00

1195 lines
30 KiB
JavaScript
Executable File

// Use strict
"use strict";
// Classes
// Crypto class
class Crypto {
// Public
// Derive child key
static deriveChildKey(extendedPrivateKey, paths, useBip39 = false) {
// Return promise
return new Promise(function(resolve, reject) {
// Get secret key and chain code from extended private key
var secretKey = extendedPrivateKey.subarray(0, Crypto.SECP256K1_SECRET_KEY_LENGTH);
var chainCode = extendedPrivateKey.subarray(Crypto.CHAIN_CODE_LENGTH);
// Set update values
var updateValues = new Promise(function(resolve, reject) {
// Resolve secret key and chain code
resolve([
// Copy secret key
new Uint8Array(secretKey),
// Copy chain code
new Uint8Array(chainCode)
]);
});
// Initialize updating values
var updatingValues = [updateValues];
// Go through all of the paths
for(let i = 0; i < paths["length"]; ++i) {
// Set update to run after the previous update
updateValues = updateValues.then(function(values) {
// Return promise
return new Promise(function(resolve, reject) {
// Get updated secret key and chain code
var updatedSecretKey = values[Crypto.SECRET_KEY_INDEX];
var updatedChainCode = values[Crypto.CHAIN_CODE_INDEX];
// Return deriving the next secret key and chain code using the path
return Crypto.deriveSecretKeyAndChainCode(updatedSecretKey, updatedChainCode, paths[i], useBip39).then(function(updatedValues) {
// Securely clear updated secret key and chain code
updatedSecretKey.fill(0);
updatedChainCode.fill(0);
// Resolve updated values
resolve(updatedValues);
// Catch errors
}).catch(function(error) {
// Securely clear secret key and chain code
updatedSecretKey.fill(0);
updatedChainCode.fill(0);
// Reject error
reject(error);
});
});
// Catch errors
}).catch(function(error) {
// Return Promise
return new Promise(function(resolve, reject) {
// Reject error
reject(error);
});
});
// Append updating value to list
updatingValues.push(updateValues);
}
// Return updating all values
return Promise.all(updatingValues).then(function(values) {
// Get updated secret key and chain code
var updatedSecretKey = values[values["length"] - 1][Crypto.SECRET_KEY_INDEX];
var updatedChainCode = values[values["length"] - 1][Crypto.CHAIN_CODE_INDEX];
// Initialize new extended private key
var newExtendedPrivateKey = Common.mergeArrays([
// Updated secret key
updatedSecretKey,
// Chain code
updatedChainCode
]);
// Securely clear updated secret key and chain code
updatedSecretKey.fill(0);
updatedChainCode.fill(0);
// Check if new extended private key's secret key is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(newExtendedPrivateKey.subarray(0, Crypto.SECP256K1_SECRET_KEY_LENGTH)) === true) {
// Resolve new extended private key
resolve(newExtendedPrivateKey);
}
// Otherwise
else {
// Securely clear new extended private key
newExtendedPrivateKey.fill(0);
// Reject error
reject("Invalid extended private key.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Commit
static commit(extendedPrivateKey, amount, identifier, switchType) {
// Return promise
return new Promise(function(resolve, reject) {
// Return deriving secret key from extended private key, amount, identifier, and switch type
return Crypto.deriveSecretKey(extendedPrivateKey, amount, identifier, switchType).then(function(secretKey) {
// Check if performing Pedersen commit with the secret key and amount was successful
var commit = Secp256k1Zkp.pedersenCommit(secretKey, amount.toFixed());
if(commit !== Secp256k1Zkp.OPERATION_FAILED) {
// Resolve commit
resolve(commit);
}
// Otherwise
else {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject("Performing Pedersen commit failed.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Commit amount
static commitAmount(amount) {
// Check if performing Pedersen commit with zero blinding factor and amount was successful
var commit = Secp256k1Zkp.pedersenCommit(Crypto.ZERO_BLINDING_FACTOR, amount.toFixed());
if(commit !== Secp256k1Zkp.OPERATION_FAILED) {
// Return commit
return commit;
}
// Otherwise
else {
// Throw error
throw "Performing Pedersen commit failed.";
}
}
// Proof
static proof(extendedPrivateKey, amount, identifier, switchType, proofBuilder) {
// Return promise
return new Promise(function(resolve, reject) {
// Return getting commit from extended private key, amount, identifier, and switch type
return Crypto.commit(extendedPrivateKey, amount, identifier, switchType).then(function(commit) {
// Return deriving secret key from extended private key, amount, identifier, and switch type
return Crypto.deriveSecretKey(extendedPrivateKey, amount, identifier, switchType).then(function(secretKey) {
// Return getting rewind nonce from the commit
return proofBuilder.rewindNonce(commit).then(function(rewindNonce) {
// Return getting private nonce from the commit
return proofBuilder.privateNonce(commit).then(function(privateNonce) {
// Try
try {
// Get proof message from identifier and switch type
var message = proofBuilder.proofMessage(identifier, switchType);
}
// Catch errors
catch(error) {
// Securely clear secret key
secretKey.fill(0);
// Securely clear rewind nonce
rewindNonce.fill(0);
// Securely clear private nonce
privateNonce.fill(0);
// Reject error
reject("Getting proof message failed.");
// Return
return;
}
// Check if creating bulletproof with the secret key, amount, rewind nonce, private nonce, and message was successful
var bulletproof = Secp256k1Zkp.createBulletproof(secretKey, amount.toFixed(), rewindNonce, privateNonce, new Uint8Array([]), message);
if(bulletproof !== Secp256k1Zkp.OPERATION_FAILED) {
// Securely clear secret key
secretKey.fill(0);
// Securely clear rewind nonce
rewindNonce.fill(0);
// Securely clear private nonce
privateNonce.fill(0);
// Resolve bulletproof
resolve(bulletproof);
}
// Otherwise
else {
// Securely clear secret key
secretKey.fill(0);
// Securely clear rewind nonce
rewindNonce.fill(0);
// Securely clear private nonce
privateNonce.fill(0);
// Reject error
reject("Getting bulletproof failed.");
}
// Catch errors
}).catch(function(error) {
// Securely clear secret key
secretKey.fill(0);
// Securely clear rewind nonce
rewindNonce.fill(0);
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Derive secret key
static deriveSecretKey(extendedPrivateKey, amount, identifier, switchType) {
// Return promise
return new Promise(function(resolve, reject) {
// Initialize paths
var paths = new Uint32Array(identifier.getDepth());
// Go through all the identifier's paths
for(var i = 0; i < identifier.getDepth(); ++i) {
// Set path to identifier's path
paths[i] = identifier.getPaths()[i];
}
// Return deriving the child key at the path from the extended private key
return Crypto.deriveChildKey(extendedPrivateKey, paths).then(function(childKey) {
// Get secret key from the child key
var secretKey = new Uint8Array(childKey.subarray(0, Crypto.SECP256K1_SECRET_KEY_LENGTH));
// Securely clear child key
childKey.fill(0);
// Check if switch type is none
if(switchType === Crypto.SWITCH_TYPE_NONE)
// Resolve secret key
resolve(secretKey);
// Otherwise check if switch type is regular
else if(switchType === Crypto.SWITCH_TYPE_REGULAR) {
// Check if getting blind switch of secret key and amount failed
var blindSwitch = Secp256k1Zkp.blindSwitch(secretKey, amount.toFixed());
if(blindSwitch === Secp256k1Zkp.OPERATION_FAILED) {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject("Performing blind switch failed.");
// Return
return;
}
// Securely clear secret key
secretKey.fill(0);
// Check if blind switch is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(blindSwitch) === true) {
// Resolve blind switch
resolve(blindSwitch);
}
// Otherwise
else {
// Securely clear blind switch
blindSwitch.fill(0);
// Reject error
reject("Blind switch isn't a valid secret key.");
}
}
// Otherwise
else {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject("Invalid switch type.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Signature message
static signatureMessage(data) {
// Check if creating message was successful
var message = Blake2b.compute(Crypto.SINGLE_SIGNER_MESSAGE_LENGTH, data, new Uint8Array([]));
if(message !== Blake2b.OPERATION_FAILED) {
// Return message
return message;
}
// Otherwise
else {
// Throw error
throw "Creating signature message failed.";
}
}
// Root public key
static rootPublicKey(extendedPrivateKey) {
// Return promise
return new Promise(function(resolve, reject) {
// Get secret key from extended private key
var secretKey = extendedPrivateKey.subarray(0, Crypto.SECP256K1_SECRET_KEY_LENGTH);
// Check if getting public key from secret key was successful
var publicKey = Secp256k1Zkp.publicKeyFromSecretKey(secretKey);
if(publicKey !== Secp256k1Zkp.OPERATION_FAILED) {
// Resolve public key
resolve(publicKey);
}
// Otherwise
else {
// Reject error
reject("Getting public key failed.");
}
});
}
// Address key
static addressKey(extendedPrivateKey, index) {
// Return promise
return new Promise(function(resolve, reject) {
// Check wallet type
switch(Consensus.getWalletType()) {
// MWC wallet
case Consensus.MWC_WALLET_TYPE:
// Return deriving root key from extended private key, address key amount, root identifier, and regular switch type
return Crypto.deriveSecretKey(extendedPrivateKey, Crypto.ADDRESS_KEY_AMOUNT, new Identifier(Identifier.ROOT_SERIALIZED_IDENTIFIER), Crypto.SWITCH_TYPE_REGULAR).then(function(rootKey) {
// Return creating crypto key from address key seed
return crypto["subtle"].importKey("raw", (new TextEncoder()).encode(Crypto.ADDRESS_KEY_SEED), {
// Name
"name": Crypto.ADDRESS_KEY_ENCRYPTION_ALGORITHM,
// Hash
"hash": {
// Name
"name": Crypto.ADDRESS_KEY_DIGEST_ALGORITHM
}
}, false, [
// Sign
"sign"
]).then(function(cryptoKey) {
// Return creating address extended private key from signing the root key
return crypto["subtle"].sign(Crypto.ADDRESS_KEY_ENCRYPTION_ALGORITHM, cryptoKey, rootKey).then(function(addressExtendedPrivateKey) {
// Securely clear root key
rootKey.fill(0);
// Get address extended private key in correct format
addressExtendedPrivateKey = new Uint8Array(addressExtendedPrivateKey);
// Get secret key and chain code from address extended private key
var secretKey = addressExtendedPrivateKey.subarray(0, Crypto.SECP256K1_SECRET_KEY_LENGTH);
var chainCode = addressExtendedPrivateKey.subarray(Crypto.CHAIN_CODE_LENGTH);
// Check if secret key is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(secretKey) === true) {
// Return updating the next secret key and chain code using the index
return Crypto.deriveSecretKeyAndChainCode(secretKey, chainCode, index).then(function(value) {
// Securely clear address extended private key
addressExtendedPrivateKey.fill(0);
// Securely clear the chain code
value[Crypto.CHAIN_CODE_INDEX].fill(0);
// Resolve the secret key
resolve(value[Crypto.SECRET_KEY_INDEX]);
// Catch errors
}).catch(function(error) {
// Securely clear address extended private key
addressExtendedPrivateKey.fill(0);
// Reject error
reject(error);
});
}
// Otherwise
else {
// Securely clear address extended private key
addressExtendedPrivateKey.fill(0);
// Reject error
reject("Secret key is not a valid secret key.");
}
// Catch errors
}).catch(function(error) {
// Securely clear root key
rootKey.fill(0);
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Securely clear root key
rootKey.fill(0);
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
// GRIN or EPIC wallet
case Consensus.GRIN_WALLET_TYPE:
case Consensus.EPIC_WALLET_TYPE:
// Create child identifier
var childIdentifier = new Identifier().getChild();
childIdentifier.getPaths()[1] = 1;
childIdentifier.getPaths()[childIdentifier.getDepth() - 1] = index;
// Return deriving root key from extended private key, child identifier, and no switch type
return Crypto.deriveSecretKey(extendedPrivateKey, new BigNumber(0), childIdentifier, Crypto.SWITCH_TYPE_NONE).then(function(rootKey) {
// Check if getting secret key from root key was successful
var secretKey = Blake2b.compute(Crypto.SECP256K1_SECRET_KEY_LENGTH, rootKey, new Uint8Array([]));
if(secretKey !== Blake2b.OPERATION_FAILED) {
// Securely clear root key
rootKey.fill(0);
// Check if secret key is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(secretKey) === true) {
// Resolve the secret key
resolve(secretKey);
}
// Otherwise
else {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject("Secret key is not a valid secret key.");
}
}
// Otherwise
else {
// Securely clear root key
rootKey.fill(0);
// Reject error
reject("Getting secret key from root key failed.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
}
});
}
// Login key
static loginKey(extendedPrivateKey) {
// Return promise
return new Promise(function(resolve, reject) {
// Create child identifier
var childIdentifier = new Identifier().getChild();
childIdentifier.getPaths()[1] = 2;
// Return deriving root key from extended private key, child identifier, and no switch type
return Crypto.deriveSecretKey(extendedPrivateKey, new BigNumber(0), childIdentifier, Crypto.SWITCH_TYPE_NONE).then(function(rootKey) {
// Check if getting secret key from root key was successful
var secretKey = Blake2b.compute(Crypto.SECP256K1_SECRET_KEY_LENGTH, rootKey, new Uint8Array([]));
if(secretKey !== Blake2b.OPERATION_FAILED) {
// Securely clear root key
rootKey.fill(0);
// Check if secret key is a valid secret key
if(Secp256k1Zkp.isValidSecretKey(secretKey) === true) {
// Resolve the secret key
resolve(secretKey);
}
// Otherwise
else {
// Securely clear secret key
secretKey.fill(0);
// Reject error
reject("Secret key is not a valid secret key.");
}
}
// Otherwise
else {
// Securely clear root key
rootKey.fill(0);
// Reject error
reject("Getting secret key from root key failed.");
}
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// AES decrypt
static aesDecrypt(encryptedData, key) {
// Return promise
return new Promise(function(resolve, reject) {
// Return importing the key
return crypto["subtle"].importKey("raw", key, {
// Name
"name": Crypto.AES_ALGORITHM
}, false, [
// Decrypt
"decrypt"
]).then(function(cryptoKey) {
// Return decrypting the encrypted data using the AES key
return crypto["subtle"].decrypt({
// Name
"name": Crypto.AES_ALGORITHM,
// Initialization vector
"iv": (new Uint8Array(Crypto.AES_INITIALIZATION_VECTOR_SIZE)).fill(0)
}, cryptoKey, encryptedData).then(function(decryptedData) {
// TODO Securely clear cryptoKey
// Resolve decrypted data
resolve(new Uint8Array(decryptedData));
// Catch errors
}).catch(function(error) {
// TODO Securely clear cryptoKey
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject(error);
});
});
}
// Switch type none
static get SWITCH_TYPE_NONE() {
// Return switch type none
return 0;
}
// Switch type regular
static get SWITCH_TYPE_REGULAR() {
// Return switch type regular
return Crypto.SWITCH_TYPE_NONE + 1;
}
// Secp256k1 secret key length
static get SECP256K1_SECRET_KEY_LENGTH() {
// Return secp256k1 secret key length
return 32;
}
// Secp256k1 public key length
static get SECP256K1_PUBLIC_KEY_LENGTH() {
// Return secp256k1 public key length
return 33;
}
// Blinding factor length
static get BLINDING_FACTOR_LENGTH() {
// Return blinding factor length
return 32;
}
// Commit length
static get COMMIT_LENGTH() {
// Return commit length
return 33;
}
// Single-signer signature length
static get SINGLE_SIGNER_SIGNATURE_LENGTH() {
// Return single-signer signature length
return 64;
}
// Single-signer message length
static get SINGLE_SIGNER_MESSAGE_LENGTH() {
// Return single-signer message length
return 32;
}
// Proof length
static get PROOF_LENGTH() {
// Return proof length
return 675;
}
// Zero blinding factor
static get ZERO_BLINDING_FACTOR() {
// No zero blinding factor
return (new Uint8Array(Crypto.BLINDING_FACTOR_LENGTH)).fill(0);
}
// Zero secret key
static get ZERO_SECRET_KEY() {
// No zero blinding factor
return (new Uint8Array(Crypto.SECP256K1_SECRET_KEY_LENGTH)).fill(0);
}
// Ed25519 secret key length
static get ED25519_SECRET_KEY_LENGTH() {
// Return Ed25519 secret key length
return 32;
}
// Ed25519 public key length
static get ED25519_PUBLIC_KEY_LENGTH() {
// Return Ed25519 public key length
return 32;
}
// X25519 secret key length
static get X25519_SECRET_KEY_LENGTH() {
// Return X25519 secret key length
return 32;
}
// X25519 public key length
static get X25519_PUBLIC_KEY_LENGTH() {
// Return X25519 public key length
return 32;
}
// Ed25519 signature length
static get ED25519_SIGNATURE_LENGTH() {
// Return Ed25519 signature length
return 64;
}
// Maximum message hash signature length
static get MAXIMUM_MESSAGE_HASH_SIGNATURE_LENGTH() {
// Return maximum message hash signature length
return 72;
}
// Nonce length
static get NONCE_LENGTH() {
// Return nonce length
return 32;
}
// Tau x length
static get TAU_X_LENGTH() {
// Return tau x length
return 32;
}
// AES key length
static get AES_KEY_LENGTH() {
// Return AES key length
return 32;
}
// Private
// Derive secret key and chain code
static deriveSecretKeyAndChainCode(secretKey, chainCode, path, useBip39 = false) {
// Return promise
return new Promise(function(resolve, reject) {
// Return creating crypto key from chain code
return crypto["subtle"].importKey("raw", chainCode, {
// Name
"name": Crypto.CHAIN_CODE_ENCRYPTION_ALGORITHM,
// Hash
"hash": {
// Name
"name": Crypto.CHAIN_CODE_DIGEST_ALGORITHM
}
}, false, [
// Sign
"sign"
]).then(function(cryptoKey) {
// Check if path is hardened
if(Identifier.isPathHardened(path) === true) {
// Get hash value from secret key
var hashValue = Common.mergeArrays([
// Zero
new Uint8Array([0]),
// Secret key
secretKey
]);
}
// Otherwise
else {
// Check if getting hash value as public key from secret key failed
var hashValue = Secp256k1Zkp.publicKeyFromSecretKey(secretKey);
if(hashValue === Secp256k1Zkp.OPERATION_FAILED) {
// TODO Securely clear cryptoKey
// Reject error
reject("Getting public key from secret key failed.");
// Return
return;
}
}
// Create secret key and chain code
var createSecretKeyAndChainCode = function(hashValueCandidate) {
// Return promise
return new Promise(function(resolve, reject) {
// Append path to hash value candidate
var pathBuffer = new ArrayBuffer(Uint32Array["BYTES_PER_ELEMENT"]);
var pathBufferView = new DataView(pathBuffer);
pathBufferView.setUint32(0, path, false);
var newHashValue = Common.mergeArrays([
// Hash value candidate
hashValueCandidate,
// Path
new Uint8Array(pathBuffer)
]);
// Securely clear hash value candidate
hashValueCandidate.fill(0);
// Return creating new extended private key from signing the new hash value
return crypto["subtle"].sign(Crypto.CHAIN_CODE_ENCRYPTION_ALGORITHM, cryptoKey, newHashValue).then(function(extendedPrivateKey) {
// Securely clear new hash value
newHashValue.fill(0);
// Get extended private key in correct format
extendedPrivateKey = new Uint8Array(extendedPrivateKey);
// Get new secret key from the extended private key
var newSecretKey = extendedPrivateKey.subarray(0, Crypto.SECP256K1_SECRET_KEY_LENGTH);
// Check if new secret key is a valid secret key or using BIP39 and new secret key is zero
if(Secp256k1Zkp.isValidSecretKey(newSecretKey) === true || (useBip39 === true && Common.arraysAreEqualTimingSafe(newSecretKey, Crypto.ZERO_SECRET_KEY) === true)) {
// Check if adding old secret key to the new secret key was successful
var updatedSecretKey = Secp256k1Zkp.secretKeyTweakAdd(newSecretKey, secretKey);
if(updatedSecretKey !== Secp256k1Zkp.OPERATION_FAILED) {
// Get updated chain code from the extended private key
var updatedChainCode = new Uint8Array(extendedPrivateKey.subarray(Crypto.SECP256K1_SECRET_KEY_LENGTH));
// Securely clear extended private key
extendedPrivateKey.fill(0);
// Resolve new extended private key
resolve([
// Updated secret key
updatedSecretKey,
// Updated chain code
updatedChainCode
]);
}
// Otherwise
else {
// Check if using BIP39
if(useBip39 === true) {
// Set next hash value candidate
var nextHashValueCandidate = Common.mergeArrays([
// One
new Uint8Array([1]),
// New chain code
extendedPrivateKey.subarray(Crypto.SECP256K1_SECRET_KEY_LENGTH)
]);
// Securely clear extended private key
extendedPrivateKey.fill(0);
// Return creating secret key and chain code
return createSecretKeyAndChainCode(nextHashValueCandidate).then(function(secretKeyAndChainCode) {
// Resolve secret key and chain code
resolve(secretKeyAndChainCode);
// Catch error
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Securely clear extended private key
extendedPrivateKey.fill(0);
// Reject error
reject("Performing secret key tweak add failed.");
}
}
}
// Otherwise
else {
// Check if using BIP39
if(useBip39 === true) {
// Set next hash value candidate
var nextHashValueCandidate = Common.mergeArrays([
// One
new Uint8Array([1]),
// New chain code
extendedPrivateKey.subarray(Crypto.SECP256K1_SECRET_KEY_LENGTH)
]);
// Securely clear extended private key
extendedPrivateKey.fill(0);
// Return creating secret key and chain code
return createSecretKeyAndChainCode(nextHashValueCandidate).then(function(secretKeyAndChainCode) {
// Resolve secret key and chain code
resolve(secretKeyAndChainCode);
// Catch error
}).catch(function(error) {
// Reject error
reject(error);
});
}
// Otherwise
else {
// Securely clear extended private key
extendedPrivateKey.fill(0);
// Reject error
reject("New secret key isn't a valid secret key or using BIP39 and new secret key isn't zero.");
}
}
// Catch errors
}).catch(function(error) {
// Securely clear new hash value
newHashValue.fill(0);
// Reject error
reject("Creating new extended private key failed.");
});
});
};
// Return creating secret key and chain code
return createSecretKeyAndChainCode(hashValue).then(function(secretKeyAndChainCode) {
// TODO Securely clear cryptoKey
// Resolve secret key and chain code
resolve(secretKeyAndChainCode);
// Catch errors
}).catch(function(error) {
// TODO Securely clear cryptoKey
// Reject error
reject(error);
});
// Catch errors
}).catch(function(error) {
// Reject error
reject("Creating crypto key failed.");
});
});
}
// Chain code length
static get CHAIN_CODE_LENGTH() {
// Return chain code length
return 32;
}
// Secret key index
static get SECRET_KEY_INDEX() {
// Return secret key index
return 0;
}
// Chain code index
static get CHAIN_CODE_INDEX() {
// Return chain code index
return Crypto.SECRET_KEY_INDEX + 1;
}
// Chain code encryption algorithm
static get CHAIN_CODE_ENCRYPTION_ALGORITHM() {
// Return chain code encryption algorithm
return "HMAC";
}
// Chain code digest algorithm
static get CHAIN_CODE_DIGEST_ALGORITHM() {
// Return chain code digest algorithm
return "SHA-512";
}
// Address key amount
static get ADDRESS_KEY_AMOUNT() {
// Return address key amount
return new BigNumber(713);
}
// Address key seed
static get ADDRESS_KEY_SEED() {
// Return address key seed
return "Grinbox_seed";
}
// Address key encryption algorithm
static get ADDRESS_KEY_ENCRYPTION_ALGORITHM() {
// Return address key encryption algorithm
return "HMAC";
}
// Address key digest algorithm
static get ADDRESS_KEY_DIGEST_ALGORITHM() {
// Return address key digest algorithm
return "SHA-512";
}
// AES algorithm
static get AES_ALGORITHM() {
// Return AES algorithm
return "AES-CBC";
}
// AES initialization vector size
static get AES_INITIALIZATION_VECTOR_SIZE() {
// Return AES initialization vector size
return 16;
}
}
// Main function
// Set global object's crypto
globalThis["Crypto"] = Crypto;