import * as jsrsasign from 'jsrsasign' ; import * as CryptoJS from 'crypto-js' ; import crc64 from './crc64' ; import * as Long from 'long' ; const crypto = require ( 'isomorphic-webcrypto' ) ; const { SHA256 , SHA512 } = CryptoJS ; type LibWordArray = any ; export type THashInput = Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | DataView | ArrayBuffer ; const curveName = 'secp256r1' ; const signAlg = 'SHA256withECDSA' ; const addressLength = 20 ; const remainder = ( x , y ) => { const a = parseInt ( x . slice ( 0 , x . length - 10 ) , 10 ) % y ; const b = parseInt ( x . slice ( 10 ) , 10 ) % y ; return ( a * ( 10 ** 10 % y ) + b ) % y ; } ; export const checksum = ( digits ) => { let first = 0 ; let second = 0 ; let value = 0 ; for ( let i = 0 ; i < digits . length ; i ++ ) { const digit = digits [ i ] ; if ( i & 1 ) { first += digit ; } else { second += digit ; } } value = ( second + 3 * first ) % 10 ; if ( 0 < value ) { value = 10 - value ; } return value ; } ; export const privateToPublic = ( privateKey ) => { const curveParams = jsrsasign . crypto . ECParameterDB . getByName ( curveName ) ; const curveG = curveParams . G ; const charLen = curveParams . keylen / 4 ; const privateBig = new jsrsasign . BigInteger ( privateKey , 16 ) ; const publicBig = curveG . multiply ( privateBig ) ; const valueX = publicBig . getX ( ) . toBigInteger ( ) ; const valueY = publicBig . getY ( ) . toBigInteger ( ) ; const xHex = ( '0000000000' + valueX . toString ( 16 ) ) . slice ( - charLen ) ; const yHex = ( '0000000000' + valueY . toString ( 16 ) ) . slice ( - charLen ) ; return xHex + yHex ; } ; export const sign = ( data , privateKey ) : string => { const signature = new jsrsasign . crypto . Signature ( { alg : signAlg } ) ; signature . init ( { d : privateKey , curve : curveName } ) ; signature . updateHex ( data ) ; return signature . sign ( ) ; } ; export const address = ( publicKey ) => { const keyDigest = SHA256 ( CryptoJS . enc . Hex . parse ( publicKey ) ) ; const hashDigest = SHA512 ( keyDigest as any as LibWordArray ) . toString ( ) ; const bytes = [ ] ; for ( let i = 0 ; i < hashDigest . length ; i += 2 ) { bytes . push ( parseInt ( hashDigest [ i ] + hashDigest [ i + 1 ] , 16 ) ) ; } const crc = crc64 ( bytes ) ; const value = '0' . repeat ( addressLength - crc . length ) + crc ; const crcDigits = value . split ( '' ) . map ( l => parseInt ( l , 10 ) ) ; const addrChecksum = checksum ( crcDigits . slice ( 0 , - 1 ) ) ; const crcLong = Long . fromString ( crc ) ; return crcLong . sub ( remainder ( crc , 10 ) ) . add ( addrChecksum ) . toString ( ) ; } ; export const addressString = ( addr ) => { const num = Long . fromString ( addr , true , 10 ) . toString ( ) ; let val = '0' . repeat ( 20 - num . length ) + num ; let ret = '' ; for ( let i = 0 ; i < 4 ; i ++ ) { ret += val . slice ( i * 4 , ( i + 1 ) * 4 ) + '-' ; } ret += val . slice ( 16 ) ; return ret ; } ; export const Sha256 = async ( data ) => { return await crypto . subtle . digest ( { name : 'SHA-256' } , data ) ; } ;