nel-neo-thinsdk
Version:
369 lines (335 loc) • 16.7 kB
text/typescript
module ThinNeo {
declare var scrypt: any;
var scrypt_loaded: boolean = false;
var CryptoJS = require('crypto-js');
var Buffer = require("buffer");
export class Helper {
public static GetPrivateKeyFromWIF(wif: string): Uint8Array {
if (wif == null) throw new Error("null wif");
var data = Neo.Cryptography.Base58.decode(wif);
//检查标志位
if (data.length != 38 || data[0] != 0x80 || data[33] != 0x01)
throw new Error("wif length or tag is error");
//取出检验字节
var sum = data.subarray(data.length - 4, data.length);
var realdata = data.subarray(0, data.length - 4);
//验证,对前34字节进行进行两次hash取前4个字节
var _checksum = Neo.Cryptography.Sha256.computeHash(realdata);
var checksum = new Uint8Array(Neo.Cryptography.Sha256.computeHash(_checksum));
var sumcalc = checksum.subarray(0, 4);
for (var i = 0; i < 4; i++) {
if (sum[i] != sumcalc[i])
throw new Error("the sum is not match.");
}
var privateKey = data.subarray(1, 1 + 32);
return privateKey;
}
public static GetWifFromPrivateKey(prikey: Uint8Array): string {
var data = new Uint8Array(38);
data[0] = 0x80;
data[33] = 0x01;
for (var i = 0; i < 32; i++) {
data[i + 1] = prikey[i];
}
var realdata = data.subarray(0, data.length - 4);
var _checksum = Neo.Cryptography.Sha256.computeHash(realdata);
var checksum = new Uint8Array(Neo.Cryptography.Sha256.computeHash(_checksum));
for (var i = 0; i < 4; i++) {
data[34 + i] = checksum[i];
}
var wif = Neo.Cryptography.Base58.encode(data);
return wif;
}
public static GetPublicKeyFromPrivateKey(privateKey: Uint8Array): Uint8Array {
var pkey = Neo.Cryptography.ECPoint.multiply(Neo.Cryptography.ECCurve.secp256r1.G, privateKey);
return pkey.encodePoint(true);
}
public static Hash160(data: Uint8Array): Uint8Array {
var hash1 = Neo.Cryptography.Sha256.computeHash(data);
var hash2 = Neo.Cryptography.RIPEMD160.computeHash(hash1);
return new Uint8Array(hash2);
}
public static GetAddressCheckScriptFromPublicKey(publicKey: Uint8Array): Uint8Array {
var script = new Uint8Array(publicKey.length + 2);
script[0] = publicKey.length;
for (var i = 0; i < publicKey.length; i++) {
script[i + 1] = publicKey[i];
};
script[script.length - 1] = 172;//CHECKSIG
return script;
}
public static GetPublicKeyScriptHashFromPublicKey(publicKey: Uint8Array): Uint8Array {
var script = Helper.GetAddressCheckScriptFromPublicKey(publicKey);
var scripthash = Neo.Cryptography.Sha256.computeHash(script);
scripthash = Neo.Cryptography.RIPEMD160.computeHash(scripthash);
return new Uint8Array(scripthash);
}
public static GetScriptHashFromScript(script: Uint8Array): Uint8Array {
var scripthash = Neo.Cryptography.Sha256.computeHash(script);
scripthash = Neo.Cryptography.RIPEMD160.computeHash(scripthash);
return new Uint8Array(scripthash);
}
public static GetAddressFromScriptHash(scripthash: Uint8Array): string {
var data = new Uint8Array(scripthash.length + 1);
data[0] = 0x17;
for (var i = 0; i < scripthash.length; i++) {
data[i + 1] = scripthash[i];
}
var hash = Neo.Cryptography.Sha256.computeHash(data);
hash = Neo.Cryptography.Sha256.computeHash(hash);
var hashu8 = new Uint8Array(hash, 0, 4);
var alldata = new Uint8Array(data.length + 4);
for (var i = 0; i < data.length; i++) {
alldata[i] = data[i];
}
for (var i = 0; i < 4; i++) {
alldata[data.length + i] = hashu8[i];
}
return Neo.Cryptography.Base58.encode(alldata);
}
public static GetAddressFromPublicKey(publicKey: Uint8Array): string {
var scripthash = Helper.GetPublicKeyScriptHashFromPublicKey(publicKey);
return Helper.GetAddressFromScriptHash(scripthash);
}
public static GetPublicKeyScriptHash_FromAddress(address: string): Uint8Array {
var array: Uint8Array = Neo.Cryptography.Base58.decode(address);
var salt = array.subarray(0, 1);
var hash = array.subarray(1, 1 + 20);
var check = array.subarray(21, 21 + 4);
var checkdata = array.subarray(0, 21);
var hashd = Neo.Cryptography.Sha256.computeHash(checkdata);
hashd = Neo.Cryptography.Sha256.computeHash(hashd);
var hashd = hashd.slice(0, 4);
var checked = new Uint8Array(hashd);
for (var i = 0; i < 4; i++) {
if (checked[i] != check[i]) {
throw new Error("the sum is not match.");
}
}
return hash.clone();
}
public static Sign(message: Uint8Array, privateKey: Uint8Array): Uint8Array {
var PublicKey = Neo.Cryptography.ECPoint.multiply(Neo.Cryptography.ECCurve.secp256r1.G, privateKey);
var pubkey = PublicKey.encodePoint(false).subarray(1, 64);
//var PublicKey = ThinNeo.Cryptography.ECC.ECCurve.Secp256r1.G * prikey;
//var pubkey = PublicKey.EncodePoint(false).Skip(1).ToArray();
var key = new Neo.Cryptography.ECDsaCryptoKey(PublicKey, privateKey);
var ecdsa = new Neo.Cryptography.ECDsa(key);
////using(var ecdsa = System.Security.Cryptography.ECDsa.Create(new System.Security.Cryptography.ECParameters
//{
// Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP256,
// D = prikey,
// Q = new System.Security.Cryptography.ECPoint
// {
// X = pubkey.Take(32).ToArray(),
// Y = pubkey.Skip(32).ToArray()
// }
//}))
{
//var hash = Neo.Cryptography.Sha256.computeHash(message);
return new Uint8Array(ecdsa.sign(message));
}
}
public static VerifySignature(message: Uint8Array, signature: Uint8Array, pubkey: Uint8Array) {
var PublicKey = Neo.Cryptography.ECPoint.decodePoint(pubkey, Neo.Cryptography.ECCurve.secp256r1);
var usepk = PublicKey.encodePoint(false).subarray(1, 64);
var key = new Neo.Cryptography.ECDsaCryptoKey(PublicKey);
var ecdsa = new Neo.Cryptography.ECDsa(key);
{
return ecdsa.verify(message, signature);
}
}
public static String2Bytes(str): Uint8Array {
var back = [];
var byteSize = 0;
for (var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i);
if (0x00 <= code && code <= 0x7f) {
byteSize += 1;
back.push(code);
} else if (0x80 <= code && code <= 0x7ff) {
byteSize += 2;
back.push((192 | (31 & (code >> 6))));
back.push((128 | (63 & code)))
} else if ((0x800 <= code && code <= 0xd7ff)
|| (0xe000 <= code && code <= 0xffff)) {
byteSize += 3;
back.push((224 | (15 & (code >> 12))));
back.push((128 | (63 & (code >> 6))));
back.push((128 | (63 & code)))
}
}
var uarr = new Uint8Array(back.length);
for (i = 0; i < back.length; i++) {
uarr[i] = back[i] & 0xff;
}
return uarr;
}
public static Bytes2String(_arr: Uint8Array) {
var UTF = '';
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2)
}
UTF += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1
} else {
UTF += String.fromCharCode(_arr[i])
}
}
return UTF;
}
public static Aes256Encrypt(src: string, key: string): string {
var srcs = CryptoJS.enc.Utf8.parse(src);
var keys = CryptoJS.enc.Utf8.parse(key);
var encryptedkey = CryptoJS.AES.encrypt(srcs, keys, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding
});
return encryptedkey.ciphertext.toString();
}
public static Aes256Encrypt_u8(src: Uint8Array, key: Uint8Array): Uint8Array {
var srcs = CryptoJS.enc.Utf8.parse("1234123412341234");
srcs.sigBytes = src.length;
srcs.words = new Array<number>(src.length / 4);
for (var i = 0; i < src.length / 4; i++) {
srcs.words[i] = src[i * 4 + 3] + src[i * 4 + 2] * 256 + src[i * 4 + 1] * 256 * 256 + src[i * 4 + 0] * 256 * 256 * 256;
}
var keys = CryptoJS.enc.Utf8.parse("1234123412341234");
keys.sigBytes = key.length;
keys.words = new Array<number>(key.length / 4);
for (var i = 0; i < key.length / 4; i++) {
keys.words[i] = key[i * 4 + 3] + key[i * 4 + 2] * 256 + key[i * 4 + 1] * 256 * 256 + key[i * 4 + 0] * 256 * 256 * 256;
}
var encryptedkey = CryptoJS.AES.encrypt(srcs, keys, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding
});
var str: string = encryptedkey.ciphertext.toString();
return str.hexToBytes();
}
public static Aes256Decrypt_u8(encryptedkey: Uint8Array, key: Uint8Array): Uint8Array {
var keys = CryptoJS.enc.Utf8.parse("1234123412341234");
keys.sigBytes = key.length;
keys.words = new Array<number>(key.length / 4);
for (var i = 0; i < key.length / 4; i++) {
keys.words[i] = key[i * 4 + 3] + key[i * 4 + 2] * 256 + key[i * 4 + 1] * 256 * 256 + key[i * 4 + 0] * 256 * 256 * 256;
}
var base64key = Base64.fromByteArray(encryptedkey);
var srcs = CryptoJS.AES.decrypt(base64key, keys, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding
});
var str: string = srcs.toString();
return str.hexToBytes();
}
public static GetNep2FromPrivateKey(prikey: Uint8Array, passphrase: string, n = 14, r = 8, p = 8, callback: (info: string, result: string) => void): void {
var pubkey = Helper.GetPublicKeyFromPrivateKey(prikey);
let addr = Helper.GetAddressFromPublicKey(pubkey);
var addresshash = Helper.GetAddrHash(addr);
scrypt(passphrase, addresshash, {
logN: 14,
r: r,
p: p,
dkLen: 64,
encoding: 'hex'
},
function (res:string) {
var u8dk = res.hexToBytes();
var derivedhalf1 = u8dk.subarray(0, 32);
var derivedhalf2 = u8dk.subarray(32, 64);
var u8xor = new Uint8Array(32);
for (var i = 0; i < 32; i++) {
u8xor[i] = prikey[i] ^ derivedhalf1[i];
}
var encryptedkey = Helper.Aes256Encrypt_u8(u8xor, derivedhalf2);
let buffer = new Uint8Array(39);
buffer[0] = 0x01;
buffer[1] = 0x42;
buffer[2] = 0xe0;
for (var i = 3; i < 3 + 4; i++) {
buffer[i] = addresshash[i - 3];
}
for (var i = 7; i < 32 + 7; i++) {
buffer[i] = encryptedkey[i - 7];
}
var b1 = Neo.Cryptography.Sha256.computeHash(buffer);
b1 = Neo.Cryptography.Sha256.computeHash(b1);
var u8hash = new Uint8Array(b1);
var outbuf = new Uint8Array(39 + 4);
for (var i = 0; i < 39; i++) {
outbuf[i] = buffer[i];
}
for (var i = 39; i < 39 + 4; i++) {
outbuf[i] = u8hash[i - 39];
}
var base58str = Neo.Cryptography.Base58.encode(outbuf);
callback("finish", base58str);
});
return;
}
public static GetPrivateKeyFromNep2(nep2: string, passphrase: string, n = 14, r = 8, p = 8, callback: (info: string, result: string | Uint8Array) => void) {
let data = Neo.Cryptography.Base58.decode(nep2);
if (data.length != 39 + 4) {
callback("error", "data.length error");
return;
}
if (data[0] != 0x01 || data[1] != 0x42 || data[2] != 0xe0) {
callback("error", "dataheader error");
return;
}
var hash = data.subarray(39, 39 + 4);
var buffer = data.subarray(0, 39);
var b1 = Neo.Cryptography.Sha256.computeHash(buffer);
b1 = Neo.Cryptography.Sha256.computeHash(b1);
var u8hash = new Uint8Array(b1);
for (var i = 0; i < 4; i++) {
if (u8hash[i] != hash[i]) {
callback("error", "data hash error");
return;
}
}
var addresshash = buffer.subarray(3, 3 + 4);
var encryptedkey = buffer.subarray(7, 7 + 32);
scrypt(passphrase, addresshash, {
logN: 14,
r: r,
p: p,
dkLen: 64,
encoding: 'hex'
},
function (res: string) {
var u8dk = res.hexToBytes() //new Uint8Array(res);
var derivedhalf1 = u8dk.subarray(0, 32);
var derivedhalf2 = u8dk.subarray(32, 64);
var u8xor = Helper.Aes256Decrypt_u8(encryptedkey, derivedhalf2);
var prikey = new Uint8Array(u8xor.length);
for (var i = 0; i < 32; i++) {
prikey[i] = u8xor[i] ^ derivedhalf1[i];
}
var pubkey = Helper.GetPublicKeyFromPrivateKey(prikey);
var address = Helper.GetAddressFromPublicKey(pubkey);
var addresshashgot = Helper.GetAddrHash(address);
for (var i = 0; i < 4; i++) {
if (addresshash[i] != addresshashgot[i]) {
callback("error", "nep2 hash not match.");
return;
}
}
callback("finish", prikey);
});
}
public static GetAddrHash(addr: string): any {
var buffer = new Buffer.Buffer(addr);
let strkey = Neo.Cryptography.Sha256.computeHash(buffer);
strkey = Neo.Cryptography.Sha256.computeHash(strkey);
var addresshash = new Uint8Array(strkey);
return addresshash.subarray(0, 4);
}
}
}