mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-20 06:55:08 -04:00
Added BIP32Derive, which uses bip32 from bitcoinjs. Modified a few more operations. Code compiles with 20.3.0
This commit is contained in:
parent
810c94803d
commit
f474ffaf72
17 changed files with 764 additions and 170 deletions
219
package-lock.json
generated
219
package-lock.json
generated
|
@ -12,12 +12,14 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astronautlabs/amf": "^0.0.6",
|
"@astronautlabs/amf": "^0.0.6",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
|
"@bitcoinerlab/secp256k1": "^1.0.5",
|
||||||
"@blu3r4y/lzma": "^2.3.3",
|
"@blu3r4y/lzma": "^2.3.3",
|
||||||
"argon2-browser": "^1.18.0",
|
"argon2-browser": "^1.18.0",
|
||||||
"arrive": "^2.4.1",
|
"arrive": "^2.4.1",
|
||||||
"avsc": "^5.7.7",
|
"avsc": "^5.7.7",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"bignumber.js": "^9.1.1",
|
"bignumber.js": "^9.1.1",
|
||||||
|
"bip32": "^4.0.0",
|
||||||
"blakejs": "^1.2.1",
|
"blakejs": "^1.2.1",
|
||||||
"bootstrap": "4.6.2",
|
"bootstrap": "4.6.2",
|
||||||
"bootstrap-colorpicker": "^3.4.0",
|
"bootstrap-colorpicker": "^3.4.0",
|
||||||
|
@ -1906,6 +1908,15 @@
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@bitcoinerlab/secp256k1": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-8gT+ukTCFN2rTxn4hD9Jq3k+UJwcprgYjfK/SQUSLgznXoIgsBnlPuARMkyyuEjycQK9VvnPiejKdszVTflh+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "^1.1.5",
|
||||||
|
"@noble/secp256k1": "^1.7.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@blu3r4y/lzma": {
|
"node_modules/@blu3r4y/lzma": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@blu3r4y/lzma/-/lzma-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@blu3r4y/lzma/-/lzma-2.3.3.tgz",
|
||||||
|
@ -2657,6 +2668,28 @@
|
||||||
"integrity": "sha512-GEBeGoXVmTYPtNC4Yq34vfgxf6mlFyEagxpsfH18Qe5BvctF2rprX+wI5dKBm9p5IqHo6ZOcXHCufOeP3cjuOw==",
|
"integrity": "sha512-GEBeGoXVmTYPtNC4Yq34vfgxf6mlFyEagxpsfH18Qe5BvctF2rprX+wI5dKBm9p5IqHo6ZOcXHCufOeP3cjuOw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@noble/secp256k1": {
|
||||||
|
"version": "1.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
|
||||||
|
"integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
|
@ -2749,6 +2782,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@scure/base": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@testim/chrome-version": {
|
"node_modules/@testim/chrome-version": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
|
||||||
|
@ -3851,6 +3895,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/base-x": {
|
||||||
|
"version": "3.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
|
||||||
|
"integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/base64-js": {
|
"node_modules/base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
@ -3931,6 +3983,20 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bip32": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "^1.2.0",
|
||||||
|
"@scure/base": "^1.1.1",
|
||||||
|
"typeforce": "^1.11.5",
|
||||||
|
"wif": "^2.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bl": {
|
"node_modules/bl": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
@ -4412,6 +4478,24 @@
|
||||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bs58": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
|
||||||
|
"dependencies": {
|
||||||
|
"base-x": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bs58check": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
|
||||||
|
"dependencies": {
|
||||||
|
"bs58": "^4.0.0",
|
||||||
|
"create-hash": "^1.1.0",
|
||||||
|
"safe-buffer": "^5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bson": {
|
"node_modules/bson": {
|
||||||
"version": "4.7.2",
|
"version": "4.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
|
||||||
|
@ -9458,9 +9542,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsonwebtoken/node_modules/semver": {
|
"node_modules/jsonwebtoken/node_modules/semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver"
|
"semver": "bin/semver"
|
||||||
}
|
}
|
||||||
|
@ -14444,9 +14528,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/protobufjs": {
|
"node_modules/protobufjs": {
|
||||||
"version": "7.2.3",
|
"version": "7.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz",
|
||||||
"integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==",
|
"integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@protobufjs/aspromise": "^1.1.2",
|
"@protobufjs/aspromise": "^1.1.2",
|
||||||
|
@ -15183,9 +15267,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
|
@ -16170,6 +16254,11 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typeforce": {
|
||||||
|
"version": "1.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
|
||||||
|
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||||
|
},
|
||||||
"node_modules/ua-parser-js": {
|
"node_modules/ua-parser-js": {
|
||||||
"version": "1.0.35",
|
"version": "1.0.35",
|
||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz",
|
||||||
|
@ -16962,6 +17051,14 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wif": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"bs58check": "<3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/winston": {
|
"node_modules/winston": {
|
||||||
"version": "2.4.7",
|
"version": "2.4.7",
|
||||||
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz",
|
||||||
|
@ -16998,9 +17095,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
@ -18520,6 +18617,15 @@
|
||||||
"to-fast-properties": "^2.0.0"
|
"to-fast-properties": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@bitcoinerlab/secp256k1": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@bitcoinerlab/secp256k1/-/secp256k1-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-8gT+ukTCFN2rTxn4hD9Jq3k+UJwcprgYjfK/SQUSLgznXoIgsBnlPuARMkyyuEjycQK9VvnPiejKdszVTflh+w==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "^1.1.5",
|
||||||
|
"@noble/secp256k1": "^1.7.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@blu3r4y/lzma": {
|
"@blu3r4y/lzma": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@blu3r4y/lzma/-/lzma-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@blu3r4y/lzma/-/lzma-2.3.3.tgz",
|
||||||
|
@ -19104,6 +19210,16 @@
|
||||||
"integrity": "sha512-GEBeGoXVmTYPtNC4Yq34vfgxf6mlFyEagxpsfH18Qe5BvctF2rprX+wI5dKBm9p5IqHo6ZOcXHCufOeP3cjuOw==",
|
"integrity": "sha512-GEBeGoXVmTYPtNC4Yq34vfgxf6mlFyEagxpsfH18Qe5BvctF2rprX+wI5dKBm9p5IqHo6ZOcXHCufOeP3cjuOw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="
|
||||||
|
},
|
||||||
|
"@noble/secp256k1": {
|
||||||
|
"version": "1.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
|
||||||
|
"integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw=="
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
|
@ -19187,6 +19303,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||||
},
|
},
|
||||||
|
"@scure/base": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="
|
||||||
|
},
|
||||||
"@testim/chrome-version": {
|
"@testim/chrome-version": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
|
||||||
|
@ -20145,6 +20266,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"base-x": {
|
||||||
|
"version": "3.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
|
||||||
|
"integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
@ -20201,6 +20330,17 @@
|
||||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bip32": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bip32/-/bip32-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-aOGy88DDlVUhspIXJN+dVEtclhIsfAUppD43V0j40cPTld3pv/0X/MlrZSZ6jowIaQQzFwP8M6rFU2z2mVYjDQ==",
|
||||||
|
"requires": {
|
||||||
|
"@noble/hashes": "^1.2.0",
|
||||||
|
"@scure/base": "^1.1.1",
|
||||||
|
"typeforce": "^1.11.5",
|
||||||
|
"wif": "^2.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"bl": {
|
"bl": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
@ -20583,6 +20723,24 @@
|
||||||
"update-browserslist-db": "^1.0.11"
|
"update-browserslist-db": "^1.0.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bs58": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
|
||||||
|
"requires": {
|
||||||
|
"base-x": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bs58check": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
|
||||||
|
"requires": {
|
||||||
|
"bs58": "^4.0.0",
|
||||||
|
"create-hash": "^1.1.0",
|
||||||
|
"safe-buffer": "^5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"bson": {
|
"bson": {
|
||||||
"version": "4.7.2",
|
"version": "4.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
|
||||||
|
@ -24397,9 +24555,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -28032,9 +28190,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"protobufjs": {
|
"protobufjs": {
|
||||||
"version": "7.2.3",
|
"version": "7.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz",
|
||||||
"integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==",
|
"integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@protobufjs/aspromise": "^1.1.2",
|
"@protobufjs/aspromise": "^1.1.2",
|
||||||
"@protobufjs/base64": "^1.1.2",
|
"@protobufjs/base64": "^1.1.2",
|
||||||
|
@ -28614,9 +28772,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
|
@ -29413,6 +29571,11 @@
|
||||||
"mime-types": "~2.1.24"
|
"mime-types": "~2.1.24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typeforce": {
|
||||||
|
"version": "1.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
|
||||||
|
"integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g=="
|
||||||
|
},
|
||||||
"ua-parser-js": {
|
"ua-parser-js": {
|
||||||
"version": "1.0.35",
|
"version": "1.0.35",
|
||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz",
|
||||||
|
@ -29997,6 +30160,14 @@
|
||||||
"string-width": "^4.0.0"
|
"string-width": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"wif": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==",
|
||||||
|
"requires": {
|
||||||
|
"bs58check": "<3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"winston": {
|
"winston": {
|
||||||
"version": "2.4.7",
|
"version": "2.4.7",
|
||||||
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz",
|
||||||
|
@ -30029,9 +30200,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"word-wrap": {
|
"word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
|
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="
|
||||||
},
|
},
|
||||||
"worker-loader": {
|
"worker-loader": {
|
||||||
"version": "3.0.8",
|
"version": "3.0.8",
|
||||||
|
|
|
@ -94,12 +94,14 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astronautlabs/amf": "^0.0.6",
|
"@astronautlabs/amf": "^0.0.6",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
|
"@bitcoinerlab/secp256k1": "^1.0.5",
|
||||||
"@blu3r4y/lzma": "^2.3.3",
|
"@blu3r4y/lzma": "^2.3.3",
|
||||||
"argon2-browser": "^1.18.0",
|
"argon2-browser": "^1.18.0",
|
||||||
"arrive": "^2.4.1",
|
"arrive": "^2.4.1",
|
||||||
"avsc": "^5.7.7",
|
"avsc": "^5.7.7",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"bignumber.js": "^9.1.1",
|
"bignumber.js": "^9.1.1",
|
||||||
|
"bip32": "^4.0.0",
|
||||||
"blakejs": "^1.2.1",
|
"blakejs": "^1.2.1",
|
||||||
"bootstrap": "4.6.2",
|
"bootstrap": "4.6.2",
|
||||||
"bootstrap-colorpicker": "^3.4.0",
|
"bootstrap-colorpicker": "^3.4.0",
|
||||||
|
|
|
@ -320,7 +320,9 @@
|
||||||
"Seedphrase To Seed",
|
"Seedphrase To Seed",
|
||||||
"Change Extended Key Version",
|
"Change Extended Key Version",
|
||||||
"Seed To Master Key",
|
"Seed To Master Key",
|
||||||
"Decrypt Keystore File"
|
"Decrypt Keystore File",
|
||||||
|
"BIP32Derive",
|
||||||
|
"Public Key To ETH Style Address"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
* Javascript code below taken from:
|
* Javascript code below taken from:
|
||||||
* https://github.com/geco/bech32-js/blob/master/bech32-js.js
|
* https://github.com/geco/bech32-js/blob/master/bech32-js.js
|
||||||
* Implements various segwit encoding / decoding functions.
|
* Implements various segwit encoding / decoding functions.
|
||||||
*
|
*
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 geco
|
* Copyright (c) 2019 geco
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -23,10 +23,10 @@
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
* copies or substantial portions of the Software.
|
* copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
|
|
@ -12,6 +12,126 @@ import {toHex} from "crypto-api/src/encoder/hex.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the length of the passed in input as one of the allowable lengths.
|
||||||
|
* @param {*} input
|
||||||
|
* @param {*} allowableLengths
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function validateLengths(input, allowableLengths) {
|
||||||
|
return allowableLengths.includes(input.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if input is a valid hex string, false otherwise.
|
||||||
|
* @param {*} input
|
||||||
|
*/
|
||||||
|
function isHex(input) {
|
||||||
|
const re = /^[0-9A-Fa-f]{2,}$/g;
|
||||||
|
return re.test(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if input could be interpreted as a byte string, false otherwise.
|
||||||
|
*/
|
||||||
|
function isValidBytes(input) {
|
||||||
|
for (let i=0; i < input.length; i ++) {
|
||||||
|
if (input.charCodeAt(i) > 255) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We validate a passed in input to see if it could be a valid private key.
|
||||||
|
* A valid private key is string of length 64 that is valid hex, or of length 32 that could be valid bytes.
|
||||||
|
* @param {*} input
|
||||||
|
*/
|
||||||
|
export function validatePrivateKey(input) {
|
||||||
|
const curInput = input.trim();
|
||||||
|
if (!validateLengths(curInput, [32, 64])) {
|
||||||
|
return "Invalid length. We want either 32 or 64 but we got: " + curInput.length;
|
||||||
|
}
|
||||||
|
if (curInput.length === 64 && !isHex(curInput)) {
|
||||||
|
return "We have a string of length 64, but not valid hex. Cannot be interpreted as a private key.";
|
||||||
|
}
|
||||||
|
if (curInput.length === 32 && !isValidBytes(curInput)) {
|
||||||
|
return "We have a string of length 32 but cannot cannot be interpreted as valid bytes.";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We validate a passed in input to see if it could be a valid public key.
|
||||||
|
* A valid public key (in bytes) is either:
|
||||||
|
* 65 bytes beginning with 04
|
||||||
|
* 33 bytes beginning with 02 or 03
|
||||||
|
* @param {*} input
|
||||||
|
*/
|
||||||
|
export function validatePublicKey(input) {
|
||||||
|
const curInput = input.trim();
|
||||||
|
if (!validateLengths(curInput, [33, 65, 66, 130])) {
|
||||||
|
return "Invalid length. We want either 33, 65 (if bytes) or 66, 130 (if hex) but we got: " + curInput.length;
|
||||||
|
}
|
||||||
|
if (isHex(curInput)) {
|
||||||
|
if (!validateLengths(curInput, [66, 130])) {
|
||||||
|
return "We have a hex string, but its length is wrong. We want 66, 130 but we got: " + curInput.length;
|
||||||
|
}
|
||||||
|
if (curInput.length === 66 && (curInput.slice(0, 2) !== "02" && curInput.slice(0, 2) !== "03")) {
|
||||||
|
return "We have a valid hex string, of reasonable length, (66) but doesn't start with the right value. Correct values are 02, or 03 but we have: " + curInput.slice(0, 2);
|
||||||
|
}
|
||||||
|
if (curInput.length === 130 && curInput.slice(0, 2) !== "04") {
|
||||||
|
return "We have a valid hex string of reasonable length, (130) but doesn't start with the right value. Correct values are 04 but we have: " + curInput.slice(0, 2);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (isValidBytes(curInput)) {
|
||||||
|
if (!validateLengths(curInput, [33, 65])) {
|
||||||
|
return "We have a byte string, but its length is wrong. We want 33 or 65 but we got: " + curInput.length;
|
||||||
|
}
|
||||||
|
if (curInput.length === 33 && toHex(curInput[0]) !== "02" && toHex(curInput[0]) !== "03") {
|
||||||
|
return "We have a valid byte string, of reasonable length, (33) but doesn't start with the right value. Correct values are 02, or 03 but we have: " + toHex(curInput[0]) ;
|
||||||
|
}
|
||||||
|
if (curInput.length === 65 && toHex(curInput[0]) !== "04") {
|
||||||
|
return "We have a valid byte string, of reasonable length, (65) but doesn't start with the right value. Correct value is 04 but we have: " + toHex(curInput[0]);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We make sure the input is a valid hex string, regardless of if its hex or bytes.
|
||||||
|
* If not valid bytes or hex, we throw TypeError.
|
||||||
|
* @param {*} input
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function makeSureIsHex(input) {
|
||||||
|
if (!(isValidBytes(input)) && !(isHex(input))) {
|
||||||
|
throw TypeError("Input: " + input + " is not valid bytes or hex.");
|
||||||
|
}
|
||||||
|
if (isValidBytes(input) && !isHex(input)) {
|
||||||
|
return toHex(input);
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We make sure the input is valid bytes, regardless of if its hex or bytes.
|
||||||
|
* If not valid bytes or hex, we throw TypeError.
|
||||||
|
* @param {*} input
|
||||||
|
*/
|
||||||
|
export function makeSureIsBytes(input) {
|
||||||
|
if (!(isValidBytes(input)) && !(isHex(input))) {
|
||||||
|
throw TypeError("Input: " + input + " is not valid bytes or hex.");
|
||||||
|
}
|
||||||
|
if (isHex(input)) {
|
||||||
|
return fromArrayBuffer(Utils.convertToByteArray(input, "hex"));
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
// ################################################ BEGIN HELPER HASH FUNCTIONS #################################################
|
// ################################################ BEGIN HELPER HASH FUNCTIONS #################################################
|
||||||
|
|
||||||
// SHA256(SHA256(input))
|
// SHA256(SHA256(input))
|
||||||
|
@ -212,6 +332,35 @@ export function deserializeExtendedKeyFunc (input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverse lookup for version bytes
|
||||||
|
const versionString = {
|
||||||
|
"043587cf": "tpub",
|
||||||
|
"04358394": "tprv",
|
||||||
|
"044a5262": "upub",
|
||||||
|
"044a4e28": "uprv",
|
||||||
|
"045f1cf6": "vpub",
|
||||||
|
"045f18bc": "vprv",
|
||||||
|
"024289ef": "Upub",
|
||||||
|
"024285b5": "Uprv",
|
||||||
|
"02575483": "Vpub",
|
||||||
|
"02575048": "Vprv",
|
||||||
|
"0488b21e": "xpub",
|
||||||
|
"0488ade4": "xprv",
|
||||||
|
"049d7cb2": "ypub",
|
||||||
|
"049d7878": "yprv",
|
||||||
|
"04b24746": "zpub",
|
||||||
|
"04b2430c": "zprv",
|
||||||
|
"02aa7ed3": "Zpub",
|
||||||
|
"02aa7a99": "Zprv",
|
||||||
|
"0295b43f": "Ypub",
|
||||||
|
"0295b005": "Yprv",
|
||||||
|
"019da462": "Ltub",
|
||||||
|
"019d9cfe": "Ltpv",
|
||||||
|
"01b26ef6": "Mtub",
|
||||||
|
"01b26792": "Mtpv",
|
||||||
|
"0436f6e1": "ttub",
|
||||||
|
"0436ef7d": "ttpv"
|
||||||
|
};
|
||||||
|
|
||||||
// Version byte dictionary.
|
// Version byte dictionary.
|
||||||
const versionBytes = {
|
const versionBytes = {
|
||||||
|
@ -253,6 +402,16 @@ export function getExtendedKeyVersion(input) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse lookup for version string. We take in bytes, output string.
|
||||||
|
* @param {*} input
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getExtendedKeyString(input) {
|
||||||
|
return versionString[input];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We serialize the extended key based off of the passed in data.
|
* We serialize the extended key based off of the passed in data.
|
||||||
* We assume that the i value should be interpreted as a Uint32 LE.
|
* We assume that the i value should be interpreted as a Uint32 LE.
|
||||||
|
@ -296,6 +455,12 @@ const versionByteInfo = {
|
||||||
"P2SH": "C4",
|
"P2SH": "C4",
|
||||||
"WIF": "EF",
|
"WIF": "EF",
|
||||||
"hrp": "tb"
|
"hrp": "tb"
|
||||||
|
},
|
||||||
|
"LTC": {
|
||||||
|
"hrp": "ltc",
|
||||||
|
"P2PKH": "30",
|
||||||
|
"P2SH": "32",
|
||||||
|
"WIF": "B0"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
93
src/core/operations/BIP32Derive.mjs
Normal file
93
src/core/operations/BIP32Derive.mjs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* @author dgoldenberg [virtualcurrency@mitre.org]
|
||||||
|
* @copyright Crown Copyright 2023
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
// import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import { b58DoubleSHAChecksum} from "../lib/Bitcoin.mjs";
|
||||||
|
import { BIP32Factory} from "bip32";
|
||||||
|
import ecc from "@bitcoinerlab/secp256k1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanity checks a derivation path.
|
||||||
|
* @param {*} input
|
||||||
|
*/
|
||||||
|
function verifyDerivationPath(input) {
|
||||||
|
const splitResults = input.split("/");
|
||||||
|
let startIndex = 0;
|
||||||
|
// We skip the first index if its m, as that's common.
|
||||||
|
if (splitResults[0] === "m") {
|
||||||
|
startIndex = 1;
|
||||||
|
}
|
||||||
|
for (let i =startIndex; i < splitResults.length; i++) {
|
||||||
|
const re = /^[0-9]{1,}[']{0,1}$/g;
|
||||||
|
if (!re.test(splitResults[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BIP32Derive operation
|
||||||
|
*/
|
||||||
|
class BIP32Derive extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BIP32Derive constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "BIP32Derive";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Takes in an extended key, performs BIP32 key derivation on the extended key, and returns the result as an extended key.";
|
||||||
|
this.infoURL = "https://en.bitcoin.it/wiki/BIP_0032";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
"name": "Derivation Path",
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.checks = [
|
||||||
|
{
|
||||||
|
"pattern": "^(X|x|Y|y|Z|z|L|l|T|t)[pub|prv|tbv|tub][A-HJ-NP-Za-km-z1-9]{2,}$",
|
||||||
|
"flags": "",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
// We check if input is blank.
|
||||||
|
// If its blank or just whitespace, we don't need to bother dealing with it.
|
||||||
|
if (input.trim().length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
input = input.trim();
|
||||||
|
if (!verifyDerivationPath(args[0])) {
|
||||||
|
return "Invalid derivation path: " + args[0] + "\n";
|
||||||
|
}
|
||||||
|
const xkeyRe = /^(X|x|Y|y|Z|z|L|l|T|t)[pub|prv|tbv|tub][A-HJ-NP-Za-km-z1-9]{2,}$/g;
|
||||||
|
if (!b58DoubleSHAChecksum(input) || !xkeyRe.test(input)) {
|
||||||
|
return "Possibly invalid Extended Key: " + input + "\n";
|
||||||
|
}
|
||||||
|
const bip32 = BIP32Factory(ecc);
|
||||||
|
const node = bip32.fromBase58(input);
|
||||||
|
const child = node.derivePath(args[0]);
|
||||||
|
return child.toBase58();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BIP32Derive;
|
|
@ -7,9 +7,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import {toHex} from "../lib/Hex.mjs";
|
|
||||||
import ec from "elliptic";
|
import ec from "elliptic";
|
||||||
|
import { validatePrivateKey, makeSureIsHex} from "../lib/Bitcoin.mjs";
|
||||||
|
// import { toHex } from "crypto-api/src/encoder/hex.mjs";
|
||||||
|
|
||||||
|
// const curves = ["secp256k1", "ed25519", "curve25519", "p521", "p384", "p256", "p224", "p192"];
|
||||||
/**
|
/**
|
||||||
* Class that takes in a private key, and returns the public key, either in compressed or uncompressed form(s).
|
* Class that takes in a private key, and returns the public key, either in compressed or uncompressed form(s).
|
||||||
*/
|
*/
|
||||||
|
@ -56,24 +58,15 @@ class PrivateECKeyToPublic extends Operation {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
input = input.trim();
|
input = input.trim();
|
||||||
const re = /^[0-9A-Fa-f]{2,}$/g;
|
|
||||||
if (!(input.length === 64 && re.test(input)) && !(input.length === 32)) {
|
|
||||||
return "Must pass a hex string of length 64, or a byte string of length 32. Got length " + input.length;
|
|
||||||
}
|
|
||||||
// If we have bytes, we need to turn the bytes to hex.
|
|
||||||
if (input.length !== undefined && input.length === 32) {
|
|
||||||
const buf = new Uint8Array(new ArrayBuffer(32));
|
|
||||||
|
|
||||||
for (let i= 0; i < 32; i ++) {
|
const privKeyCheck = validatePrivateKey(input);
|
||||||
if (input.charCodeAt(i) > 255) {
|
|
||||||
return "Cannot interpret this 32 character string as bytes.";
|
if (privKeyCheck.trim().length !== 0) {
|
||||||
}
|
return "Error with the input as private key. Error is:\n\t" + privKeyCheck;
|
||||||
buf[i] = input.charCodeAt(i);
|
|
||||||
}
|
|
||||||
input = toHex(buf, "", 2, "", 0);
|
|
||||||
}
|
}
|
||||||
|
const processedInput = makeSureIsHex(input);
|
||||||
const ecContext = ec.ec("secp256k1");
|
const ecContext = ec.ec("secp256k1");
|
||||||
const key = ecContext.keyFromPrivate(input);
|
const key = ecContext.keyFromPrivate(processedInput);
|
||||||
const pubkey = key.getPublic(args[0], "hex");
|
const pubkey = key.getPublic(args[0], "hex");
|
||||||
|
|
||||||
return pubkey;
|
return pubkey;
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import { base58Encode, getWIFVersionByte, doubleSHA} from "../lib/Bitcoin.mjs";
|
import { base58Encode, getWIFVersionByte, doubleSHA, validatePrivateKey, makeSureIsHex} from "../lib/Bitcoin.mjs";
|
||||||
import { fromArrayBuffer } from "crypto-api/src/encoder/array-buffer.mjs";
|
import { fromArrayBuffer } from "crypto-api/src/encoder/array-buffer.mjs";
|
||||||
import {toHex} from "crypto-api/src/encoder/hex.mjs";
|
import {toHex} from "crypto-api/src/encoder/hex.mjs";
|
||||||
import {toHex as toHexOther} from "../lib/Hex.mjs";
|
// import {toHex as toHexOther} from "../lib/Hex.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,26 +65,13 @@ class PrivateKeyToWIF extends Operation {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
input = input.trim();
|
input = input.trim();
|
||||||
// We check to see if the input is hex or not.
|
const privateKeyCheck = validatePrivateKey(input);
|
||||||
// If it is not, we convert it back to hex
|
if (privateKeyCheck.trim().length !== 0) {
|
||||||
const re = /[0-9A-Fa-f]{2,}/g;
|
return "Error parsing private key. Error is:\n\t" + privateKeyCheck;
|
||||||
if (!(input.length === 64 && re.test(input)) && !(input.length === 32)) {
|
|
||||||
return "Must pass a hex string of length 64, or a byte string of length 32. Got length: " + input.length;
|
|
||||||
}
|
}
|
||||||
if (input.length === 32) {
|
const processedKey = makeSureIsHex(input);
|
||||||
const buf = new Uint8Array(new ArrayBuffer(32));
|
|
||||||
|
|
||||||
for (let i= 0; i < 32; i ++) {
|
|
||||||
if (input.charCodeAt(i) > 255) {
|
|
||||||
return "Cannot interpret this 32 character string as bytes.";
|
|
||||||
}
|
|
||||||
buf[i] = input.charCodeAt(i);
|
|
||||||
}
|
|
||||||
input = toHexOther(buf, "", 2, "", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionByte = getWIFVersionByte(args[0]);
|
const versionByte = getWIFVersionByte(args[0]);
|
||||||
let extendedPrivateKey = versionByte + input;
|
let extendedPrivateKey = versionByte + processedKey;
|
||||||
if (args[1]) {
|
if (args[1]) {
|
||||||
extendedPrivateKey += "01";
|
extendedPrivateKey += "01";
|
||||||
}
|
}
|
||||||
|
|
87
src/core/operations/PublicKeyToETHStyleAddress.mjs
Normal file
87
src/core/operations/PublicKeyToETHStyleAddress.mjs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/**
|
||||||
|
* @author dgoldenberg [virtualcurrency@mitre.org]
|
||||||
|
* @copyright Crown Copyright 2023
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import { makeSureIsBytes, validatePublicKey} from "../lib/Bitcoin.mjs";
|
||||||
|
import JSSHA3 from "js-sha3";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import ec from "elliptic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns a public key into an ETH address.
|
||||||
|
* @param {*} input Input, a public key in hex or bytes.
|
||||||
|
*/
|
||||||
|
function pubKeyToETHAddress(input) {
|
||||||
|
// Ethereum addresses require uncompressed public keys.
|
||||||
|
// We convert if the public key is compressed.
|
||||||
|
let curKey = makeSureIsBytes(input);
|
||||||
|
if (curKey[0] !== 0x04 || curKey.length !== 65) {
|
||||||
|
const ecContext = ec.ec("secp256k1");
|
||||||
|
const thisKey = ecContext.keyFromPublic(curKey);
|
||||||
|
curKey = thisKey.getPublic(false, "hex");
|
||||||
|
}
|
||||||
|
const algo = JSSHA3.keccak256;
|
||||||
|
// We need to redo the hex-> bytes transformation here because Javascript is silly.
|
||||||
|
// sometimes what is desired is an array of ints.
|
||||||
|
// Other times a string
|
||||||
|
// Here, the Keccak algorithm seems to want an array of ints. (sigh)
|
||||||
|
const result = algo(Utils.convertToByteArray(curKey, "hex").slice(1,));
|
||||||
|
return "0x" + result.slice(-40);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PublicKeyToETHStyleAddress operation
|
||||||
|
*/
|
||||||
|
class PublicKeyToETHStyleAddress extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PublicKeyToETHStyleAddress constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Public Key To ETH Style Address";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Converts a public key (compressed or uncompressed) to an Ethereum style address.";
|
||||||
|
this.infoURL = "https://www.freecodecamp.org/news/how-to-create-an-ethereum-wallet-address-from-a-private-key-ae72b0eee27b/";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [];
|
||||||
|
this.checks = [
|
||||||
|
{
|
||||||
|
pattern: "^0[3|2][a-fA-F0-9]{64}$",
|
||||||
|
flags: "",
|
||||||
|
args: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "^04[a-fA-F0-9]{128}$",
|
||||||
|
flags: "",
|
||||||
|
args: []
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
// We check if input is blank.
|
||||||
|
// If its blank or just whitespace, we don't need to bother dealing with it.
|
||||||
|
if (input.trim().length === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (validatePublicKey(input) !== "") {
|
||||||
|
return validatePublicKey(input);
|
||||||
|
}
|
||||||
|
return pubKeyToETHAddress(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PublicKeyToETHStyleAddress;
|
|
@ -9,11 +9,11 @@
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import { fromArrayBuffer } from "crypto-api/src/encoder/array-buffer.mjs";
|
import { fromArrayBuffer } from "crypto-api/src/encoder/array-buffer.mjs";
|
||||||
import {toHex} from "crypto-api/src/encoder/hex.mjs";
|
import {toHex} from "crypto-api/src/encoder/hex.mjs";
|
||||||
import { base58Encode, getP2PKHVersionByte, getP2SHVersionByte, hash160Func, doubleSHA, getHumanReadablePart} from "../lib/Bitcoin.mjs";
|
import { base58Encode, getP2PKHVersionByte, getP2SHVersionByte, hash160Func, doubleSHA, getHumanReadablePart, makeSureIsBytes, validatePublicKey} from "../lib/Bitcoin.mjs";
|
||||||
import {encodeProgramToSegwit} from "../lib/Bech32.mjs";
|
import {encodeProgramToSegwit} from "../lib/Bech32.mjs";
|
||||||
import JSSHA3 from "js-sha3";
|
|
||||||
import Utils from "../Utils.mjs";
|
import Utils from "../Utils.mjs";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Public Key to a P2PKH Address of the given type.
|
* Converts a Public Key to a P2PKH Address of the given type.
|
||||||
*/
|
*/
|
||||||
|
@ -27,19 +27,19 @@ class PublicKeyToP2PKHAddress extends Operation {
|
||||||
|
|
||||||
this.name = "Public Key To Cryptocurrency Address";
|
this.name = "Public Key To Cryptocurrency Address";
|
||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Turns a public key into a cryptocurrency address.";
|
this.description = "Turns a public key into a cryptocurrency address. Can select P2PKH, P2SH-P2WPKH and P2WPKH addresses for Bitcoin and Testnet.";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
"name": "Currency Type",
|
"name": "Currency Type",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["BTC", "Testnet", "Ethereum"]
|
"value": ["BTC", "Testnet", "LTC"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Address Type",
|
"name": "Address Type",
|
||||||
"type": "option",
|
"type": "option",
|
||||||
"value": ["P2PKH (V1 BTC Addresses)", "P2SH-P2PWPKH (Segwit Compatible)", "Segwit (P2WPKH)"]
|
"value": ["P2PKH (V1 BTC Addresses)", "P2SH-P2PWPKH (Segwit Compatible V3 Addresses)", "Segwit (P2WPKH bc1 Addresses)"]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
this.checks = [
|
this.checks = [
|
||||||
|
@ -48,11 +48,6 @@ class PublicKeyToP2PKHAddress extends Operation {
|
||||||
flags: "",
|
flags: "",
|
||||||
args: ["BTC", "P2PKH (V1 BTC Addresses)"]
|
args: ["BTC", "P2PKH (V1 BTC Addresses)"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
pattern: "^04[a-fA-F0-9]{128}$",
|
|
||||||
flags: "",
|
|
||||||
args: ["Ethereum", "P2PKH (V1 BTC Addresses)"]
|
|
||||||
}
|
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -68,75 +63,39 @@ class PublicKeyToP2PKHAddress extends Operation {
|
||||||
if (input.trim().length === 0) {
|
if (input.trim().length === 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
// We check to see if the input is hex or not.
|
if (validatePublicKey(input) !== "") {
|
||||||
// If it is, we convert back to bytes.
|
return validatePublicKey(input);
|
||||||
const re = /([0-9A-Fa-f]{2,})/g;
|
|
||||||
let inputIsHex = false;
|
|
||||||
let curInput = input;
|
|
||||||
if (re.test(input)) {
|
|
||||||
inputIsHex = true;
|
|
||||||
}
|
|
||||||
if (inputIsHex) {
|
|
||||||
curInput = fromArrayBuffer(Utils.convertToByteArray(input, "hex"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We sanity check the input
|
// We hash the input
|
||||||
const startByte = toHex(curInput[0]);
|
const curInput = makeSureIsBytes(input);
|
||||||
if (curInput.length !== 33 && curInput.length !== 65) {
|
const hash160 = toHex(hash160Func(curInput));
|
||||||
return "Input is wrong length. Should be either 33 or 65 bytes, but is: " + curInput.length;
|
// We do segwit addresses first.
|
||||||
}
|
if (args[1] === "Segwit (P2WPKH bc1 Addresses)") {
|
||||||
if (curInput.length === 33 && startByte !== "03" && startByte !== "02") {
|
const redeemScript = hash160;
|
||||||
return "Input is 33 bytes, but begins with invalid byte: " + startByte;
|
const hrp = getHumanReadablePart(args[0]);
|
||||||
}
|
if (hrp !== "") {
|
||||||
|
|
||||||
if (curInput.length === 65 && startByte !== "04") {
|
|
||||||
return "Input is 65 bytes, but begins with invalid byte: " + startByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args[0] === "Ethereum") {
|
|
||||||
// Ethereum addresses require uncompressed public keys.
|
|
||||||
if (startByte !== "04" || curInput.length !== 65) {
|
|
||||||
return "Ethereum addresses require uncompressed public keys.";
|
|
||||||
}
|
|
||||||
const algo = JSSHA3.keccak256;
|
|
||||||
// We need to redo the hex-> bytes transformation here because Javascript is silly.
|
|
||||||
// sometimes what is desired is an array of ints.
|
|
||||||
// Other times a string
|
|
||||||
// Here, the Keccak algorithm seems to want an array of ints. (sigh)
|
|
||||||
let result;
|
|
||||||
if (inputIsHex) {
|
|
||||||
result = algo(Utils.convertToByteArray(input, "hex").slice(1,));
|
|
||||||
} else {
|
|
||||||
result = algo(Utils.convertToByteArray(toHex(input), "hex").slice(1,));
|
|
||||||
}
|
|
||||||
return "0x" + result.slice(-40);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// We hash the input
|
|
||||||
const hash160 = toHex(hash160Func(curInput));
|
|
||||||
// We do segwit addresses first.
|
|
||||||
if (args[1] === "Segwit (P2WPKH)") {
|
|
||||||
const redeemScript = hash160;
|
|
||||||
const hrp = getHumanReadablePart(args[0]);
|
|
||||||
return encodeProgramToSegwit(hrp, 0, Utils.convertToByteArray(redeemScript, "hex"));
|
return encodeProgramToSegwit(hrp, 0, Utils.convertToByteArray(redeemScript, "hex"));
|
||||||
}
|
|
||||||
// It its not segwit, we create the redeemScript either for P2PKH or P2SH-P2WPKH addresses.
|
|
||||||
const versionByte = "P2PKH (V1 BTC Addresses)" === args[1] ? getP2PKHVersionByte(args[0]) : getP2SHVersionByte(args[0]);
|
|
||||||
// If its a P2SH-P2WPKH address, we have to prepend some extra bytes and hash again. Either way we prepend the version byte.
|
|
||||||
let hashRedeemedScript;
|
|
||||||
if (args[1] === "P2SH-P2PWPKH (Segwit Compatible)") {
|
|
||||||
const redeemScript = "0014" + hash160;
|
|
||||||
hashRedeemedScript = versionByte + toHex(hash160Func(fromArrayBuffer(Utils.convertToByteArray(redeemScript, "hex"))));
|
|
||||||
} else {
|
} else {
|
||||||
hashRedeemedScript = versionByte + hash160;
|
return args[0] + " does not support Segwit Addresses.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// We calculate the checksum, convert to Base58 and then we're done!
|
|
||||||
const checksumHash = toHex(doubleSHA(fromArrayBuffer(Utils.convertToByteArray(hashRedeemedScript, "hex"))));
|
|
||||||
const finalString = hashRedeemedScript + checksumHash.slice(0, 8);
|
|
||||||
const address = base58Encode(Utils.convertToByteArray(finalString, "hex"));
|
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
|
// It its not segwit, we create the redeemScript either for P2PKH or P2SH-P2WPKH addresses.
|
||||||
|
const versionByte = "P2PKH (V1 BTC Addresses)" === args[1] ? getP2PKHVersionByte(args[0]) : getP2SHVersionByte(args[0]);
|
||||||
|
// If its a P2SH-P2WPKH address, we have to prepend some extra bytes and hash again. Either way we prepend the version byte.
|
||||||
|
let hashRedeemedScript;
|
||||||
|
if (args[1] === "P2SH-P2PWPKH (Segwit Compatible V3 Addresses)") {
|
||||||
|
const redeemScript = "0014" + hash160;
|
||||||
|
hashRedeemedScript = versionByte + toHex(hash160Func(fromArrayBuffer(Utils.convertToByteArray(redeemScript, "hex"))));
|
||||||
|
} else {
|
||||||
|
hashRedeemedScript = versionByte + hash160;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We calculate the checksum, convert to Base58 and then we're done!
|
||||||
|
const checksumHash = toHex(doubleSHA(fromArrayBuffer(Utils.convertToByteArray(hashRedeemedScript, "hex"))));
|
||||||
|
const finalString = hashRedeemedScript + checksumHash.slice(0, 8);
|
||||||
|
const address = base58Encode(Utils.convertToByteArray(finalString, "hex"));
|
||||||
|
return address;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ import "./tests/DecryptKeyStoreFile.mjs";
|
||||||
import "./tests/WIFToPrivateKey.mjs";
|
import "./tests/WIFToPrivateKey.mjs";
|
||||||
import "./tests/SeedphraseToSeed.mjs";
|
import "./tests/SeedphraseToSeed.mjs";
|
||||||
import "./tests/DeserializeExtendedKey.mjs";
|
import "./tests/DeserializeExtendedKey.mjs";
|
||||||
|
import "./tests/PublicKeyToETHStyleAddress.mjs";
|
||||||
import "./tests/GetAllCasings.mjs";
|
import "./tests/GetAllCasings.mjs";
|
||||||
import "./tests/SIGABA.mjs";
|
import "./tests/SIGABA.mjs";
|
||||||
import "./tests/ELFInfo.mjs";
|
import "./tests/ELFInfo.mjs";
|
||||||
|
|
|
@ -34,8 +34,8 @@ TestRegister.addTests([
|
||||||
"args": [false]
|
"args": [false]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To ETH Style Address",
|
||||||
"args": ["Ethereum", "P2PKH (V1 BTC Addresses)"]
|
"args": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "Private EC Key to Public (Wrong Length)",
|
name: "Private EC Key to Public (Wrong Length)",
|
||||||
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
||||||
expectedOutput: "Must pass a hex string of length 64, or a byte string of length 32. Got length 66",
|
expectedOutput: "Error with the input as private key. Error is:\n\tInvalid length. We want either 32 or 64 but we got: 66",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Private EC Key to Public Key",
|
"op": "Private EC Key to Public Key",
|
||||||
|
@ -61,7 +61,7 @@ TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "Private EC Key to Public (From Bytes Uncompressed Wrong Length)",
|
name: "Private EC Key to Public (From Bytes Uncompressed Wrong Length)",
|
||||||
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
||||||
expectedOutput: "Must pass a hex string of length 64, or a byte string of length 32. Got length 33",
|
expectedOutput: "Error with the input as private key. Error is:\n\tInvalid length. We want either 32 or 64 but we got: 33",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "From Hex",
|
"op": "From Hex",
|
||||||
|
|
|
@ -61,7 +61,7 @@ TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "Private Key To WIF (BTC, Compressed, Wrong Number of Bytes)",
|
name: "Private Key To WIF (BTC, Compressed, Wrong Number of Bytes)",
|
||||||
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
||||||
expectedOutput: "Must pass a hex string of length 64, or a byte string of length 32. Got length: 66",
|
expectedOutput: "Error parsing private key. Error is:\n\tInvalid length. We want either 32 or 64 but we got: 66",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "To WIF Format",
|
"op": "To WIF Format",
|
||||||
|
@ -72,7 +72,7 @@ TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "Private Key To WIF (BTC, Compressed, Wrong Number of Bytes)",
|
name: "Private Key To WIF (BTC, Compressed, Wrong Number of Bytes)",
|
||||||
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
input: "5E2A8FDE9F861056607208F512287CFBD634E124044EE23EBF7289E8E7B3822E08",
|
||||||
expectedOutput: "Must pass a hex string of length 64, or a byte string of length 32. Got length: 33",
|
expectedOutput: "Error parsing private key. Error is:\n\tInvalid length. We want either 32 or 64 but we got: 33",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "From Hex",
|
"op": "From Hex",
|
||||||
|
|
110
tests/operations/tests/PublicKeyToETHStyleAddress.mjs
Normal file
110
tests/operations/tests/PublicKeyToETHStyleAddress.mjs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/**
|
||||||
|
* Public Key to ETH Style Address Cryptocurrency Address tests.
|
||||||
|
*
|
||||||
|
* @author dgoldenberg [virtualcurrency@mitre.org]
|
||||||
|
* @copyright MITRE 2023
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Public Key To ETH Style Address",
|
||||||
|
input: "04d26bcecd763bdf6bdb89ba929d2485429fbda73bae723d525ef55554ef45350582085bd24055079f6deebad5b6af612c14587c6862391d330484afe750fbf144",
|
||||||
|
expectedOutput: "0x63e8b85679d29235791a0f558d6485c7ed51c9e6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key To ETH Style Address 2",
|
||||||
|
input: "047d3e5107b46421c3ddf7292fcbe1f5805952279926c325d119f6ddfed1e5e7ea9a9f5dceadc57b897cb286479450b66a6422f8f270bcd2a61ab4eea800911956",
|
||||||
|
expectedOutput: "0x099f75d5bc069026531394d5c6d6c37a41158d31",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key to ETH Style Address: Compressed Key",
|
||||||
|
input: "027d3e5107b46421c3ddf7292fcbe1f5805952279926c325d119f6ddfed1e5e7ea",
|
||||||
|
expectedOutput: "0x099f75d5bc069026531394d5c6d6c37a41158d31",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key to ETH Style Address: Compressed Key 2",
|
||||||
|
input: "039d491d3f5a2a79b422b76b8115b175b38e42c6103b1a84c88fb6221fe9072bbe",
|
||||||
|
expectedOutput: "0x345029d286159d516ca1169edf0a80ff6c855ac0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key to ETH Style Address: Compressed Key (From Hex)",
|
||||||
|
input: "027d3e5107b46421c3ddf7292fcbe1f5805952279926c325d119f6ddfed1e5e7ea",
|
||||||
|
expectedOutput: "0x099f75d5bc069026531394d5c6d6c37a41158d31",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Auto"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key to ETH Style Address: Compressed Key 2 (From Hex)",
|
||||||
|
input: "039d491d3f5a2a79b422b76b8115b175b38e42c6103b1a84c88fb6221fe9072bbe",
|
||||||
|
expectedOutput: "0x345029d286159d516ca1169edf0a80ff6c855ac0",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Auto"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key To ETH Style Address (From Hex)",
|
||||||
|
input: "04d26bcecd763bdf6bdb89ba929d2485429fbda73bae723d525ef55554ef45350582085bd24055079f6deebad5b6af612c14587c6862391d330484afe750fbf144",
|
||||||
|
expectedOutput: "0x63e8b85679d29235791a0f558d6485c7ed51c9e6",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Auto"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Public Key To ETH Style Address",
|
||||||
|
"args": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
]);
|
|
@ -32,6 +32,17 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key To Address: P2PKH LTC",
|
||||||
|
input: "037b39f764a10f31bfd47038738ca27bffeefce1fe4ccbfb9343fcb69d9363b27b",
|
||||||
|
expectedOutput: "LPTR2TBuF8vbwWaJdNeCAQemW4SC7q7zJP",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
|
"args": ["LTC", "P2PKH (V1 BTC Addresses)"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Public Key To Address: P2PKH (Long)",
|
name: "Public Key To Address: P2PKH (Long)",
|
||||||
input: "04219A19E157B5FEDDF7EBDD3C7A58D7AB4F6565E84226691B6A5F80BBCE8E0100B49D6AB503CA4B701626E941EB8D2460F154992D7AD4EC671CF1CFB8C1DE8164",
|
input: "04219A19E157B5FEDDF7EBDD3C7A58D7AB4F6565E84226691B6A5F80BBCE8E0100B49D6AB503CA4B701626E941EB8D2460F154992D7AD4EC671CF1CFB8C1DE8164",
|
||||||
|
@ -50,7 +61,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["BTC", "P2SH-P2PWPKH (Segwit Compatible)"]
|
"args": ["BTC", "P2SH-P2PWPKH (Segwit Compatible V3 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -61,7 +72,18 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["BTC", "P2SH-P2PWPKH (Segwit Compatible)"]
|
"args": ["BTC", "P2SH-P2PWPKH (Segwit Compatible V3 Addresses)"]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Public Key To Address: P2SH-P2WPKH LTC",
|
||||||
|
input: "02f442a169ca36702bbcbb268319295bece8fe1cbc6ca095b2669d13ef56c759de",
|
||||||
|
expectedOutput: "MMwYiJmkxDKqiP2WWAHMMgkeRt2nLxGqih",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
|
"args": ["LTC", "P2SH-P2PWPKH (Segwit Compatible V3 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -72,7 +94,7 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["BTC", "Segwit (P2WPKH)"]
|
"args": ["BTC", "Segwit (P2WPKH bc1 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -83,21 +105,20 @@ TestRegister.addTests([
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["BTC", "Segwit (P2WPKH)"]
|
"args": ["BTC", "Segwit (P2WPKH bc1 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Public Key To Address: (ETH)",
|
name: "Public Key To Address: P2WPKH LTC",
|
||||||
input: "04d26bcecd763bdf6bdb89ba929d2485429fbda73bae723d525ef55554ef45350582085bd24055079f6deebad5b6af612c14587c6862391d330484afe750fbf144",
|
input: "026a532c31184b94edf540ad60c3cc208342be4f51cc764a373a420731dd198a59",
|
||||||
expectedOutput: "0x63e8b85679d29235791a0f558d6485c7ed51c9e6",
|
expectedOutput: "ltc1qj587punda8h0r4m83k794xseqlnl3az4ktu2zp",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["Ethereum", "Segwit (P2WPKH)"]
|
"args": ["LTC", "Segwit (P2WPKH bc1 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Public Key To Address: (Testnet)",
|
name: "Public Key To Address: (Testnet)",
|
||||||
|
@ -114,29 +135,29 @@ TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "Public Key To Address: P2WPKH (Wrong Length)",
|
name: "Public Key To Address: P2WPKH (Wrong Length)",
|
||||||
input: "03bc32bdc5dc96c9fb56e2481fefd321ebe9e17a807bbb337dea1df5e68b1f075642",
|
input: "03bc32bdc5dc96c9fb56e2481fefd321ebe9e17a807bbb337dea1df5e68b1f075642",
|
||||||
expectedOutput: "Input is wrong length. Should be either 33 or 65 bytes, but is: 34",
|
expectedOutput: "Invalid length. We want either 33, 65 (if bytes) or 66, 130 (if hex) but we got: 68",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["BTC", "Segwit (P2WPKH)"]
|
"args": ["BTC", "Segwit (P2WPKH bc1 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Public Key To Address: P2WPKH (Wrong Start)",
|
name: "Public Key To Address: P2WPKH (Wrong Start)",
|
||||||
input: "05bc32bdc5dc96c9fb56e2481fefd321ebe9e17a807bbb337dea1df5e68b1f0756",
|
input: "05bc32bdc5dc96c9fb56e2481fefd321ebe9e17a807bbb337dea1df5e68b1f0756",
|
||||||
expectedOutput: "Input is 33 bytes, but begins with invalid byte: 05",
|
expectedOutput: "We have a valid hex string, of reasonable length, (66) but doesn't start with the right value. Correct values are 02, or 03 but we have: 05",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
"args": ["BTC", "Segwit (P2WPKH)"]
|
"args": ["BTC", "Segwit (P2WPKH bc1 Addresses)"]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Public Key To Address: P2PKH (Long With Error)",
|
name: "Public Key To Address: P2PKH (Long With Error)",
|
||||||
input: "06219A19E157B5FEDDF7EBDD3C7A58D7AB4F6565E84226691B6A5F80BBCE8E0100B49D6AB503CA4B701626E941EB8D2460F154992D7AD4EC671CF1CFB8C1DE8164",
|
input: "06219A19E157B5FEDDF7EBDD3C7A58D7AB4F6565E84226691B6A5F80BBCE8E0100B49D6AB503CA4B701626E941EB8D2460F154992D7AD4EC671CF1CFB8C1DE8164",
|
||||||
expectedOutput: "Input is 65 bytes, but begins with invalid byte: 06",
|
expectedOutput: "We have a valid hex string of reasonable length, (130) but doesn't start with the right value. Correct values are 04 but we have: 06",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
"op": "Public Key To Cryptocurrency Address",
|
||||||
|
@ -159,16 +180,4 @@ TestRegister.addTests([
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Public Key To Address: (ETH Compressed Key)",
|
|
||||||
input: "03ebf60a619da2fbc6239089ca0a93878ea53baa3d22188cacad4033b103237ae9",
|
|
||||||
expectedOutput: "Ethereum addresses require uncompressed public keys.",
|
|
||||||
recipeConfig: [
|
|
||||||
{
|
|
||||||
"op": "Public Key To Cryptocurrency Address",
|
|
||||||
"args": ["Ethereum", "Segwit (P2WPKH)"]
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -21,6 +21,21 @@ TestRegister.addTests([
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Seed To Master Private Key (xprv) From Hex",
|
||||||
|
input: "c766f48d3729a16249b5d0171c678d458d31454b2bb7791b61169b5541a130719714ebd41f22a2515246d013e9a4e978aee48dd5140b73a540108d58008c4aa9",
|
||||||
|
expectedOutput: "xprv9s21ZrQH143K2nwujwREGif1wyBwt5Jh9BdFVSgSeYdrUp1qPxKsHrmnpJ8xKpKPDvXJMmBRpsZ3X64MeafyURs8Xoj53kGu7hb48Yg7unj",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "From Hex",
|
||||||
|
"args": ["Auto"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op": "Seed To Master Key",
|
||||||
|
"args": ["xprv"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Seed To Master Private Key (tprv)",
|
name: "Seed To Master Private Key (tprv)",
|
||||||
input: "c766f48d3729a16249b5d0171c678d458d31454b2bb7791b61169b5541a130719714ebd41f22a2515246d013e9a4e978aee48dd5140b73a540108d58008c4aa9",
|
input: "c766f48d3729a16249b5d0171c678d458d31454b2bb7791b61169b5541a130719714ebd41f22a2515246d013e9a4e978aee48dd5140b73a540108d58008c4aa9",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue