diff --git a/dist/esbuild/main.js b/dist/esbuild/main.js index 64537ab..1438f47 100644 --- a/dist/esbuild/main.js +++ b/dist/esbuild/main.js @@ -5481,4 +5481,4 @@ YAHOO.lang = { //# sourceURL=webpack://JSEncrypt/./lib/lib/jsrsasign/yahoo.js?`)},"./lib/version.json":module=>{eval(`module.exports = {"version":"3.2.1"}; -//# sourceURL=webpack://JSEncrypt/./lib/version.json?`)}},__webpack_module_cache__={};function __webpack_require__(t){var n=__webpack_module_cache__[t];if(n!==void 0)return n.exports;var e=__webpack_module_cache__[t]={exports:{}};return __webpack_modules__[t](e,e.exports,__webpack_require__),e.exports}__webpack_require__.d=(t,n)=>{for(var e in n)__webpack_require__.o(n,e)&&!__webpack_require__.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},__webpack_require__.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),__webpack_require__.r=t=>{typeof Symbol!="undefined"&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./lib/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})()})},{}]},{},[1])(1)})});var cn;try{window.crypto,cn=c("bls-eth-wasm/browser")}catch(t){cn=c("bls-eth-wasm")}var p=cn;var ln=class{constructor(){this.operatorsCount=3}setOperatorsCount(n){this.operatorsCount=n}},xn=t=>!(t<4||t>13||t%3!=1),Gn=new ln;var P=class extends Error{constructor(e,r){super(r);this.data=e}},k=class extends Error{constructor(e,r){super(r);this.data=e}},M=class extends Error{constructor(n){super(n)}},E=class extends Error{constructor(n){super(n)}},L=class extends Error{constructor(e,r){super(r);this.data=e}},S=class extends Error{constructor(e,r){super(r);this.data=e}},x=class extends Error{constructor(e,r){super(r);this.data=e}};var un=class extends Error{constructor(e,r){super(r);this.operators=e}},hn=class extends Error{constructor(e,r){super(r);this.operator=e}},gn=class{constructor(){this.shares=[]}static get DEFAULT_THRESHOLD_NUMBER(){return 3}create(n,e){return h(this,null,function*(){if(!n.startsWith("0x"))throw new L(n,"The private key must be provided in the 0x format.");if(e.map(a=>{if(!Number.isInteger(a))throw new hn(a,`Operator must be integer. Got: ${a}`)}),!xn(e.length))throw new un(e,"Invalid operators amount. Enter an 3f+1 compatible amount of operator ids.");let r=[],i=[];p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381)),this.privateKey=p.deserializeHexStrToSecretKey(n.replace("0x","")),this.publicKey=this.privateKey.getPublicKey(),r.push(this.privateKey),i.push(this.publicKey);let s=(e.length-1)/3;for(let a=1;a`0${(e&255).toString(16)}`.slice(-2)).join("")}},H=fn;var _n;try{window.crypto,_n=c("jsencrypt").JSEncrypt||c("jsencrypt")}catch(t){_n=Rn()}var q=_n;var bn=c("js-base64");var W=class extends Error{constructor(e,r){super(r);this.operator=e}},F=class extends Error{constructor(e,r){super(r);this.operator=e}},G=class extends Error{constructor(e,r,i){super(i);this.listOne=e,this.listTwo=r}},z=class extends Error{constructor(e,r){super(r);this.operator=e}};var Y=t=>{t=t.trim();let n="-----BEGIN RSA PUBLIC KEY-----",e="-----END RSA PUBLIC KEY-----",r=new q({}),i="";try{let s="";if(t.startsWith(n))s=t;else{if(t.length<98)throw Error("The length of the operator public key must be at least 98 characters.");try{s=(0,bn.decode)(t).trim()}catch(o){throw new Error("Failed to decode the operator public key. Ensure it's correctly base64 encoded.")}if(!s.startsWith(n))throw new Error(`Operator public key does not start with '${n}'`)}if(!s.endsWith(e))throw new Error(`Operator public key does not end with '${e}'`);try{let o=s.slice(n.length,t.length-e.length).trim();i=(0,bn.decode)(o)}catch(o){throw new Error("Failed to decode the RSA public key. Ensure it's correctly base64 encoded.")}try{r.setPublicKey(i)}catch(o){throw new Error("Invalid operator key format, make sure the operator exists in the network.")}}catch(s){throw new z({rsa:i,base64:t},s.message)}return!0};var R=class{constructor(n,e){this.operatorPublicKeys=[...n],this.shares=e}encrypt(){let n=[];for(let[e,r]of this.operatorPublicKeys.entries()){Y(r);let i=new q({});i.setPublicKey(r);let s=i.encrypt(this.shares[e].privateKey),o={operatorPublicKey:r,privateKey:s,publicKey:this.shares[e].publicKey};n.push(o)}return n}};var _=c("class-validator");var Z=c("class-validator");var I=class{validate(n){return Y(n)}defaultMessage(){return"Invalid operator public key"}};I=u([(0,Z.ValidatorConstraint)({name:"operatorKey",async:!1})],I);function Tn(t){return function(n,e){(0,Z.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:I})}}var T=class{constructor(n){this.id=n.id,this.operatorKey=n.operatorKey,this.validate()}validate(){(0,_.validateSync)(this)}};u([(0,_.IsNotEmpty)({message:"The operator id is null"}),(0,_.IsDefined)({message:"The operator id is undefined"}),(0,_.IsInt)({message:"The operator id must be an integer"})],T.prototype,"id",2),u([(0,_.IsNotEmpty)({message:"The operator public key is null"}),(0,_.IsDefined)({message:"The operator public key is undefined"}),(0,_.IsString)({message:"The operator public key must be a string"}),Tn()],T.prototype,"operatorKey",2);var v=t=>t.sort((n,e)=>+n.id-+e.id).map(n=>{if(!n.id||!n.operatorKey)throw new G(t,t,"Mismatch amount of operator ids and operator keys.");return new T(n)});var $=class{extractKeys(n,e){return h(this,null,function*(){let r=yield new H(n).getPrivateKey(e);return p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381)),{privateKey:`0x${r}`,publicKey:`0x${p.deserializeHexStrToSecretKey(r).getPublicKey().serializeToHexStr()}`}})}createThreshold(n,e){return h(this,null,function*(){let r=v(e);return this.threshold=yield new C().create(n,r.map(i=>i.id)),this.threshold})}encryptShares(n,e){return h(this,null,function*(){let i=v(n).map(s=>Buffer.from(s.operatorKey,"base64").toString());return new R(i,e).encrypt()})}buildShares(n,e){return h(this,null,function*(){let r=yield this.createThreshold(n,e);return this.encryptShares(e,r.shares)})}getThreshold(){return this.threshold}};$.SHARES_FORMAT_ABI="abi";var j=y(c("ethers")),En=y(c("semver"));var An=y(c("web3")),In=y(c("ethers")),mn=y(c("ethereumjs-util"));var Q=class extends Error{constructor(e,r){super(r);this.publicKey=e}},X=class extends Error{constructor(e,r){super(r);this.data=e}};var D=new An.default;var nn=t=>{let n=new Uint8Array(t.map(e=>[...In.utils.arrayify(e)]).flat());return Buffer.from(n)},Dn=(t,n)=>h(void 0,null,function*(){p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381));let e=p.deserializeHexStrToSecretKey(n.replace("0x","")),r=mn.keccak256(Buffer.from(t));return`0x${e.sign(new Uint8Array(r)).serializeToHexStr()}`}),On=(t,n,e)=>h(void 0,null,function*(){p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381));let r=p.deserializeHexStrToPublicKey(e.replace("0x","")),i=p.deserializeHexStrToSignature(n.replace("0x","")),s=mn.keccak256(Buffer.from(t));if(!r.verify(i,new Uint8Array(s)))throw new X(n,"Single shares signature is invalid")}),wn=t=>h(void 0,null,function*(){return p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381)),`0x${p.deserializeHexStrToSecretKey(t.replace("0x","")).getPublicKey().serializeToHexStr()}`});var en={name:"ssv-keys",version:"1.0.4",description:"Tool for splitting a validator key into a predefined threshold of shares via Shamir-Secret-Sharing (SSS), and encrypt them with a set of operator keys.",author:"SSV.Network",repository:"https://github.com/bloxapp/ssv-keys",license:"MIT",keywords:["ssv","ssv.network","keystore","shares"],main:"./dist/tsc/src/main.js",types:"./dist/tsc/src/main.d.ts",bin:{"ssv-keys":"./dist/tsc/src/cli.js"},engines:{node:">=10"},scripts:{"dev:cli":"ts-node src/cli.ts","dev:icli":"ts-node src/cli-interactive.ts",icli:"node ./dist/tsc/src/cli-interactive.js",cli:"node ./dist/tsc/src/cli.js",lint:"eslint src/ --ext .js,.jsx,.ts,.tsx",test:"jest",clean:"rm -rf dist build package","ts-node":"ts-node",docs:"typedoc",build:"tsc -p tsconfig.json","build-all":"yarn clean && yarn build && yarn esbuild",esbuild:"node ./esbuild.js","pre-commit":"yarn test && yarn lint && yarn build-all","package-linux":"pkg dist/tsc/src/cli-interactive.js --targets node14-linux-x64 --output bin/linux/ssv-keys-lin --compress GZip","package-macos":"pkg dist/tsc/src/cli-interactive.js --targets node14-macos-x64 --output bin/macos/ssv-keys-mac --compress GZip","package-win":"pkg dist/tsc/src/cli-interactive.js --targets node14-win-x64 --output bin/win/ssv-keys.exe --compress GZip","package-all":"yarn package-linux && yarn package-macos && yarn package-win"},devDependencies:{"@testing-library/jest-dom":"^5.16.4","@types/argparse":"^2.0.10","@types/atob":"^2.1.2","@types/btoa":"^1.2.3","@types/jest":"^26.0.24","@types/node":"^15.14.9","@types/prompts":"^2.0.14","@types/semver":"^7.5.0","@typescript-eslint/eslint-plugin":"^4.33.0","@typescript-eslint/parser":"^4.33.0",esbuild:"^0.14.38","esbuild-node-externals":"^1.4.1",eslint:"^7.32.0",husky:"^7.0.4",jest:"^26.6.3","jest-environment-jsdom":"^26.6.2","jest-environment-node":"^26.6.2","jest-environment-uint8array":"^1.0.0","jest-watch-typeahead":"0.6.5",jsdom:"^16.5.3","jsdom-global":"^3.0.2",pkg:"^5.7.0","ts-jest":"^26.5.6","ts-node":"^10.9.1",typedoc:"^0.22.15",typescript:"^4.6.4"},dependencies:{"@types/figlet":"^1.5.4","@types/underscore":"^1.11.4","@types/yargs":"^17.0.12",argparse:"^2.0.1",assert:"^2.0.0",atob:"^2.1.2","bls-eth-wasm":"^1.0.4","bls-signatures":"^0.2.5",btoa:"^1.2.1","class-validator":"^0.13.2",colors:"^1.4.0",crypto:"^1.0.1","eth2-keystore-js":"^1.0.8","ethereumjs-util":"^7.1.5","ethereumjs-wallet":"^1.0.1",ethers:"^5.7.2",events:"^3.3.0",figlet:"^1.5.2","js-base64":"^3.7.2",jsencrypt:"3.2.1",minimist:"^1.2.6",moment:"^2.29.3","node-jsencrypt":"^1.0.0",prompts:"https://github.com/meshin-blox/prompts.git","scrypt-js":"^3.0.1",semver:"^7.5.1",stream:"^0.0.2",underscore:"^1.13.4",web3:"1.7.3",yargs:"^17.5.1"},licenses:[{MIT:"SEE LICENSE IN LICENCE FILE"}]};var m=c("class-validator");var d=c("class-validator");var tn=c("class-validator");var O=class{validate(n){let e=new Set,r=new Set;for(let i of n||[]){if(e.has(i.id))throw new W(i,"Operator ID already exists");if(e.add(i.id),r.has(i.operatorKey))throw new F(i,"Operator public key already exists");r.add(i.operatorKey)}return!0}defaultMessage(){return"The list of operators contains duplicate entries"}};O=u([(0,tn.ValidatorConstraint)({name:"uniqueList",async:!1})],O);function Bn(t){return function(n,e){(0,tn.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:O})}}var rn=c("class-validator");var w=class{validate(n){return h(this,null,function*(){try{typeof n=="string"?p.deserializeHexStrToPublicKey(n.replace("0x","")):n.forEach(e=>p.deserializeHexStrToPublicKey(e.replace("0x","")))}catch(e){throw new Q(n,"Failed to BLS deserialize validator public key")}return!0})}defaultMessage(){return"Invalid public key"}};w=u([(0,rn.ValidatorConstraint)({name:"publicKey",async:!0})],w);function Kn(t){return function(n,e){(0,rn.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:w})}}var sn=c("class-validator");var B=class{validate(n){try{D.utils.toChecksumAddress(n)}catch(e){throw new S(n,"Owner address is not a valid Ethereum address")}return!0}defaultMessage(){return"Invalid owner address"}};B=u([(0,sn.ValidatorConstraint)({name:"ownerAddress",async:!1})],B);function jn(t){return function(n,e){(0,sn.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:B})}}var an=c("class-validator");var K=class{validate(n){if(!Number.isInteger(n)||n<0)throw new x(n,"Owner nonce is not positive integer");return!0}defaultMessage(){return"Invalid owner nonce"}};K=u([(0,an.ValidatorConstraint)({name:"ownerNonce",async:!1})],K);function Nn(t){return function(n,e){(0,an.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:K})}}var b=class{constructor(){this.ownerNonce=null;this.ownerAddress=null;this.publicKey=null;this.operators=null}update(n){n.ownerAddress&&(this.ownerAddress=n.ownerAddress),typeof n.ownerNonce=="number"&&(this.ownerNonce=n.ownerNonce),n.publicKey&&(this.publicKey=n.publicKey),n.operators&&(this.operators=v(n.operators))}validate(){return h(this,null,function*(){(0,d.validateSync)(this)})}get operatorIds(){var n;return(n=this.operators)!=null&&n.length?this.operators.map(e=>parseInt(String(e.id),10)):[]}get operatorPublicKeys(){var n;return(n=this.operators)!=null&&n.length?this.operators.map(e=>String(e.operatorKey)):[]}};u([(0,d.IsOptional)(),(0,d.IsNumber)(),Nn()],b.prototype,"ownerNonce",2),u([(0,d.IsOptional)(),(0,d.IsString)(),jn()],b.prototype,"ownerAddress",2),u([(0,d.IsOptional)(),(0,d.IsString)(),(0,d.Length)(98,98),Kn()],b.prototype,"publicKey",2),u([(0,d.IsOptional)(),(0,d.ValidateNested)({each:!0}),Bn()],b.prototype,"operators",2);var on=class{_sharesToBytes(n,e){let r=[...e].map(s=>"0x"+Buffer.from(s,"base64").toString("hex"));return`0x${nn([...n,...r]).toString("hex")}`}build(n){return this.readable={publicKey:n.publicKey,operatorIds:n.operatorIds,sharesData:this._sharesToBytes(n.encryptedShares.map(e=>e.publicKey),n.encryptedShares.map(e=>e.privateKey))},this.readable}};var Un=192,Pn=96,N=class{constructor(){this.data=new b,this.payload=new on}buildPayload(n,e){return h(this,null,function*(){let{ownerAddress:r,ownerNonce:i,privateKey:s}=e;if(!Number.isInteger(i)||i<0)throw new x(i,"Owner nonce is not positive integer");let o;try{o=D.utils.toChecksumAddress(r)}catch(f){throw new S(r,"Owner address is not a valid Ethereum address")}let a=this.payload.build({publicKey:n.publicKey,operatorIds:v(n.operators).map(f=>f.id),encryptedShares:n.encryptedShares}),l=yield Dn(`${o}:${i}`,s),g=nn([l,a.sharesData]);return a.sharesData=`0x${g.toString("hex")}`,yield this.validateSingleShares(a.sharesData,{ownerAddress:r,ownerNonce:i,publicKey:yield wn(s)}),a})}validateSingleShares(n,e){return h(this,null,function*(){let{ownerAddress:r,ownerNonce:i,publicKey:s}=e;if(!Number.isInteger(i)||i<0)throw new x(i,"Owner nonce is not positive integer");let o;try{o=D.utils.toChecksumAddress(r)}catch(l){throw new S(r,"Owner address is not a valid Ethereum address")}let a=n.replace("0x","").substring(0,Un);yield On(`${o}:${i}`,`0x${a}`,s)})}buildSharesFromBytes(n,e){let i=n.replace("0x","").substring(Un).substring(0,e*Pn),s=j.utils.arrayify("0x"+i),o=this._splitArray(e,s).map(f=>j.utils.hexlify(f)),a=n.substring(e*Pn),l=j.utils.arrayify("0x"+a),g=this._splitArray(e,l).map(f=>Buffer.from(j.utils.hexlify(f).replace("0x",""),"hex").toString("base64"));return{sharesPublicKeys:o,encryptedKeys:g}}update(n){this.data.update(n),this.validate()}validate(){(0,m.validateSync)(this)}fromJson(n){let e=typeof n=="string"?JSON.parse(n):n,r=En.default.parse(e.version),i=En.default.parse(en.version);if(!r||!i)throw new Error("The file for keyshares must contain a version mark provided by ssv-keys.");if(!r||i.major!==r.major||i.minor!==r.minor)throw new Error(`The keyshares file you are attempting to reuse does not have the same version (v${en.version}) as supported by ssv-keys`);return this.update(e.data),this}toJson(){return JSON.stringify({version:`v${en.version}`,createdAt:new Date().toISOString(),data:this.data||null,payload:this.payload.readable||null},null," ")}_splitArray(n,e){let r=Math.floor(e.length/n),i=[];for(let s=0;s{for(var e in n)__webpack_require__.o(n,e)&&!__webpack_require__.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},__webpack_require__.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),__webpack_require__.r=t=>{typeof Symbol!="undefined"&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./lib/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})()})},{}]},{},[1])(1)})});var cn;try{window.crypto,cn=c("bls-eth-wasm/browser")}catch(t){cn=c("bls-eth-wasm")}var p=cn;var ln=class{constructor(){this.operatorsCount=3}setOperatorsCount(n){this.operatorsCount=n}},xn=t=>!(t<4||t>13||t%3!=1),Gn=new ln;var P=class extends Error{constructor(e,r){super(r);this.data=e}},k=class extends Error{constructor(e,r){super(r);this.data=e}},M=class extends Error{constructor(n){super(n)}},E=class extends Error{constructor(n){super(n)}},L=class extends Error{constructor(e,r){super(r);this.data=e}},S=class extends Error{constructor(e,r){super(r);this.data=e}},x=class extends Error{constructor(e,r){super(r);this.data=e}};var un=class extends Error{constructor(e,r){super(r);this.operators=e}},hn=class extends Error{constructor(e,r){super(r);this.operator=e}},gn=class{constructor(){this.shares=[]}static get DEFAULT_THRESHOLD_NUMBER(){return 3}create(n,e){return h(this,null,function*(){if(!n.startsWith("0x"))throw new L(n,"The private key must be provided in the 0x format.");if(e.map(a=>{if(!Number.isInteger(a))throw new hn(a,`Operator must be integer. Got: ${a}`)}),!xn(e.length))throw new un(e,"Invalid operators amount. Enter an 3f+1 compatible amount of operator ids.");let r=[],i=[];p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381)),this.privateKey=p.deserializeHexStrToSecretKey(n.replace("0x","")),this.publicKey=this.privateKey.getPublicKey(),r.push(this.privateKey),i.push(this.publicKey);let s=(e.length-1)/3;for(let a=1;a`0${(e&255).toString(16)}`.slice(-2)).join("")}},H=fn;var _n;try{window.crypto,_n=c("jsencrypt").JSEncrypt||c("jsencrypt")}catch(t){_n=Rn()}var q=_n;var bn=c("js-base64");var W=class extends Error{constructor(e,r){super(r);this.operator=e}},F=class extends Error{constructor(e,r){super(r);this.operator=e}},G=class extends Error{constructor(e,r,i){super(i);this.listOne=e,this.listTwo=r}},z=class extends Error{constructor(e,r){super(r);this.operator=e}};var Y=t=>{t=t.trim();let n="-----BEGIN RSA PUBLIC KEY-----",e="-----END RSA PUBLIC KEY-----",r=new q({}),i="";try{let s="";if(t.startsWith(n))s=t;else{if(t.length<98)throw Error("The length of the operator public key must be at least 98 characters.");try{s=(0,bn.decode)(t).trim()}catch(o){throw new Error("Failed to decode the operator public key. Ensure it's correctly base64 encoded.")}if(!s.startsWith(n))throw new Error(`Operator public key does not start with '${n}'`)}if(!s.endsWith(e))throw new Error(`Operator public key does not end with '${e}'`);try{let o=s.slice(n.length,t.length-e.length).trim();i=(0,bn.decode)(o)}catch(o){throw new Error("Failed to decode the RSA public key. Ensure it's correctly base64 encoded.")}try{r.setPublicKey(i)}catch(o){throw new Error("Invalid operator key format, make sure the operator exists in the network.")}}catch(s){throw new z({rsa:i,base64:t},s.message)}return!0};var R=class{constructor(n,e){this.operatorPublicKeys=[...n],this.shares=e}encrypt(){let n=[];for(let[e,r]of this.operatorPublicKeys.entries()){Y(r);let i=new q({});i.setPublicKey(r);let s=i.encrypt(this.shares[e].privateKey),o={operatorPublicKey:r,privateKey:s,publicKey:this.shares[e].publicKey};n.push(o)}return n}};var _=c("class-validator");var Z=c("class-validator");var I=class{validate(n){return Y(n)}defaultMessage(){return"Invalid operator public key"}};I=u([(0,Z.ValidatorConstraint)({name:"operatorKey",async:!1})],I);function Tn(t){return function(n,e){(0,Z.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:I})}}var T=class{constructor(n){this.id=n.id,this.operatorKey=n.operatorKey,this.validate()}validate(){(0,_.validateSync)(this)}};u([(0,_.IsNotEmpty)({message:"The operator id is null"}),(0,_.IsDefined)({message:"The operator id is undefined"}),(0,_.IsInt)({message:"The operator id must be an integer"})],T.prototype,"id",2),u([(0,_.IsNotEmpty)({message:"The operator public key is null"}),(0,_.IsDefined)({message:"The operator public key is undefined"}),(0,_.IsString)({message:"The operator public key must be a string"}),Tn()],T.prototype,"operatorKey",2);var v=t=>t.sort((n,e)=>+n.id-+e.id).map(n=>{if(!n.id||!n.operatorKey)throw new G(t,t,"Mismatch amount of operator ids and operator keys.");return new T(n)});var $=class{extractKeys(n,e){return h(this,null,function*(){let r=yield new H(n).getPrivateKey(e);return p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381)),{privateKey:`0x${r}`,publicKey:`0x${p.deserializeHexStrToSecretKey(r).getPublicKey().serializeToHexStr()}`}})}createThreshold(n,e){return h(this,null,function*(){let r=v(e);return this.threshold=yield new C().create(n,r.map(i=>i.id)),this.threshold})}encryptShares(n,e){return h(this,null,function*(){let i=v(n).map(s=>Buffer.from(s.operatorKey,"base64").toString());return new R(i,e).encrypt()})}buildShares(n,e){return h(this,null,function*(){let r=yield this.createThreshold(n,e);return this.encryptShares(e,r.shares)})}getThreshold(){return this.threshold}};$.SHARES_FORMAT_ABI="abi";var j=y(c("ethers")),En=y(c("semver"));var An=y(c("web3")),In=y(c("ethers")),mn=y(c("ethereumjs-util"));var Q=class extends Error{constructor(e,r){super(r);this.publicKey=e}},X=class extends Error{constructor(e,r){super(r);this.data=e}};var D=new An.default;var nn=t=>{let n=new Uint8Array(t.map(e=>[...In.utils.arrayify(e)]).flat());return Buffer.from(n)},Dn=(t,n)=>h(void 0,null,function*(){p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381));let e=p.deserializeHexStrToSecretKey(n.replace("0x","")),r=mn.keccak256(Buffer.from(t));return`0x${e.sign(new Uint8Array(r)).serializeToHexStr()}`}),On=(t,n,e)=>h(void 0,null,function*(){p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381));let r=p.deserializeHexStrToPublicKey(e.replace("0x","")),i=p.deserializeHexStrToSignature(n.replace("0x","")),s=mn.keccak256(Buffer.from(t));if(!r.verify(i,new Uint8Array(s)))throw new X(n,"Single shares signature is invalid")}),wn=t=>h(void 0,null,function*(){return p.deserializeHexStrToSecretKey||(yield p.init(p.BLS12_381)),`0x${p.deserializeHexStrToSecretKey(t.replace("0x","")).getPublicKey().serializeToHexStr()}`});var en={name:"ssv-keys",version:"1.0.4",description:"Tool for splitting a validator key into a predefined threshold of shares via Shamir-Secret-Sharing (SSS), and encrypt them with a set of operator keys.",author:"SSV.Network",repository:"https://github.com/bloxapp/ssv-keys",license:"MIT",keywords:["ssv","ssv.network","keystore","shares"],main:"./dist/tsc/src/main.js",types:"./dist/tsc/src/main.d.ts",bin:{"ssv-keys":"./dist/tsc/src/cli.js"},engines:{node:">=12"},scripts:{"dev:cli":"ts-node src/cli.ts","dev:icli":"ts-node src/cli-interactive.ts",icli:"node ./dist/tsc/src/cli-interactive.js",cli:"node ./dist/tsc/src/cli.js",lint:"eslint src/ --ext .js,.jsx,.ts,.tsx",test:"jest",clean:"rm -rf dist build package","ts-node":"ts-node",docs:"typedoc",build:"tsc -p tsconfig.json","build-all":"yarn clean && yarn build && yarn esbuild",esbuild:"node ./esbuild.js","pre-commit":"yarn test && yarn lint && yarn build-all","package-linux":"pkg dist/tsc/src/cli-interactive.js --targets node14-linux-x64 --output bin/linux/ssv-keys-lin --compress GZip","package-macos":"pkg dist/tsc/src/cli-interactive.js --targets node14-macos-x64 --output bin/macos/ssv-keys-mac --compress GZip","package-win":"pkg dist/tsc/src/cli-interactive.js --targets node14-win-x64 --output bin/win/ssv-keys.exe --compress GZip","package-all":"yarn package-linux && yarn package-macos && yarn package-win"},devDependencies:{"@testing-library/jest-dom":"^5.16.4","@types/argparse":"^2.0.10","@types/atob":"^2.1.2","@types/btoa":"^1.2.3","@types/jest":"^26.0.24","@types/node":"^15.14.9","@types/prompts":"^2.0.14","@types/semver":"^7.5.0","@typescript-eslint/eslint-plugin":"^4.33.0","@typescript-eslint/parser":"^4.33.0",esbuild:"^0.14.38","esbuild-node-externals":"^1.4.1",eslint:"^7.32.0",husky:"^7.0.4",jest:"^26.6.3","jest-environment-jsdom":"^26.6.2","jest-environment-node":"^26.6.2","jest-environment-uint8array":"^1.0.0","jest-watch-typeahead":"0.6.5",jsdom:"^16.5.3","jsdom-global":"^3.0.2",pkg:"^5.7.0","ts-jest":"^26.5.6","ts-node":"^10.9.1",typedoc:"^0.22.15",typescript:"^4.6.4"},dependencies:{"@types/figlet":"^1.5.4","@types/underscore":"^1.11.4","@types/yargs":"^17.0.12",argparse:"^2.0.1",assert:"^2.0.0",atob:"^2.1.2","bls-eth-wasm":"^1.0.4","bls-signatures":"^0.2.5",btoa:"^1.2.1","class-validator":"^0.13.2",colors:"^1.4.0",crypto:"^1.0.1","eth2-keystore-js":"^1.0.8","ethereumjs-util":"^7.1.5","ethereumjs-wallet":"^1.0.1",ethers:"^5.7.2",events:"^3.3.0",figlet:"^1.5.2","js-base64":"^3.7.2",jsencrypt:"3.2.1",minimist:"^1.2.6",moment:"^2.29.3","node-jsencrypt":"^1.0.0",prompts:"https://github.com/meshin-blox/prompts.git","scrypt-js":"^3.0.1",semver:"^7.5.1",stream:"^0.0.2",underscore:"^1.13.4",web3:"1.7.3",yargs:"^17.5.1"},licenses:[{MIT:"SEE LICENSE IN LICENCE FILE"}]};var m=c("class-validator");var d=c("class-validator");var tn=c("class-validator");var O=class{validate(n){let e=new Set,r=new Set;for(let i of n||[]){if(e.has(i.id))throw new W(i,"Operator ID already exists");if(e.add(i.id),r.has(i.operatorKey))throw new F(i,"Operator public key already exists");r.add(i.operatorKey)}return!0}defaultMessage(){return"The list of operators contains duplicate entries"}};O=u([(0,tn.ValidatorConstraint)({name:"uniqueList",async:!1})],O);function Bn(t){return function(n,e){(0,tn.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:O})}}var rn=c("class-validator");var w=class{validate(n){return h(this,null,function*(){try{typeof n=="string"?p.deserializeHexStrToPublicKey(n.replace("0x","")):n.forEach(e=>p.deserializeHexStrToPublicKey(e.replace("0x","")))}catch(e){throw new Q(n,"Failed to BLS deserialize validator public key")}return!0})}defaultMessage(){return"Invalid public key"}};w=u([(0,rn.ValidatorConstraint)({name:"publicKey",async:!0})],w);function Kn(t){return function(n,e){(0,rn.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:w})}}var sn=c("class-validator");var B=class{validate(n){try{D.utils.toChecksumAddress(n)}catch(e){throw new S(n,"Owner address is not a valid Ethereum address")}return!0}defaultMessage(){return"Invalid owner address"}};B=u([(0,sn.ValidatorConstraint)({name:"ownerAddress",async:!1})],B);function jn(t){return function(n,e){(0,sn.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:B})}}var an=c("class-validator");var K=class{validate(n){if(!Number.isInteger(n)||n<0)throw new x(n,"Owner nonce is not positive integer");return!0}defaultMessage(){return"Invalid owner nonce"}};K=u([(0,an.ValidatorConstraint)({name:"ownerNonce",async:!1})],K);function Nn(t){return function(n,e){(0,an.registerDecorator)({target:n.constructor,propertyName:e,options:t,constraints:[],validator:K})}}var b=class{constructor(){this.ownerNonce=null;this.ownerAddress=null;this.publicKey=null;this.operators=null}update(n){n.ownerAddress&&(this.ownerAddress=n.ownerAddress),typeof n.ownerNonce=="number"&&(this.ownerNonce=n.ownerNonce),n.publicKey&&(this.publicKey=n.publicKey),n.operators&&(this.operators=v(n.operators))}validate(){return h(this,null,function*(){(0,d.validateSync)(this)})}get operatorIds(){var n;return(n=this.operators)!=null&&n.length?this.operators.map(e=>parseInt(String(e.id),10)):[]}get operatorPublicKeys(){var n;return(n=this.operators)!=null&&n.length?this.operators.map(e=>String(e.operatorKey)):[]}};u([(0,d.IsOptional)(),(0,d.IsNumber)(),Nn()],b.prototype,"ownerNonce",2),u([(0,d.IsOptional)(),(0,d.IsString)(),jn()],b.prototype,"ownerAddress",2),u([(0,d.IsOptional)(),(0,d.IsString)(),(0,d.Length)(98,98),Kn()],b.prototype,"publicKey",2),u([(0,d.IsOptional)(),(0,d.ValidateNested)({each:!0}),Bn()],b.prototype,"operators",2);var on=class{_sharesToBytes(n,e){let r=[...e].map(s=>"0x"+Buffer.from(s,"base64").toString("hex"));return`0x${nn([...n,...r]).toString("hex")}`}build(n){return this.readable={publicKey:n.publicKey,operatorIds:n.operatorIds,sharesData:this._sharesToBytes(n.encryptedShares.map(e=>e.publicKey),n.encryptedShares.map(e=>e.privateKey))},this.readable}};var Un=192,Pn=96,N=class{constructor(){this.data=new b,this.payload=new on}buildPayload(n,e){return h(this,null,function*(){let{ownerAddress:r,ownerNonce:i,privateKey:s}=e;if(!Number.isInteger(i)||i<0)throw new x(i,"Owner nonce is not positive integer");let o;try{o=D.utils.toChecksumAddress(r)}catch(f){throw new S(r,"Owner address is not a valid Ethereum address")}let a=this.payload.build({publicKey:n.publicKey,operatorIds:v(n.operators).map(f=>f.id),encryptedShares:n.encryptedShares}),l=yield Dn(`${o}:${i}`,s),g=nn([l,a.sharesData]);return a.sharesData=`0x${g.toString("hex")}`,yield this.validateSingleShares(a.sharesData,{ownerAddress:r,ownerNonce:i,publicKey:yield wn(s)}),a})}validateSingleShares(n,e){return h(this,null,function*(){let{ownerAddress:r,ownerNonce:i,publicKey:s}=e;if(!Number.isInteger(i)||i<0)throw new x(i,"Owner nonce is not positive integer");let o;try{o=D.utils.toChecksumAddress(r)}catch(l){throw new S(r,"Owner address is not a valid Ethereum address")}let a=n.replace("0x","").substring(0,Un);yield On(`${o}:${i}`,`0x${a}`,s)})}buildSharesFromBytes(n,e){let i=n.replace("0x","").substring(Un).substring(0,e*Pn),s=j.utils.arrayify("0x"+i),o=this._splitArray(e,s).map(f=>j.utils.hexlify(f)),a=n.substring(e*Pn),l=j.utils.arrayify("0x"+a),g=this._splitArray(e,l).map(f=>Buffer.from(j.utils.hexlify(f).replace("0x",""),"hex").toString("base64"));return{sharesPublicKeys:o,encryptedKeys:g}}update(n){this.data.update(n),this.validate()}validate(){(0,m.validateSync)(this)}fromJson(n){let e=typeof n=="string"?JSON.parse(n):n,r=En.default.parse(e.version),i=En.default.parse(en.version);if(!r||!i)throw new Error("The file for keyshares must contain a version mark provided by ssv-keys.");if(!r||i.major!==r.major||i.minor!==r.minor)throw new Error(`The keyshares file you are attempting to reuse does not have the same version (v${en.version}) as supported by ssv-keys`);return this.update(e.data),this}toJson(){return JSON.stringify({version:`v${en.version}`,createdAt:new Date().toISOString(),data:this.data||null,payload:this.payload.readable||null},null," ")}_splitArray(n,e){let r=Math.floor(e.length/n),i=[];for(let s=0;s=10" + "node": ">=12" }, "scripts": { "dev:cli": "ts-node src/cli.ts", diff --git a/package.json b/package.json index aedcf12..483f1d2 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "ssv-keys": "./dist/tsc/src/cli.js" }, "engines": { - "node": ">=10" + "node": ">=12" }, "scripts": { "dev:cli": "ts-node src/cli.ts",