diff --git a/.gitignore b/.gitignore index c6bba59..815d92b 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,6 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# scratch +scratch.js \ No newline at end of file diff --git a/README.md b/README.md index b29e96e..9f0f9cc 100644 --- a/README.md +++ b/README.md @@ -1 +1,116 @@ -# slp-sdp \ No newline at end of file +# slp-sdp + +Encode and encrypt SDP data according to the Simple Ledger Session Description Protocol (SLSDP) + +## Installation + +### npm +```shell +npm install slp-sdp +``` + +### yarn +```shell +yarn install slp-sdp +``` + +### git + +```shell +git clone https://github.com/badger-cash/slp-sdp.git +``` + +## Usage + +```js +import * as slpsdp from "./index.js"; + +const sdp = 'v=0\r\n' + +'o=rtc 1074756789 0 IN IP4 127.0.0.1\r\n' + +'s=-\r\n' + +'t=0 0\r\n' + +'a=group:BUNDLE 0\r\n' + +'a=msid-semantic:WMS *\r\n' + +'a=setup:active\r\n' + +'a=ice-ufrag:7hJ1\r\n' + +'a=ice-pwd:SYJg4xHfZHfWHHjCMmXIZQ\r\n' + +'a=ice-options:ice2,trickle\r\n' + +'a=fingerprint:sha-256 09:5B:9D:35:59:A7:1E:87:24:FF:6B:68:D3:87:E0:B6:C4:B8:4E:CD:0F:5F:76:D3:AA:8E:38:CC:A6:92:DD:D6\r\n' + +'m=application 59405 UDP/DTLS/SCTP webrtc-datachannel\r\n' + +'c=IN IP4 192.168.1.119\r\n' + +'a=mid:0\r\n' + +'a=sendrecv\r\n' + +'a=sctp-port:5000\r\n' + +'a=max-message-size:262144\r\n' + +'a=candidate:1 1 UDP 2122317823 192.168.1.119 59405 typ host\r\n' + +'a=candidate:2 1 UDP 1686109951 176.99.247.125 59405 typ srflx raddr 0.0.0.0 rport 0\r\n' + +'a=end-of-candidates\r\n' + +const privateKey = Buffer.from('0551c74103024b39b51f461a55d355d558b147cbfffcc7ae24c3f88ca25d826a', 'hex') +const publicKey = Buffer.from('0399539c7356d73a9d2e4e37f8f72539e60489f6a4753ffad3f6bf357e01ca47f9', 'hex') + +const encryptedSdp = slpsdp.encryptSdp(sdp, publicKey) +const encryptedHex = encryptedSdp.toString('hex') +const decryptedSdp = slpsdp.decryptSdp(encryptedSdp, privateKey) +``` + +### Produces + +```js +{ + sdp: 'v=0\r\n' + + 'o=rtc 1074756789 0 IN IP4 127.0.0.1\r\n' + + 's=-\r\n' + + 't=0 0\r\n' + + 'a=group:BUNDLE 0\r\n' + + 'a=msid-semantic:WMS *\r\n' + + 'a=setup:active\r\n' + + 'a=ice-ufrag:7hJ1\r\n' + + 'a=ice-pwd:SYJg4xHfZHfWHHjCMmXIZQ\r\n' + + 'a=ice-options:ice2,trickle\r\n' + + 'a=fingerprint:sha-256 09:5B:9D:35:59:A7:1E:87:24:FF:6B:68:D3:87:E0:B6:C4:B8:4E:CD:0F:5F:76:D3:AA:8E:38:CC:A6:92:DD:D6\r\n' + + 'm=application 59405 UDP/DTLS/SCTP webrtc-datachannel\r\n' + + 'c=IN IP4 192.168.1.119\r\n' + + 'a=mid:0\r\n' + + 'a=sendrecv\r\n' + + 'a=sctp-port:5000\r\n' + + 'a=max-message-size:262144\r\n' + + 'a=candidate:1 1 UDP 2122317823 192.168.1.119 59405 typ host\r\n' + + 'a=candidate:2 1 UDP 1686109951 176.99.247.125 59405 typ srflx raddr 0.0.0.0 rport 0\r\n' + + 'a=end-of-candidates\r\n', + encrypted: '043345aa19d896182fb39b8722f751b560241f9cf295306b7100578147a2263664abf7eb6d1f3cc2f70f5cd62d54c50df1d97460af6fd11c0739a400792f4c6ae2c70926b5cd8bd1f160a9216488c6df8b699f9538de62bf352797078cd256722c9d29837f38c440dd00f4cb890f9e4e99d24ec23fedd9604e124d86f0322a03b40b1872c3fda9d94d599d123d12a514dd7939bff3b3f598e2a717f0653f40e3751ce503887da01b12d65eb09edb2a63b87fe94f4243d9f324365bfe14dda4db3fb24b20c62a9e39a786fd2642503b9595', + encryptedLength: 209, + decrypted: 'a=setup:active\r\n' + + 'a=ice-ufrag:7hJ1\r\n' + + 'a=ice-pwd:SYJg4xHfZHfWHHjCMmXIZQ\r\n' + + 'a=fingerprint:sha-256 09:5B:9D:35:59:A7:1E:87:24:FF:6B:68:D3:87:E0:B6:C4:B8:4E:CD:0F:5F:76:D3:AA:8E:38:CC:A6:92:DD:D6\r\n' + + 'm=application 59405 UDP/DTLS/SCTP webrtc-datachannel\r\n' + + 'a=candidate:1 1 UDP 1686109951 176.99.247.125 59405 typ srflx raddr 0.0.0.0 rport 0\r\n' +} +``` + + +### License + +This software is licensed under the MIT License. + +Copyright Fedor Badger, 2024. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/index.js b/index.js new file mode 100644 index 0000000..2b2ed7e --- /dev/null +++ b/index.js @@ -0,0 +1,279 @@ +import * as eccryptoJS from '@vinarmani/eccrypto-js' + +const ipToBuffer = (ipString) => { + const ipSplit = ipString.split('.') + const ipBufArray = ipSplit.map(num => Buffer.alloc(1, parseInt(num))) + return Buffer.concat(ipBufArray) +} + +const bufferToIp = (ipBuf) => { + const ipArr = [...ipBuf] + return ipArr.join('.') +} + +const encodeCandidate = (candidateString) => { + const type = candidateString.includes('srflx') ? 1 : 2 + const bufArr = [Buffer.alloc(1, type)] + const candidateSplit = candidateString.split(' ') + const priorityBuf = Buffer.alloc(5) + priorityBuf.writeUIntLE(candidateSplit[3], 0, 5) + const addrBuf = ipToBuffer(candidateSplit[4]) + const portBuf = Buffer.alloc(2) + portBuf.writeUInt16LE(parseInt(candidateSplit[5])) + bufArr.push(priorityBuf, addrBuf, portBuf) + if (type === 1) { + const raddrBuf = ipToBuffer(candidateSplit[9]) + const rportBuf = Buffer.alloc(2) + rportBuf.writeUInt16LE(parseInt(candidateSplit[11])) + bufArr.push(raddrBuf, rportBuf) + } + + return Buffer.concat(bufArr) +} + +const decodeCandidate = (encodedCandidate) => { + let candidateString = '1 1 UDP ' + let offset = 0 + const type = encodedCandidate.readUint8(offset) === 1 ? 'srflx' : 'host' + offset += 1 + const priority = encodedCandidate.readUintLE(offset, 5) + offset += 5 + const addr = bufferToIp(encodedCandidate.subarray(offset, offset + 4)) + offset += 4 + const port = encodedCandidate.readUint16LE(offset) + candidateString += `${priority} ${addr} ${port} typ ${type}` + if (type === 'srflx') { + offset += 2 + const raddr = bufferToIp(encodedCandidate.subarray(offset, offset + 4)) + offset += 4 + const rport = encodedCandidate.readUint16LE(offset) + candidateString += ` raddr ${raddr} rport ${rport}` + } + + return candidateString +} + +const encodeSdp = (sdp) => { + const encObj = {} + const sdpSplit = sdp.split('\r\n') + for (let i = 0; i < sdpSplit.length; i++) { + const line = sdpSplit[i] + const [key, val] = line.split(line.includes('m=application') ? / (.*)/s : /:(.*)/s) + encObj[key] = val + } + + let setupBuf = Buffer.alloc(1) // active, 1 + switch (encObj['a=setup']) { + case 'active': + setupBuf.writeUint8(1) + break; + case 'passive': + setupBuf.writeUint8(2) + break; + case 'actpass': + setupBuf.writeUint8(3) + break; + default: + break + } + + const ufragBuf = Buffer.from(encObj['a=ice-ufrag'], 'utf-8') + const ufragLenBuf = Buffer.alloc(1) + ufragLenBuf.writeUint8(ufragBuf.length) + + const pwdBuf = Buffer.from(encObj['a=ice-pwd'], 'utf-8') + const pwdLenBuf = Buffer.alloc(1) + pwdLenBuf.writeUInt8(pwdBuf.length) + + const [, fullFingerprint] = encObj['a=fingerprint'].split(' ') + const fingerprint = fullFingerprint.replaceAll(':', '') + const fingerprintBuf = Buffer.from(fingerprint, 'hex') + + const [ applicationInt ] = encObj['m=application'].split(' ', 1) + const applicationIntBuf = Buffer.alloc(4) + applicationIntBuf.writeUint32LE(applicationInt) + + const candidateBuf = encodeCandidate(encObj['a=candidate']) + + const encArr = [ + setupBuf, + ufragLenBuf, + ufragBuf, + pwdLenBuf, + pwdBuf, + fingerprintBuf, + applicationIntBuf, + candidateBuf + ] + + const encodedSdp = Buffer.concat(encArr) + return encodedSdp +} + +const decimalToHex = (d, padding) => { + var hex = Number(d).toString(16); + padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; + + while (hex.length < padding) { + hex = "0" + hex; + } + + return hex; +} + +const decodeSdp = (encodedSdp) => { + let offset = 0 + let sdp = 'a=setup:' + switch (encodedSdp.readUint8(offset)) { + case 1: + sdp += 'active' + break; + case 2: + sdp += 'passive' + break; + case 3: + sdp += 'actpass' + break; + default: + break + } + + sdp += '\r\na=ice-ufrag:' + offset += 1 + const ufragLen = encodedSdp.readUint8(offset) + offset += 1 + sdp += encodedSdp.subarray(offset, offset + ufragLen).toString('utf-8') + offset += ufragLen + + sdp += '\r\na=ice-pwd:' + const pwdLen = encodedSdp.readUint8(offset) + offset += 1 + sdp += encodedSdp.subarray(offset, offset + pwdLen).toString('utf-8') + offset += pwdLen + + sdp += '\r\na=fingerprint:sha-256 ' + const fingerprintBuf = encodedSdp.subarray(offset, offset + 32) + const fingerprintArr = [...fingerprintBuf].map(num => decimalToHex(num).toUpperCase()) + sdp += fingerprintArr.join(':') + offset += 32 + + sdp += '\r\nm=application ' + const applicationInt = encodedSdp.readUint32LE(offset) + sdp += applicationInt + ' UDP/DTLS/SCTP webrtc-datachannel' + offset += 4 + + sdp += '\r\na=candidate:' + const encodedCandidate = encodedSdp.subarray(offset) + sdp += decodeCandidate(encodedCandidate) + '\r\n' + + return sdp + +} + +const invalidIpStrings = [ + '127.0.0.1', + '192.168', + '169.254', + '::' +] + +const extraSdp = [ + 'o=', + 'c=', + 's=', + 'v=', + 't=', + 'a=group', + 'a=msid', + 'a=ice-options', + 'a=mid', + 'a=sendrecv', + 'a=sctp-port', + 'a=max-message-size' +] + +const isRemoteIpCandidate = (candidateLine) => { + const lineSplit = candidateLine.split(' ') + if (lineSplit[2].toUpperCase() !== 'UDP') + return false + // if (invalidIpStrings.some(sub => lineSplit[4].includes(sub))) + // return false + if (lineSplit[7].toUpperCase() !== 'SRFLX') + return false + return true +} + +// Only use remote candidate +const filterSdp = (sdp) => { + const sdpSplit = sdp.split('\r\n') + const filteredSplitSdp = [] + for (let i = 0; i < sdpSplit.length; i++) { + const line = sdpSplit[i] + if (extraSdp.some(prop => line.includes(prop))) + continue + // Only include remote candidates + if (line.includes('a=candidate') && !isRemoteIpCandidate(line)) + continue + + filteredSplitSdp.push(line) + // leave after the first remote candidate + if (line.includes('a=candidate') && isRemoteIpCandidate(line)) + break + } + const filteredSdp = filteredSplitSdp.join('\r\n') + return filteredSdp +} + +const convertToEncryptStruct = (encbuf) => { + let offset = 0; + let tagLength = 32; + let pub; + switch(encbuf[0]) { + case 4: + pub = encbuf.slice(0, 65); + break; + case 3: + case 2: + pub = encbuf.slice(0, 33); + break; + default: + throw new Error('Invalid type: ' + encbuf[0]); + } + offset += pub.length; + + let c = encbuf.slice(offset, encbuf.length - tagLength); + let ivbuf = c.slice(0, 128 / 8); + let ctbuf = c.slice(128 / 8); + + let d = encbuf.slice(encbuf.length - tagLength, encbuf.length); + + return { + iv: ivbuf, + ephemPublicKey: pub, + ciphertext: ctbuf, + mac: d + } +} + +const encryptSdp = (sdp, publicKey) => { + const filteredSdp = filterSdp(sdp) + const encodedSdp = encodeSdp(filteredSdp) + const structuredEj = eccryptoJS.encryptSync(publicKey, encodedSdp) + return Buffer.concat([structuredEj.ephemPublicKey, structuredEj.iv, structuredEj.ciphertext, structuredEj.mac]) +} + +const decryptSdp = (encryptedSdpBuf, privateKey) => { + const encodedSdp = eccryptoJS.decryptSync(privateKey, convertToEncryptStruct(encryptedSdpBuf)) + return decodeSdp(encodedSdp) +} + +export { + filterSdp, + isRemoteIpCandidate, + encodeSdp, + decodeSdp, + encodeCandidate, + decodeCandidate, + encryptSdp, + decryptSdp +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..197d99b --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "slp-sdp", + "version": "1.0.0", + "description": "Encode and encrypt SDP data according to the Simple Ledger Session Description Protocol (SLSDP)", + "main": "index.js", + "repository": "https://github.com/badger-cash/slp-sdp.git", + "author": "Vin Armani ", + "license": "MIT", + "type": "module", + "dependencies": { + "@vinarmani/eccrypto-js": "^5.4.1" + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..5cfe33a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,288 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@vinarmani/eccrypto-js@^5.4.1": + version "5.4.1" + resolved "https://registry.yarnpkg.com/@vinarmani/eccrypto-js/-/eccrypto-js-5.4.1.tgz#aabfb4efcc7aa0861dafb428be57e7e46fc914e8" + integrity sha512-HO5nDcneLAhKxSQOZzz1D0EwDGwoFxHpOLEy7hTxOO2QZeCv03AsoAnTpGVZ6KzlnuWSOJLOffz2UwcOMLQKkQ== + dependencies: + aes-js "3.1.2" + enc-utils "2.1.0" + hash.js "1.1.7" + js-sha3 "0.8.0" + pbkdf2 "^3.0.17" + randombytes "2.1.0" + secp256k1 "3.8.0" + +aes-js@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bip66@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw== + dependencies: + safe-buffer "^5.0.1" + +bn.js@4.11.8: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +bn.js@^4.11.8, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browserify-aes@^1.0.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +drbg.js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g== + dependencies: + browserify-aes "^1.0.6" + create-hash "^1.1.2" + create-hmac "^1.1.4" + +elliptic@^6.5.2: + version "6.5.5" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +enc-utils@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/enc-utils/-/enc-utils-2.1.0.tgz#f6c28c3d4bb38fb409a93185848cf361f4fde142" + integrity sha512-VD0eunGDyzhojePzkORWDnW88gi6tIeGb5Z6QVHugux6mMAPiXyw94fb/7WdDQEWhKMSoYRyzFFUebCqeH20PA== + dependencies: + bn.js "4.11.8" + is-typedarray "1.0.0" + typedarray-to-buffer "3.1.5" + +evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-typedarray@1.0.0, is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +nan@^2.14.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" + integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== + +pbkdf2@^3.0.17: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +randombytes@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +secp256k1@3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" + integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== + dependencies: + bindings "^1.5.0" + bip66 "^1.1.5" + bn.js "^4.11.8" + create-hash "^1.2.0" + drbg.js "^1.0.1" + elliptic "^6.5.2" + nan "^2.14.0" + safe-buffer "^5.1.2" + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +typedarray-to-buffer@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==