crypto.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import { ADDRESS_PREFIX, ADDRESS_PREFIX_BYTE, ADDRESS_SIZE } from './constants.js';
  2. import { base64EncodeToString, base64DecodeFromString, hexStr2byteArray } from './code.js';
  3. import { encode58, decode58 } from './base58.js';
  4. import { byte2hexStr, byteArray2hexStr } from './bytes.js';
  5. import { keccak256, sha256, recoverAddress, arrayify, Signature } from './ethersUtils.js';
  6. import { secp256k1 as secp } from 'ethereum-cryptography/secp256k1';
  7. function normalizePrivateKeyBytes(priKeyBytes) {
  8. return hexStr2byteArray(byteArray2hexStr(priKeyBytes).padStart(64, '0'));
  9. }
  10. export function getBase58CheckAddress(addressBytes) {
  11. const hash0 = SHA256(addressBytes);
  12. const hash1 = SHA256(hash0);
  13. let checkSum = hash1.slice(0, 4);
  14. checkSum = addressBytes.concat(checkSum);
  15. return encode58(checkSum);
  16. }
  17. export function decodeBase58Address(base58Sting) {
  18. if (typeof base58Sting != 'string')
  19. return false;
  20. if (base58Sting.length <= 4)
  21. return false;
  22. let address = decode58(base58Sting);
  23. if (base58Sting.length <= 4)
  24. return false;
  25. const len = address.length;
  26. const offset = len - 4;
  27. const checkSum = address.slice(offset);
  28. address = address.slice(0, offset);
  29. const hash0 = SHA256(address);
  30. const hash1 = SHA256(hash0);
  31. const checkSum1 = hash1.slice(0, 4);
  32. if (checkSum[0] == checkSum1[0] &&
  33. checkSum[1] == checkSum1[1] &&
  34. checkSum[2] == checkSum1[2] &&
  35. checkSum[3] == checkSum1[3]) {
  36. return address;
  37. }
  38. throw new Error('Invalid address provided');
  39. }
  40. // @TODO transaction type should be determined.
  41. export function signTransaction(priKeyBytes, transaction) {
  42. if (typeof priKeyBytes === 'string')
  43. priKeyBytes = hexStr2byteArray(priKeyBytes);
  44. const txID = transaction.txID;
  45. const signature = ECKeySign(hexStr2byteArray(txID), priKeyBytes);
  46. if (Array.isArray(transaction.signature)) {
  47. if (!transaction.signature.includes(signature))
  48. transaction.signature.push(signature);
  49. }
  50. else
  51. transaction.signature = [signature];
  52. return transaction;
  53. }
  54. export function ecRecover(signedData, signature) {
  55. signedData = '0x' + signedData.replace(/^0x/, '');
  56. signature = '0x' + signature.replace(/^0x/, '');
  57. const recovered = recoverAddress(arrayify(signedData), Signature.from(signature));
  58. const tronAddress = ADDRESS_PREFIX + recovered.substring(2);
  59. return tronAddress;
  60. }
  61. export function arrayToBase64String(a) {
  62. return btoa(String.fromCharCode(...a));
  63. }
  64. export function signBytes(privateKey, contents) {
  65. if (typeof privateKey === 'string')
  66. privateKey = hexStr2byteArray(privateKey);
  67. const hashBytes = SHA256(contents);
  68. const signBytes = ECKeySign(hashBytes, privateKey);
  69. return signBytes;
  70. }
  71. export function getRowBytesFromTransactionBase64(base64Data) {
  72. const bytesDecode = base64DecodeFromString(base64Data);
  73. // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  74. // @ts-ignore
  75. const transaction = globalThis.proto.protocol.Transaction.deserializeBinary(bytesDecode);
  76. const raw = transaction.getRawData();
  77. return raw.serializeBinary();
  78. }
  79. export function genPriKey() {
  80. const priKey = secp.utils.randomPrivateKey();
  81. let priKeyHex = byteArray2hexStr(priKey);
  82. priKeyHex = priKeyHex.padStart(64, '0');
  83. return hexStr2byteArray(priKeyHex);
  84. }
  85. export function computeAddress(pubBytes) {
  86. if (pubBytes.length === 65)
  87. pubBytes = pubBytes.slice(1);
  88. const hash = keccak256(new Uint8Array(pubBytes)).toString().substring(2);
  89. const addressHex = ADDRESS_PREFIX + hash.substring(24);
  90. return hexStr2byteArray(addressHex);
  91. }
  92. export function getAddressFromPriKey(priKeyBytes) {
  93. const pubBytes = getPubKeyFromPriKey(priKeyBytes);
  94. return computeAddress(pubBytes);
  95. }
  96. export function decode58Check(addressStr) {
  97. const decodeCheck = decode58(addressStr);
  98. if (decodeCheck.length <= 4)
  99. return false;
  100. const decodeData = decodeCheck.slice(0, decodeCheck.length - 4);
  101. const hash0 = SHA256(decodeData);
  102. const hash1 = SHA256(hash0);
  103. if (hash1[0] === decodeCheck[decodeData.length] &&
  104. hash1[1] === decodeCheck[decodeData.length + 1] &&
  105. hash1[2] === decodeCheck[decodeData.length + 2] &&
  106. hash1[3] === decodeCheck[decodeData.length + 3]) {
  107. return decodeData;
  108. }
  109. return false;
  110. }
  111. export function isAddressValid(base58Str) {
  112. if (typeof base58Str !== 'string')
  113. return false;
  114. if (base58Str.length !== ADDRESS_SIZE)
  115. return false;
  116. let address = decode58(base58Str);
  117. if (address.length !== 25)
  118. return false;
  119. if (address[0] !== ADDRESS_PREFIX_BYTE)
  120. return false;
  121. const checkSum = address.slice(21);
  122. address = address.slice(0, 21);
  123. const hash0 = SHA256(address);
  124. const hash1 = SHA256(hash0);
  125. const checkSum1 = hash1.slice(0, 4);
  126. if (checkSum[0] == checkSum1[0] &&
  127. checkSum[1] == checkSum1[1] &&
  128. checkSum[2] == checkSum1[2] &&
  129. checkSum[3] == checkSum1[3]) {
  130. return true;
  131. }
  132. return false;
  133. }
  134. export function getBase58CheckAddressFromPriKeyBase64String(priKeyBase64String) {
  135. const priKeyBytes = base64DecodeFromString(priKeyBase64String);
  136. const pubBytes = getPubKeyFromPriKey(priKeyBytes);
  137. const addressBytes = computeAddress(pubBytes);
  138. return getBase58CheckAddress(addressBytes);
  139. }
  140. export function getHexStrAddressFromPriKeyBase64String(priKeyBase64String) {
  141. const priKeyBytes = base64DecodeFromString(priKeyBase64String);
  142. const pubBytes = getPubKeyFromPriKey(priKeyBytes);
  143. const addressBytes = computeAddress(pubBytes);
  144. const addressHex = byteArray2hexStr(addressBytes);
  145. return addressHex;
  146. }
  147. export function getAddressFromPriKeyBase64String(priKeyBase64String) {
  148. const priKeyBytes = base64DecodeFromString(priKeyBase64String);
  149. const pubBytes = getPubKeyFromPriKey(priKeyBytes);
  150. const addressBytes = computeAddress(pubBytes);
  151. const addressBase64 = base64EncodeToString(addressBytes);
  152. return addressBase64;
  153. }
  154. export function getPubKeyFromPriKey(priKeyBytes) {
  155. const pubkey = secp.ProjectivePoint.fromPrivateKey(new Uint8Array(normalizePrivateKeyBytes(priKeyBytes)));
  156. const x = pubkey.x;
  157. const y = pubkey.y;
  158. const xHex = x.toString(16).padStart(64, '0');
  159. const yHex = y.toString(16).padStart(64, '0');
  160. const pubkeyHex = `04${xHex}${yHex}`;
  161. const pubkeyBytes = hexStr2byteArray(pubkeyHex);
  162. return pubkeyBytes;
  163. }
  164. export function ECKeySign(hashBytes, priKeyBytes) {
  165. const signature = secp.sign(byteArray2hexStr(hashBytes), byteArray2hexStr(priKeyBytes));
  166. const r = signature.r.toString(16);
  167. const s = signature.s.toString(16);
  168. const v = signature.recovery + 27;
  169. return r.padStart(64, '0') + s.padStart(64, '0') + byte2hexStr(v);
  170. }
  171. export function SHA256(msgBytes) {
  172. const msgHex = byteArray2hexStr(msgBytes);
  173. const hashHex = sha256('0x' + msgHex).replace(/^0x/, '');
  174. return hexStr2byteArray(hashHex);
  175. }
  176. export function passwordToAddress(password) {
  177. const com_priKeyBytes = base64DecodeFromString(password);
  178. const com_addressBytes = getAddressFromPriKey(com_priKeyBytes);
  179. return getBase58CheckAddress(com_addressBytes);
  180. }
  181. export function pkToAddress(privateKey, strict = false) {
  182. const com_priKeyBytes = hexStr2byteArray(privateKey, strict);
  183. const com_addressBytes = getAddressFromPriKey(com_priKeyBytes);
  184. return getBase58CheckAddress(com_addressBytes);
  185. }
  186. export function sha3(string, prefix = true) {
  187. return (prefix ? '0x' : '') + keccak256(Buffer.from(string, 'utf-8')).toString().substring(2);
  188. }
  189. //# sourceMappingURL=crypto.js.map