├── settings.json ├── package.json ├── Messaging ├── Messages │ ├── Server │ │ ├── ServerHelloMessage.js │ │ ├── LoginOkMessage.js │ │ └── LoginFailedMessage.js │ └── Client │ │ ├── ClientHelloMessage.js │ │ └── LoginMessage.js ├── LogicLaserMessageFactory.js └── Messaging.js ├── utils └── Debugger.js ├── TcpSocket └── Connection.js ├── DataStream ├── Queue.js └── ByteStream.js ├── Crypto ├── Nonce.js ├── PepperCrypto.js ├── util.js ├── blake2b.js └── Nacl.js ├── LICENSE ├── README.md └── Program.js /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash": "08dae21938f2f66e9a1dcc3d857b5fdf7f0e3eb8", 3 | "major": 59, 4 | "minor": 219, 5 | "build": 1 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "brawlstars-client", 3 | "version": "1.0.0", 4 | "description": "an unofficial brawl stars client", 5 | "main": "Program.js", 6 | "scripts": { 7 | "test": "node Program.js" 8 | }, 9 | "author": "S.B#0056 & risporce#6552", 10 | "license": "MIT", 11 | "dependencies": { 12 | "colors": "^1.4.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Messaging/Messages/Server/ServerHelloMessage.js: -------------------------------------------------------------------------------- 1 | const ByteStream = require("../../../DataStream/ByteStream"); 2 | 3 | module.exports = class { 4 | constructor() { 5 | this.ByteStream = new ByteStream(); 6 | } 7 | decode() {} 8 | process(messaging) { 9 | messaging.sendPepperLogin(); 10 | } 11 | } 12 | 13 | module.exports.getMessageType = () => 20100; 14 | -------------------------------------------------------------------------------- /Messaging/LogicLaserMessageFactory.js: -------------------------------------------------------------------------------- 1 | const Messages = { 2 | 20100: require("./Messages/Server/ServerHelloMessage"), 3 | 20103: require("./Messages/Server/LoginFailedMessage"), 4 | 20104: require("./Messages/Server/LoginOkMessage") 5 | } 6 | 7 | function createMessageByType(type) { 8 | if (Messages[type]) { 9 | return new Messages[type](); 10 | } 11 | } 12 | 13 | module.exports = { 14 | createMessageByType 15 | } -------------------------------------------------------------------------------- /utils/Debugger.js: -------------------------------------------------------------------------------- 1 | const colors = require('colors/safe'); 2 | 3 | global.Debugger = { 4 | warn: function(...args) { 5 | console.log(colors.brightYellow("[WARNING]", args.join(" "))); 6 | }, 7 | info: function(...args) { 8 | console.log(colors.brightCyan("[INFO]", args.join(" "))); 9 | }, 10 | error: function(...args) { 11 | console.log(colors.brightRed("[ERROR]", args.join(" "))); 12 | }, 13 | fatal: function(...args) { 14 | Debugger.error(...args); 15 | process.exit(); 16 | } 17 | } -------------------------------------------------------------------------------- /TcpSocket/Connection.js: -------------------------------------------------------------------------------- 1 | const Messaging = require("../Messaging/Messaging"); 2 | const Queue = require("../DataStream/Queue") 3 | 4 | module.exports = function(client) { 5 | let queue = new Queue(); 6 | let messaging = new Messaging(client, queue); 7 | 8 | messaging.sendPepperAuthentication(); 9 | 10 | client.on("data", data => { 11 | queue.add(data); 12 | while (messaging.pendingJob()) { 13 | messaging.update(); 14 | } 15 | }); 16 | client.on("close", 17 | () => { 18 | Debugger.info("connection closed"); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /DataStream/Queue.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this._data = null; 4 | } 5 | add(buffer) { 6 | if (this._data == null) { 7 | this._data = buffer; 8 | } else { 9 | this._data = Buffer.concat([this._data, buffer]); 10 | } 11 | } 12 | get() { 13 | return this._data; 14 | } 15 | size() { 16 | return this._data.length; 17 | } 18 | release(size) { 19 | this._data = this._data.slice(size); 20 | } 21 | reset() { 22 | this._data = null; 23 | } 24 | } 25 | 26 | module.exports = Queue -------------------------------------------------------------------------------- /Messaging/Messages/Server/LoginOkMessage.js: -------------------------------------------------------------------------------- 1 | const ByteStream = require("../../../DataStream/ByteStream"); 2 | 3 | module.exports = class { 4 | constructor() { 5 | this.ByteStream = new ByteStream(); 6 | } 7 | decode() { 8 | this.hi = this.ByteStream.readInt(); 9 | this.lo = this.ByteStream.readInt(); 10 | this.ByteStream.readInt(); 11 | this.ByteStream.readInt(); 12 | this.token = this.ByteStream.readString(); 13 | } 14 | process(messaging) { 15 | settings.hi = this.hi; 16 | settings.lo = this.lo; 17 | settings.token = this.token; 18 | flush(); 19 | } 20 | } 21 | 22 | module.exports.getMessageType = () => 20100; -------------------------------------------------------------------------------- /Messaging/Messages/Client/ClientHelloMessage.js: -------------------------------------------------------------------------------- 1 | const ByteStream = require("../../../DataStream/ByteStream"); 2 | 3 | module.exports = class { 4 | constructor() { 5 | this.ByteStream = new ByteStream(); 6 | } 7 | encode() { 8 | this.ByteStream.writeInt(2); // protocol version 9 | this.ByteStream.writeInt(48); // crypto version 10 | this.ByteStream.writeInt(settings.major); // major version 11 | this.ByteStream.writeInt(settings.build); // build version 12 | this.ByteStream.writeInt(settings.minor); // minor version 13 | this.ByteStream.writeString(settings.hash); // master hash 14 | this.ByteStream.writeInt(2); 15 | this.ByteStream.writeInt(2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Crypto/Nonce.js: -------------------------------------------------------------------------------- 1 | const Blake2b = require("./blake2b"), 2 | crypto = require("crypto"); 3 | 4 | module.exports = class { 5 | constructor(input) { 6 | if (!input) { 7 | this.nonce = new Uint8Array(crypto.randomBytes(24)); 8 | return; 9 | } 10 | 11 | if (input.Keys) { 12 | let b2b = Blake2b.blake2bInit(24); 13 | if (input.nonce) { 14 | Blake2b.blake2bUpdate(b2b, input.nonce); 15 | } 16 | input.Keys.forEach(key => { 17 | Blake2b.blake2bUpdate(b2b, key); 18 | }) 19 | this.nonce = Blake2b.blake2bFinal(b2b); 20 | } else if (input.nonce) { 21 | this.nonce = input.nonce; 22 | } 23 | } 24 | bytes() { 25 | return this.nonce; 26 | } 27 | increment() { 28 | let temp = Buffer.from(this.nonce); 29 | temp.writeInt32LE(temp.readInt32LE(0) + 2, 0); 30 | this.nonce = new Uint8Array(temp); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 HaccerCat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Messaging/Messages/Server/LoginFailedMessage.js: -------------------------------------------------------------------------------- 1 | const ByteStream = require("../../../DataStream/ByteStream"); 2 | 3 | module.exports = class { 4 | constructor() { 5 | this.ByteStream = new ByteStream(); 6 | } 7 | decode() { 8 | this.error_code = this.ByteStream.readInt(); 9 | this.fingerprint = this.ByteStream.readString(); 10 | } 11 | process(messaging) { 12 | if (this.error_code != 7) { 13 | Debugger.fatal("LoginFailedMessage: received error code {}".format(this.error_code)); 14 | } 15 | const { 16 | sha, 17 | version 18 | } = JSON.parse(this.fingerprint); 19 | Debugger.info("LoginFailedMessage: updating fingerprint settings ".format(sha, version)); 20 | settings.hash = sha; 21 | const versions = version.split(".").map(v => parseInt(v)); 22 | settings.major = versions[0]; 23 | settings.minor = versions[1]; 24 | settings.build = versions[2]; 25 | flush(); 26 | connect(); // reconnect 27 | } 28 | } 29 | 30 | module.exports.getMessageType = () => 20103; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BrawlStars-Client 2 | Client for brawl stars prod server 3 | 4 | # NOTE 5 | This content is not affiliated with, endorsed,sponsored, or specifically approved by supercell and supercell is not responsible for it. 6 | 7 | In addition, you are the only person responsible for your actions when using it. 8 | 9 | ## usage 10 | install required module(s): 11 | ``` 12 | npm install 13 | ``` 14 | run the program: 15 | ``` 16 | node Program.js game.brawlstarsgame.com 9339 17 | ``` 18 | if you want to save decrypted server packets, run the program with: 19 | ``` 20 | node Program.js game.brawlstarsgame.com 9339 dump 21 | ``` 22 | .. or else you can just 23 | ``` 24 | node Program.js dump 25 | ``` 26 | program will gonna use default values 🙃 27 | 28 | # credits 29 | this project was made by [S.B#0056](https://github.com/HaccerCat) and [risporce#6552](https://github.com/risporce) 30 | 31 | # contributors 32 | [@kubune](https://github.com/kubune) - updated client to game version v58 and v59 33 | 34 | [@RyfterWasTaken](https://github.com/RyfterWasTaken) - updated hash and minor versions for v58 35 | 36 | ## give a 🌟 because why not :p 37 | 38 | # [join my discord server](https://discord.gg/b2ejYcJjqA) 39 | -------------------------------------------------------------------------------- /Program.js: -------------------------------------------------------------------------------- 1 | const args = process.argv.slice(2); 2 | 3 | require("./utils/Debugger"); // initialize it globally 4 | 5 | global.dump = args[2] == "dump" || args[0] == "dump"; 6 | 7 | args[0] = args[0] != "dump" && args[0] ? args[0]: "game.brawlstarsgame.com"; 8 | 9 | args[1] ??= 9339; 10 | 11 | if (isNaN(args[1])) Debugger.fatal("port should be an integer."); 12 | 13 | global.String.prototype.format = function(...args) { 14 | return args.reduce((p, c) => p.replace(/{}/, c), this); 15 | } 16 | 17 | const net = require("net"), 18 | Connection = require("./TcpSocket/Connection"), 19 | { 20 | writeFileSync 21 | } = require("fs"); 22 | global.settings = require("./settings.json"); 23 | global.flush = function() { 24 | writeFileSync("settings.json", JSON.stringify(settings, null, 4)); 25 | } 26 | 27 | var client; 28 | 29 | global.connect = function() { 30 | 31 | if (client) { 32 | client.destroy(); 33 | Debugger.info("reconnecting..."); 34 | } 35 | 36 | client = new net.Socket(); 37 | 38 | client.connect(parseInt(args[1]), args[0], () => { 39 | Debugger.info("succesfully connected to {}:{}".format(args[0], args[1])); 40 | Connection(client); 41 | }); 42 | 43 | client.on("error", error => { 44 | Debugger.fatal(error); 45 | }); 46 | } 47 | 48 | connect(); -------------------------------------------------------------------------------- /Messaging/Messages/Client/LoginMessage.js: -------------------------------------------------------------------------------- 1 | const ByteStream = require("../../../DataStream/ByteStream"); 2 | 3 | module.exports = class { 4 | constructor() { 5 | this.ByteStream = new ByteStream(); 6 | } 7 | encode() { 8 | this.ByteStream.writeInt(settings.hi || 0); // high 9 | this.ByteStream.writeInt(settings.lo || 0); // low 10 | this.ByteStream.writeString(settings.token); // token 11 | 12 | this.ByteStream.writeInt(settings.major); 13 | this.ByteStream.writeInt(settings.build); 14 | this.ByteStream.writeInt(settings.minor); 15 | this.ByteStream.writeString(settings.hash); 16 | 17 | this.ByteStream.writeString(); 18 | this.ByteStream.writeDataReference(1, 0); 19 | this.ByteStream.writeString("en-US"); 20 | this.ByteStream.writeString(); 21 | this.ByteStream.writeBoolean(false); 22 | this.ByteStream.writeString(); 23 | this.ByteStream.writeString(); 24 | this.ByteStream.writeBoolean(true); 25 | this.ByteStream.writeString(); 26 | this.ByteStream.writeInt(1448); 27 | this.ByteStream.writeVInt(0); 28 | this.ByteStream.writeString(); 29 | 30 | this.ByteStream.writeString(); 31 | this.ByteStream.writeString(); 32 | this.ByteStream.writeVInt(0); 33 | 34 | this.ByteStream.writeString(); 35 | this.ByteStream.writeString(); 36 | this.ByteStream.writeString(); 37 | 38 | this.ByteStream.writeString(); // Supercell ID Session Token, must be compressed with zlib 39 | 40 | this.ByteStream.writeBoolean(false); 41 | this.ByteStream.writeString(); 42 | this.ByteStream.writeString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Crypto/PepperCrypto.js: -------------------------------------------------------------------------------- 1 | const Nacl = require("./Nacl"), 2 | Nonce = require("./Nonce"), 3 | crypto = require("crypto"); 4 | 5 | module.exports = class { 6 | constructor() { 7 | this.server_public_key = fromHexString("5C344B84451436796B735CB62EE38DF813A31798D21294F8C05E0F2B4CA4C047"); 8 | this.client_secret_key = new Uint8Array(crypto.randomBytes(32)); 9 | this.client_public_key = new Uint8Array(32); 10 | Nacl.lowlevel.crypto_scalarmult_base(this.client_public_key, this.client_secret_key); 11 | this.key = Nacl.box.before(this.server_public_key, this.client_secret_key); 12 | this.nonce = new Nonce({ 13 | Keys: [ 14 | this.client_public_key, 15 | this.server_public_key 16 | ] 17 | }); 18 | this.client_nonce = new Nonce(); 19 | } 20 | encrypt(type, payload) { 21 | if (type == 10100) { 22 | return payload; 23 | } else if (type == 10101) { 24 | return Buffer.concat([this.client_public_key, Nacl.box.after(Buffer.concat([this.session_key, this.client_nonce.bytes(), payload]), this.nonce.bytes(), this.key)]); 25 | } else { 26 | this.client_nonce.increment(); 27 | return Buffer.from(Nacl.box.after(payload, this.client_nonce.bytes(), this.key)); 28 | } 29 | } 30 | decrypt(type, payload) { 31 | if (type == 20100) { 32 | this.session_key = payload.slice(4, 28); 33 | return payload; 34 | } else if ([20104, 20103].includes(type)) { 35 | if (!this.session_key) return payload; 36 | let nonce = new Nonce({ 37 | nonce: this.client_nonce.bytes(), 38 | Keys: [ 39 | this.client_public_key, 40 | this.server_public_key 41 | ] 42 | }); 43 | let decrypted = Nacl.box.open.after(payload, nonce.bytes(), this.key); 44 | this.server_nonce = new Nonce({ 45 | nonce: decrypted.slice(0, 24) 46 | }); 47 | this.key = decrypted.slice(24, 56); 48 | return decrypted.slice(56); 49 | } else { 50 | this.server_nonce.increment(); 51 | return Nacl.box.open.after(payload, this.server_nonce.bytes(), this.key); 52 | } 53 | } 54 | } 55 | 56 | function fromHexString (hexString) { 57 | hexString = hexString.replaceAll(" ", "") 58 | return new Uint8Array(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))) 59 | } 60 | -------------------------------------------------------------------------------- /Crypto/util.js: -------------------------------------------------------------------------------- 1 | // https://github.com/dcposch/blakejs 2 | 3 | const ERROR_MSG_INPUT = 'Input must be an string, Buffer or Uint8Array' 4 | 5 | // For convenience, let people hash a string, not just a Uint8Array 6 | function normalizeInput (input) { 7 | let ret 8 | if (input instanceof Uint8Array) { 9 | ret = input 10 | } else if (typeof input === 'string') { 11 | const encoder = new TextEncoder() 12 | ret = encoder.encode(input) 13 | } else { 14 | throw new Error(ERROR_MSG_INPUT) 15 | } 16 | return ret 17 | } 18 | 19 | // Converts a Uint8Array to a hexadecimal string 20 | // For example, toHex([255, 0, 255]) returns "ff00ff" 21 | function toHex (bytes) { 22 | return Array.prototype.map 23 | .call(bytes, function (n) { 24 | return (n < 16 ? '0' : '') + n.toString(16) 25 | }) 26 | .join('') 27 | } 28 | 29 | // Converts any value in [0...2^32-1] to an 8-character hex string 30 | function uint32ToHex (val) { 31 | return (0x100000000 + val).toString(16).substring(1) 32 | } 33 | 34 | // For debugging: prints out hash state in the same format as the RFC 35 | // sample computation exactly, so that you can diff 36 | function debugPrint (label, arr, size) { 37 | let msg = '\n' + label + ' = ' 38 | for (let i = 0; i < arr.length; i += 2) { 39 | if (size === 32) { 40 | msg += uint32ToHex(arr[i]).toUpperCase() 41 | msg += ' ' 42 | msg += uint32ToHex(arr[i + 1]).toUpperCase() 43 | } else if (size === 64) { 44 | msg += uint32ToHex(arr[i + 1]).toUpperCase() 45 | msg += uint32ToHex(arr[i]).toUpperCase() 46 | } else throw new Error('Invalid size ' + size) 47 | if (i % 6 === 4) { 48 | msg += '\n' + new Array(label.length + 4).join(' ') 49 | } else if (i < arr.length - 2) { 50 | msg += ' ' 51 | } 52 | } 53 | console.log(msg) 54 | } 55 | 56 | // For performance testing: generates N bytes of input, hashes M times 57 | // Measures and prints MB/second hash performance each time 58 | function testSpeed (hashFn, N, M) { 59 | let startMs = new Date().getTime() 60 | 61 | const input = new Uint8Array(N) 62 | for (let i = 0; i < N; i++) { 63 | input[i] = i % 256 64 | } 65 | const genMs = new Date().getTime() 66 | console.log('Generated random input in ' + (genMs - startMs) + 'ms') 67 | startMs = genMs 68 | 69 | for (let i = 0; i < M; i++) { 70 | const hashHex = hashFn(input) 71 | const hashMs = new Date().getTime() 72 | const ms = hashMs - startMs 73 | startMs = hashMs 74 | console.log('Hashed in ' + ms + 'ms: ' + hashHex.substring(0, 20) + '...') 75 | console.log( 76 | Math.round((N / (1 << 20) / (ms / 1000)) * 100) / 100 + ' MB PER SECOND' 77 | ) 78 | } 79 | } 80 | 81 | module.exports = { 82 | normalizeInput: normalizeInput, 83 | toHex: toHex, 84 | debugPrint: debugPrint, 85 | testSpeed: testSpeed 86 | } 87 | -------------------------------------------------------------------------------- /Messaging/Messaging.js: -------------------------------------------------------------------------------- 1 | const LogicLaserMessageFactory = require("./LogicLaserMessageFactory"); 2 | const ClientHelloMessage = require("./Messages/Client/ClientHelloMessage"); 3 | const LoginMessage = require("./Messages/Client/LoginMessage"); 4 | const PepperCrypto = require("../Crypto/PepperCrypto"); 5 | let messages = {} 6 | 7 | let fs; 8 | if (dump) { 9 | fs = require("fs"); 10 | if (!fs.existsSync("./PacketsDumps")) { 11 | fs.mkdirSync("./PacketsDumps"); 12 | } 13 | } 14 | 15 | 16 | class Messaging { 17 | constructor(socket, queue) { 18 | this._queue = queue; 19 | this._socket = socket; 20 | this.crypto = new PepperCrypto(); 21 | } 22 | pendingJob() { 23 | if (this._queue.size() < 7) return false; 24 | return this._queue.get().readUIntBE(2, 3) <= this._queue.size() - 7; 25 | } 26 | update() { 27 | const buffer = this._queue.get(); 28 | const length = buffer.readUIntBE(2, 3); 29 | const type = buffer.readUInt16BE(0); 30 | const version = buffer.readUInt16BE(5); 31 | this._queue.release(length + 7); 32 | const payload = this.crypto.decrypt(type, buffer.slice(7, length + 7)); 33 | if (payload == null) { 34 | return Debugger.fatal("failed to decrypt {}".format(type)) 35 | } 36 | Debugger.info("received message of type: {}, length: {}, version: {}".format(type, length, version)); 37 | const message = LogicLaserMessageFactory.createMessageByType(type); 38 | if (message) { 39 | message.ByteStream.set(payload); 40 | message.decode(); 41 | message.process(this); 42 | } else { 43 | Debugger.info("ignoring unsupported message ({})".format(type)); 44 | } 45 | if (dump) { 46 | if (!messages[type]) messages[type] = 0; 47 | fs.writeFileSync("./PacketsDumps/{}-{}.bin".format(type, messages[type]), payload); 48 | messages[type] += 1; 49 | } 50 | } 51 | sendPepperAuthentication() { 52 | const message = new ClientHelloMessage(); 53 | message.ByteStream.set(100); 54 | message.encode(); 55 | this.encryptAndWriteToSocket(10100, 0, message.ByteStream.getBytes()); 56 | } 57 | sendPepperLogin() { 58 | const message = new LoginMessage(); 59 | message.ByteStream.set(250); 60 | message.encode(); 61 | this.encryptAndWriteToSocket(10101, 0, message.ByteStream.getBytes()); 62 | } 63 | encryptAndWriteToSocket(type, version, buffer) { 64 | const header = Buffer.alloc(7); 65 | header.writeUInt16BE(type, 0); 66 | buffer = this.crypto.encrypt(type, buffer); 67 | header.writeUIntBE(buffer.length, 2, 3); 68 | header.writeUInt16BE(version, 5); 69 | this._socket.write(header); 70 | this._socket.write(buffer); 71 | Debugger.info("sent message of type: {}, length: {}".format(type, buffer.length)); 72 | } 73 | } 74 | 75 | module.exports = Messaging 76 | -------------------------------------------------------------------------------- /DataStream/ByteStream.js: -------------------------------------------------------------------------------- 1 | module.exports = class { 2 | constructor(obj) { 3 | this.payload = new Uint8Array(obj); 4 | this.offset = 0; 5 | } 6 | set(obj) { 7 | this.payload = new Uint8Array(obj); 8 | } 9 | write(a1) { 10 | this.payload[this.offset++] = a1; 11 | } 12 | read() { 13 | return this.payload[this.offset++]; 14 | } 15 | writeUInt(a1) { 16 | this.write(a1 & 0xFF); 17 | } 18 | writeByte(a1) { 19 | this.write(a1); 20 | } 21 | writeBoolean(a1) { 22 | this.write(a1 ? 1: 0); 23 | } 24 | writeInt(a1) { 25 | this.write((a1 >> 24) & 0xFF); 26 | this.write((a1 >> 16) & 0xFF); 27 | this.write((a1 >> 8) & 0xFF); 28 | this.write(a1 & 0xFF); 29 | } 30 | writeString(a1) { 31 | if (!a1) return this.writeInt(-1); 32 | let b = new Uint8Array(Buffer.from(a1)); 33 | this.writeInt(b.length); 34 | for (let strOffset = 0; strOffset < b.length; strOffset++) { 35 | this.write(b[strOffset]); 36 | } 37 | } 38 | writeVInt(a1) { 39 | let v1 = (((a1 >> 25) & 0x40) | (a1 & 0x3F)), 40 | v2 = ((a1 ^ (a1 >> 31)) >> 6), v3 41 | 42 | a1 >>= 6; 43 | if (v2 == 0) { 44 | this.writeByte(v1); 45 | } else { 46 | this.writeByte(v1 | 0x80); 47 | v2 >>= 7; 48 | v3 = 0; 49 | if (v2 > 0) { 50 | v3 = 0x80; 51 | } 52 | this.writeByte((a1 & 0x7F) | v3); 53 | a1 >>= 7; 54 | while (v2 != 0) { 55 | v2 >>= 7; 56 | v3 = 0; 57 | if (v2 > 0) { 58 | v3 = 0x80; 59 | } 60 | this.writeByte((a1 & 0x7F) | v3); 61 | a1 >>= 7; 62 | } 63 | } 64 | } 65 | writeDataReference(a1, a2) { 66 | this.writeVInt(a1); 67 | if (a1 == 0) return; 68 | this.writeVInt(a2); 69 | } 70 | readDataReference() { 71 | let a1 = this.readVInt(); 72 | return [a1, a1 == 0 ? 0 : this.readVInt()]; 73 | } 74 | readInt() { 75 | return (this.read() << 24 | this.read() << 16 | this.read() << 8 | this.read()); 76 | } 77 | readByte() { 78 | return this.read(); 79 | } 80 | readBytes(size) { 81 | let result = new Uint8Array(size); 82 | for (let index = 0; index < size; index++) { 83 | result[index] = this.readByte(); 84 | } 85 | return result; 86 | } 87 | readBoolean() { 88 | return Boolean(this.read()); 89 | } 90 | readString() { 91 | let len = this.readInt(); 92 | if (len <= 0 || len == 4294967295) { 93 | return ""; 94 | } 95 | return Buffer.from(this.readBytes(len)).toString(); 96 | } 97 | readVInt() { 98 | // this method is discovered by nameless#1347 99 | let result = 0, 100 | shift = 0, b, seventh, msb, n; 101 | 102 | while (true) { 103 | b = this.read(); 104 | if (shift == 0) { 105 | seventh = (b & 0x40) >> 6; 106 | msb = (b & 0x80) >> 7; 107 | n = b << 1; 108 | n = n & ~0x181; 109 | b = n | (msb << 7) | seventh; 110 | } 111 | result |= (b & 0x7f) << shift; 112 | shift += 7; 113 | if ((b & 0x80) <= 0) { 114 | break; 115 | } 116 | } 117 | return (result >> 1) ^ (-(result & 1)); 118 | } 119 | getBytes() { 120 | return this.payload.slice(0, this.offset); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /Crypto/blake2b.js: -------------------------------------------------------------------------------- 1 | // Blake2B in pure Javascript 2 | // Adapted from the reference implementation in RFC7693 3 | // Ported to Javascript by DC - https://github.com/dcposch 4 | 5 | // https://github.com/dcposch/blakejs 6 | 7 | const util = require('./util') 8 | 9 | // 64-bit unsigned addition 10 | // Sets v[a,a+1] += v[b,b+1] 11 | // v should be a Uint32Array 12 | function ADD64AA (v, a, b) { 13 | const o0 = v[a] + v[b] 14 | let o1 = v[a + 1] + v[b + 1] 15 | if (o0 >= 0x100000000) { 16 | o1++ 17 | } 18 | v[a] = o0 19 | v[a + 1] = o1 20 | } 21 | 22 | // 64-bit unsigned addition 23 | // Sets v[a,a+1] += b 24 | // b0 is the low 32 bits of b, b1 represents the high 32 bits 25 | function ADD64AC (v, a, b0, b1) { 26 | let o0 = v[a] + b0 27 | if (b0 < 0) { 28 | o0 += 0x100000000 29 | } 30 | let o1 = v[a + 1] + b1 31 | if (o0 >= 0x100000000) { 32 | o1++ 33 | } 34 | v[a] = o0 35 | v[a + 1] = o1 36 | } 37 | 38 | // Little-endian byte access 39 | function B2B_GET32 (arr, i) { 40 | return arr[i] ^ (arr[i + 1] << 8) ^ (arr[i + 2] << 16) ^ (arr[i + 3] << 24) 41 | } 42 | 43 | // G Mixing function 44 | // The ROTRs are inlined for speed 45 | function B2B_G (a, b, c, d, ix, iy) { 46 | const x0 = m[ix] 47 | const x1 = m[ix + 1] 48 | const y0 = m[iy] 49 | const y1 = m[iy + 1] 50 | 51 | ADD64AA(v, a, b) // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s 52 | ADD64AC(v, a, x0, x1) // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits 53 | 54 | // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits 55 | let xor0 = v[d] ^ v[a] 56 | let xor1 = v[d + 1] ^ v[a + 1] 57 | v[d] = xor1 58 | v[d + 1] = xor0 59 | 60 | ADD64AA(v, c, d) 61 | 62 | // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits 63 | xor0 = v[b] ^ v[c] 64 | xor1 = v[b + 1] ^ v[c + 1] 65 | v[b] = (xor0 >>> 24) ^ (xor1 << 8) 66 | v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8) 67 | 68 | ADD64AA(v, a, b) 69 | ADD64AC(v, a, y0, y1) 70 | 71 | // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits 72 | xor0 = v[d] ^ v[a] 73 | xor1 = v[d + 1] ^ v[a + 1] 74 | v[d] = (xor0 >>> 16) ^ (xor1 << 16) 75 | v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16) 76 | 77 | ADD64AA(v, c, d) 78 | 79 | // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits 80 | xor0 = v[b] ^ v[c] 81 | xor1 = v[b + 1] ^ v[c + 1] 82 | v[b] = (xor1 >>> 31) ^ (xor0 << 1) 83 | v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1) 84 | } 85 | 86 | // Initialization Vector 87 | const BLAKE2B_IV32 = new Uint32Array([ 88 | 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 89 | 0x5f1d36f1, 0xa54ff53a, 0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 90 | 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19 91 | ]) 92 | 93 | const SIGMA8 = [ 94 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 10, 4, 8, 9, 15, 13, 95 | 6, 1, 12, 0, 2, 11, 7, 5, 3, 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 96 | 9, 4, 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, 9, 0, 5, 7, 2, 4, 97 | 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 98 | 15, 14, 1, 9, 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, 13, 11, 7, 99 | 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 100 | 13, 7, 1, 4, 10, 5, 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, 0, 101 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 10, 4, 8, 9, 15, 13, 6, 102 | 1, 12, 0, 2, 11, 7, 5, 3 103 | ] 104 | 105 | // These are offsets into a uint64 buffer. 106 | // Multiply them all by 2 to make them offsets into a uint32 buffer, 107 | // because this is Javascript and we don't have uint64s 108 | const SIGMA82 = new Uint8Array( 109 | SIGMA8.map(function (x) { 110 | return x * 2 111 | }) 112 | ) 113 | 114 | // Compression function. 'last' flag indicates last block. 115 | // Note we're representing 16 uint64s as 32 uint32s 116 | const v = new Uint32Array(32) 117 | const m = new Uint32Array(32) 118 | function blake2bCompress (ctx, last) { 119 | let i = 0 120 | 121 | // init work variables 122 | for (i = 0; i < 16; i++) { 123 | v[i] = ctx.h[i] 124 | v[i + 16] = BLAKE2B_IV32[i] 125 | } 126 | 127 | // low 64 bits of offset 128 | v[24] = v[24] ^ ctx.t 129 | v[25] = v[25] ^ (ctx.t / 0x100000000) 130 | // high 64 bits not supported, offset may not be higher than 2**53-1 131 | 132 | // last block flag set ? 133 | if (last) { 134 | v[28] = ~v[28] 135 | v[29] = ~v[29] 136 | } 137 | 138 | // get little-endian words 139 | for (i = 0; i < 32; i++) { 140 | m[i] = B2B_GET32(ctx.b, 4 * i) 141 | } 142 | 143 | // twelve rounds of mixing 144 | // uncomment the DebugPrint calls to log the computation 145 | // and match the RFC sample documentation 146 | // util.debugPrint(' m[16]', m, 64) 147 | for (i = 0; i < 12; i++) { 148 | // util.debugPrint(' (i=' + (i < 10 ? ' ' : '') + i + ') v[16]', v, 64) 149 | B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]) 150 | B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]) 151 | B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]) 152 | B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]) 153 | B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]) 154 | B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]) 155 | B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]) 156 | B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]) 157 | } 158 | // util.debugPrint(' (i=12) v[16]', v, 64) 159 | 160 | for (i = 0; i < 16; i++) { 161 | ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i + 16] 162 | } 163 | // util.debugPrint('h[8]', ctx.h, 64) 164 | } 165 | 166 | // reusable parameterBlock 167 | const parameterBlock = new Uint8Array([ 168 | 0, 169 | 0, 170 | 0, 171 | 0, // 0: outlen, keylen, fanout, depth 172 | 0, 173 | 0, 174 | 0, 175 | 0, // 4: leaf length, sequential mode 176 | 0, 177 | 0, 178 | 0, 179 | 0, // 8: node offset 180 | 0, 181 | 0, 182 | 0, 183 | 0, // 12: node offset 184 | 0, 185 | 0, 186 | 0, 187 | 0, // 16: node depth, inner length, rfu 188 | 0, 189 | 0, 190 | 0, 191 | 0, // 20: rfu 192 | 0, 193 | 0, 194 | 0, 195 | 0, // 24: rfu 196 | 0, 197 | 0, 198 | 0, 199 | 0, // 28: rfu 200 | 0, 201 | 0, 202 | 0, 203 | 0, // 32: salt 204 | 0, 205 | 0, 206 | 0, 207 | 0, // 36: salt 208 | 0, 209 | 0, 210 | 0, 211 | 0, // 40: salt 212 | 0, 213 | 0, 214 | 0, 215 | 0, // 44: salt 216 | 0, 217 | 0, 218 | 0, 219 | 0, // 48: personal 220 | 0, 221 | 0, 222 | 0, 223 | 0, // 52: personal 224 | 0, 225 | 0, 226 | 0, 227 | 0, // 56: personal 228 | 0, 229 | 0, 230 | 0, 231 | 0 // 60: personal 232 | ]) 233 | 234 | // Creates a BLAKE2b hashing context 235 | // Requires an output length between 1 and 64 bytes 236 | // Takes an optional Uint8Array key 237 | // Takes an optinal Uint8Array salt 238 | // Takes an optinal Uint8Array personal 239 | function blake2bInit (outlen, key, salt, personal) { 240 | if (outlen === 0 || outlen > 64) { 241 | throw new Error('Illegal output length, expected 0 < length <= 64') 242 | } 243 | if (key && key.length > 64) { 244 | throw new Error('Illegal key, expected Uint8Array with 0 < length <= 64') 245 | } 246 | if (salt && salt.length !== 16) { 247 | throw new Error('Illegal salt, expected Uint8Array with length is 16') 248 | } 249 | if (personal && personal.length !== 16) { 250 | throw new Error('Illegal personal, expected Uint8Array with length is 16') 251 | } 252 | 253 | // state, 'param block' 254 | const ctx = { 255 | b: new Uint8Array(128), 256 | h: new Uint32Array(16), 257 | t: 0, // input count 258 | c: 0, // pointer within buffer 259 | outlen: outlen // output length in bytes 260 | } 261 | 262 | // initialize parameterBlock before usage 263 | parameterBlock.fill(0) 264 | parameterBlock[0] = outlen 265 | if (key) parameterBlock[1] = key.length 266 | parameterBlock[2] = 1 // fanout 267 | parameterBlock[3] = 1 // depth 268 | if (salt) parameterBlock.set(salt, 32) 269 | if (personal) parameterBlock.set(personal, 48) 270 | 271 | // initialize hash state 272 | for (let i = 0; i < 16; i++) { 273 | ctx.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameterBlock, i * 4) 274 | } 275 | 276 | // key the hash, if applicable 277 | if (key) { 278 | blake2bUpdate(ctx, key) 279 | // at the end 280 | ctx.c = 128 281 | } 282 | 283 | return ctx 284 | } 285 | 286 | // Updates a BLAKE2b streaming hash 287 | // Requires hash context and Uint8Array (byte array) 288 | function blake2bUpdate (ctx, input) { 289 | for (let i = 0; i < input.length; i++) { 290 | if (ctx.c === 128) { 291 | // buffer full ? 292 | ctx.t += ctx.c // add counters 293 | blake2bCompress(ctx, false) // compress (not last) 294 | ctx.c = 0 // counter to zero 295 | } 296 | ctx.b[ctx.c++] = input[i] 297 | } 298 | } 299 | 300 | // Completes a BLAKE2b streaming hash 301 | // Returns a Uint8Array containing the message digest 302 | function blake2bFinal (ctx) { 303 | ctx.t += ctx.c // mark last block offset 304 | 305 | while (ctx.c < 128) { 306 | // fill up with zeros 307 | ctx.b[ctx.c++] = 0 308 | } 309 | blake2bCompress(ctx, true) // final block flag = 1 310 | 311 | // little endian convert and store 312 | const out = new Uint8Array(ctx.outlen) 313 | for (let i = 0; i < ctx.outlen; i++) { 314 | out[i] = ctx.h[i >> 2] >> (8 * (i & 3)) 315 | } 316 | return out 317 | } 318 | 319 | // Computes the BLAKE2B hash of a string or byte array, and returns a Uint8Array 320 | // 321 | // Returns a n-byte Uint8Array 322 | // 323 | // Parameters: 324 | // - input - the input bytes, as a string, Buffer or Uint8Array 325 | // - key - optional key Uint8Array, up to 64 bytes 326 | // - outlen - optional output length in bytes, default 64 327 | // - salt - optional salt bytes, string, Buffer or Uint8Array 328 | // - personal - optional personal bytes, string, Buffer or Uint8Array 329 | function blake2b (input, key, outlen, salt, personal) { 330 | // preprocess inputs 331 | outlen = outlen || 64 332 | input = util.normalizeInput(input) 333 | if (salt) { 334 | salt = util.normalizeInput(salt) 335 | } 336 | if (personal) { 337 | personal = util.normalizeInput(personal) 338 | } 339 | 340 | // do the math 341 | const ctx = blake2bInit(outlen, key, salt, personal) 342 | blake2bUpdate(ctx, input) 343 | return blake2bFinal(ctx) 344 | } 345 | 346 | // Computes the BLAKE2B hash of a string or byte array 347 | // 348 | // Returns an n-byte hash in hex, all lowercase 349 | // 350 | // Parameters: 351 | // - input - the input bytes, as a string, Buffer, or Uint8Array 352 | // - key - optional key Uint8Array, up to 64 bytes 353 | // - outlen - optional output length in bytes, default 64 354 | // - salt - optional salt bytes, string, Buffer or Uint8Array 355 | // - personal - optional personal bytes, string, Buffer or Uint8Array 356 | function blake2bHex (input, key, outlen, salt, personal) { 357 | const output = blake2b(input, key, outlen, salt, personal) 358 | return util.toHex(output) 359 | } 360 | 361 | module.exports = { 362 | blake2b: blake2b, 363 | blake2bHex: blake2bHex, 364 | blake2bInit: blake2bInit, 365 | blake2bUpdate: blake2bUpdate, 366 | blake2bFinal: blake2bFinal 367 | } 368 | -------------------------------------------------------------------------------- /Crypto/Nacl.js: -------------------------------------------------------------------------------- 1 | (function(nacl) { 2 | 'use strict'; 3 | 4 | // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. 5 | // Public domain. 6 | // 7 | // Implementation derived from TweetNaCl version 20140427. 8 | // See for details: http://tweetnacl.cr.yp.to/ 9 | 10 | var u64 = function(h, l) { this.hi = h|0 >>> 0; this.lo = l|0 >>> 0; }; 11 | var gf = function(init) { 12 | var i, r = new Float64Array(16); 13 | if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; 14 | return r; 15 | }; 16 | 17 | // Pluggable, initialized in high-level API below. 18 | var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; 19 | 20 | var _0 = new Uint8Array(16); 21 | var _9 = new Uint8Array(32); _9[0] = 9; 22 | 23 | var gf0 = gf(), 24 | gf1 = gf([1]), 25 | _121665 = gf([0xdb41, 1]), 26 | D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), 27 | D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), 28 | X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), 29 | Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), 30 | I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); 31 | 32 | function L32(x, c) { return (x << c) | (x >>> (32 - c)); } 33 | 34 | function ld32(x, i) { 35 | var u = x[i+3] & 0xff; 36 | u = (u<<8)|(x[i+2] & 0xff); 37 | u = (u<<8)|(x[i+1] & 0xff); 38 | return (u<<8)|(x[i+0] & 0xff); 39 | } 40 | 41 | function dl64(x, i) { 42 | var h = (x[i] << 24) | (x[i+1] << 16) | (x[i+2] << 8) | x[i+3]; 43 | var l = (x[i+4] << 24) | (x[i+5] << 16) | (x[i+6] << 8) | x[i+7]; 44 | return new u64(h, l); 45 | } 46 | 47 | function st32(x, j, u) { 48 | var i; 49 | for (i = 0; i < 4; i++) { x[j+i] = u & 255; u >>>= 8; } 50 | } 51 | 52 | function ts64(x, i, u) { 53 | x[i] = (u.hi >> 24) & 0xff; 54 | x[i+1] = (u.hi >> 16) & 0xff; 55 | x[i+2] = (u.hi >> 8) & 0xff; 56 | x[i+3] = u.hi & 0xff; 57 | x[i+4] = (u.lo >> 24) & 0xff; 58 | x[i+5] = (u.lo >> 16) & 0xff; 59 | x[i+6] = (u.lo >> 8) & 0xff; 60 | x[i+7] = u.lo & 0xff; 61 | } 62 | 63 | function vn(x, xi, y, yi, n) { 64 | var i,d = 0; 65 | for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; 66 | return (1 & ((d - 1) >>> 8)) - 1; 67 | } 68 | 69 | function crypto_verify_16(x, xi, y, yi) { 70 | return vn(x,xi,y,yi,16); 71 | } 72 | 73 | function crypto_verify_32(x, xi, y, yi) { 74 | return vn(x,xi,y,yi,32); 75 | } 76 | 77 | function core(out,inp,k,c,h) { 78 | var w = new Uint32Array(16), x = new Uint32Array(16), 79 | y = new Uint32Array(16), t = new Uint32Array(4); 80 | var i, j, m; 81 | 82 | for (i = 0; i < 4; i++) { 83 | x[5*i] = ld32(c, 4*i); 84 | x[1+i] = ld32(k, 4*i); 85 | x[6+i] = ld32(inp, 4*i); 86 | x[11+i] = ld32(k, 16+4*i); 87 | } 88 | 89 | for (i = 0; i < 16; i++) y[i] = x[i]; 90 | 91 | for (i = 0; i < 19; i++) { // salsa rounds 92 | for (j = 0; j < 4; j++) { 93 | for (m = 0; m < 4; m++) t[m] = x[(5*j+4*m)%16]; 94 | t[1] ^= L32((t[0]+t[3])|0, 7); 95 | t[2] ^= L32((t[1]+t[0])|0, 9); 96 | t[3] ^= L32((t[2]+t[1])|0,13); 97 | t[0] ^= L32((t[3]+t[2])|0,18); 98 | for (m = 0; m < 4; m++) w[4*j+(j+m)%4] = t[m]; 99 | } 100 | for (m = 0; m < 16; m++) x[m] = w[m]; 101 | } 102 | 103 | if (h) { 104 | for (i = 0; i < 16; i++) x[i] = (x[i] + y[i]) | 0; 105 | for (i = 0; i < 4; i++) { 106 | x[5*i] = (x[5*i] - ld32(c, 4*i)) | 0; 107 | x[6+i] = (x[6+i] - ld32(inp, 4*i)) | 0; 108 | } 109 | for (i = 0; i < 4; i++) { 110 | st32(out,4*i,x[5*i]); 111 | st32(out,16+4*i,x[6+i]); 112 | } 113 | } else { 114 | for (i = 0; i < 16; i++) st32(out, 4 * i, (x[i] + y[i]) | 0); 115 | } 116 | } 117 | 118 | function crypto_core_salsa20(out,inp,k,c) { 119 | core(out,inp,k,c,false); 120 | return 0; 121 | } 122 | 123 | function crypto_core_hsalsa20(out,inp,k,c) { 124 | core(out,inp,k,c,true); 125 | return 0; 126 | } 127 | 128 | var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]); 129 | // "expand 32-byte k" 130 | 131 | function crypto_stream_salsa20_xor(c,cpos,m,mpos,b,n,k) { 132 | var z = new Uint8Array(16), x = new Uint8Array(64); 133 | var u, i; 134 | if (!b) return 0; 135 | for (i = 0; i < 16; i++) z[i] = 0; 136 | for (i = 0; i < 8; i++) z[i] = n[i]; 137 | while (b >= 64) { 138 | crypto_core_salsa20(x,z,k,sigma); 139 | for (i = 0; i < 64; i++) c[cpos+i] = (m?m[mpos+i]:0) ^ x[i]; 140 | u = 1; 141 | for (i = 8; i < 16; i++) { 142 | u = u + (z[i] & 0xff) | 0; 143 | z[i] = u & 0xff; 144 | u >>>= 8; 145 | } 146 | b -= 64; 147 | cpos += 64; 148 | if (m) mpos += 64; 149 | } 150 | if (b > 0) { 151 | crypto_core_salsa20(x,z,k,sigma); 152 | for (i = 0; i < b; i++) c[cpos+i] = (m?m[mpos+i]:0) ^ x[i]; 153 | } 154 | return 0; 155 | } 156 | 157 | function crypto_stream_salsa20(c,cpos,d,n,k) { 158 | return crypto_stream_salsa20_xor(c,cpos,null,0,d,n,k); 159 | } 160 | 161 | function crypto_stream(c,cpos,d,n,k) { 162 | var s = new Uint8Array(32); 163 | crypto_core_hsalsa20(s,n,k,sigma); 164 | return crypto_stream_salsa20(c,cpos,d,n.subarray(16),s); 165 | } 166 | 167 | function crypto_stream_xor(c,cpos,m,mpos,d,n,k) { 168 | var s = new Uint8Array(32); 169 | crypto_core_hsalsa20(s,n,k,sigma); 170 | return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,n.subarray(16),s); 171 | } 172 | 173 | function add1305(h, c) { 174 | var j, u = 0; 175 | for (j = 0; j < 17; j++) { 176 | u = (u + ((h[j] + c[j]) | 0)) | 0; 177 | h[j] = u & 255; 178 | u >>>= 8; 179 | } 180 | } 181 | 182 | var minusp = new Uint32Array([ 183 | 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 184 | ]); 185 | 186 | function crypto_onetimeauth(out, outpos, m, mpos, n, k) { 187 | var s, i, j, u; 188 | var x = new Uint32Array(17), r = new Uint32Array(17), 189 | h = new Uint32Array(17), c = new Uint32Array(17), 190 | g = new Uint32Array(17); 191 | for (j = 0; j < 17; j++) r[j]=h[j]=0; 192 | for (j = 0; j < 16; j++) r[j]=k[j]; 193 | r[3]&=15; 194 | r[4]&=252; 195 | r[7]&=15; 196 | r[8]&=252; 197 | r[11]&=15; 198 | r[12]&=252; 199 | r[15]&=15; 200 | 201 | while (n > 0) { 202 | for (j = 0; j < 17; j++) c[j] = 0; 203 | for (j = 0; (j < 16) && (j < n); ++j) c[j] = m[mpos+j]; 204 | c[j] = 1; 205 | mpos += j; n -= j; 206 | add1305(h,c); 207 | for (i = 0; i < 17; i++) { 208 | x[i] = 0; 209 | for (j = 0; j < 17; j++) x[i] = (x[i] + (h[j] * ((j <= i) ? r[i - j] : ((320 * r[i + 17 - j])|0))) | 0) | 0; 210 | } 211 | for (i = 0; i < 17; i++) h[i] = x[i]; 212 | u = 0; 213 | for (j = 0; j < 16; j++) { 214 | u = (u + h[j]) | 0; 215 | h[j] = u & 255; 216 | u >>>= 8; 217 | } 218 | u = (u + h[16]) | 0; h[16] = u & 3; 219 | u = (5 * (u >>> 2)) | 0; 220 | for (j = 0; j < 16; j++) { 221 | u = (u + h[j]) | 0; 222 | h[j] = u & 255; 223 | u >>>= 8; 224 | } 225 | u = (u + h[16]) | 0; h[16] = u; 226 | } 227 | 228 | for (j = 0; j < 17; j++) g[j] = h[j]; 229 | add1305(h,minusp); 230 | s = (-(h[16] >>> 7) | 0); 231 | for (j = 0; j < 17; j++) h[j] ^= s & (g[j] ^ h[j]); 232 | 233 | for (j = 0; j < 16; j++) c[j] = k[j + 16]; 234 | c[16] = 0; 235 | add1305(h,c); 236 | for (j = 0; j < 16; j++) out[outpos+j] = h[j]; 237 | return 0; 238 | } 239 | 240 | function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) { 241 | var x = new Uint8Array(16); 242 | crypto_onetimeauth(x,0,m,mpos,n,k); 243 | return crypto_verify_16(h,hpos,x,0); 244 | } 245 | 246 | function crypto_secretbox(c,m,d,n,k) { 247 | var i; 248 | if (d < 32) return -1; 249 | crypto_stream_xor(c,0,m,0,d,n,k); 250 | crypto_onetimeauth(c, 16, c, 32, d - 32, c); 251 | for (i = 0; i < 16; i++) c[i] = 0; 252 | return 0; 253 | } 254 | 255 | function crypto_secretbox_open(m,c,d,n,k) { 256 | var i; 257 | var x = new Uint8Array(32); 258 | if (d < 32) return -1; 259 | crypto_stream(x,0,32,n,k); 260 | if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1; 261 | crypto_stream_xor(m,0,c,0,d,n,k); 262 | for (i = 0; i < 32; i++) m[i] = 0; 263 | return 0; 264 | } 265 | 266 | function set25519(r, a) { 267 | var i; 268 | for (i = 0; i < 16; i++) r[i] = a[i]|0; 269 | } 270 | 271 | function car25519(o) { 272 | var c; 273 | var i; 274 | for (i = 0; i < 16; i++) { 275 | o[i] += 65536; 276 | c = Math.floor(o[i] / 65536); 277 | o[(i+1)*(i<15?1:0)] += c - 1 + 37 * (c-1) * (i===15?1:0); 278 | o[i] -= (c * 65536); 279 | } 280 | } 281 | 282 | function sel25519(p, q, b) { 283 | var t, c = ~(b-1); 284 | for (var i = 0; i < 16; i++) { 285 | t = c & (p[i] ^ q[i]); 286 | p[i] ^= t; 287 | q[i] ^= t; 288 | } 289 | } 290 | 291 | function pack25519(o, n) { 292 | var i, j, b; 293 | var m = gf(), t = gf(); 294 | for (i = 0; i < 16; i++) t[i] = n[i]; 295 | car25519(t); 296 | car25519(t); 297 | car25519(t); 298 | for (j = 0; j < 2; j++) { 299 | m[0] = t[0] - 0xffed; 300 | for (i = 1; i < 15; i++) { 301 | m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); 302 | m[i-1] &= 0xffff; 303 | } 304 | m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); 305 | b = (m[15]>>16) & 1; 306 | m[14] &= 0xffff; 307 | sel25519(t, m, 1-b); 308 | } 309 | for (i = 0; i < 16; i++) { 310 | o[2*i] = t[i] & 0xff; 311 | o[2*i+1] = t[i]>>8; 312 | } 313 | } 314 | 315 | function neq25519(a, b) { 316 | var c = new Uint8Array(32), d = new Uint8Array(32); 317 | pack25519(c, a); 318 | pack25519(d, b); 319 | return crypto_verify_32(c, 0, d, 0); 320 | } 321 | 322 | function par25519(a) { 323 | var d = new Uint8Array(32); 324 | pack25519(d, a); 325 | return d[0] & 1; 326 | } 327 | 328 | function unpack25519(o, n) { 329 | var i; 330 | for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); 331 | o[15] &= 0x7fff; 332 | } 333 | 334 | function A(o, a, b) { 335 | var i; 336 | for (i = 0; i < 16; i++) o[i] = (a[i] + b[i])|0; 337 | } 338 | 339 | function Z(o, a, b) { 340 | var i; 341 | for (i = 0; i < 16; i++) o[i] = (a[i] - b[i])|0; 342 | } 343 | 344 | function M(o, a, b) { 345 | var i, j, t = new Float64Array(31); 346 | for (i = 0; i < 31; i++) t[i] = 0; 347 | for (i = 0; i < 16; i++) { 348 | for (j = 0; j < 16; j++) { 349 | t[i+j] += a[i] * b[j]; 350 | } 351 | } 352 | for (i = 0; i < 15; i++) { 353 | t[i] += 38 * t[i+16]; 354 | } 355 | for (i = 0; i < 16; i++) o[i] = t[i]; 356 | car25519(o); 357 | car25519(o); 358 | } 359 | 360 | function S(o, a) { 361 | M(o, a, a); 362 | } 363 | 364 | function inv25519(o, i) { 365 | var c = gf(); 366 | var a; 367 | for (a = 0; a < 16; a++) c[a] = i[a]; 368 | for (a = 253; a >= 0; a--) { 369 | S(c, c); 370 | if(a !== 2 && a !== 4) M(c, c, i); 371 | } 372 | for (a = 0; a < 16; a++) o[a] = c[a]; 373 | } 374 | 375 | function pow2523(o, i) { 376 | var c = gf(); 377 | var a; 378 | for (a = 0; a < 16; a++) c[a] = i[a]; 379 | for (a = 250; a >= 0; a--) { 380 | S(c, c); 381 | if(a !== 1) M(c, c, i); 382 | } 383 | for (a = 0; a < 16; a++) o[a] = c[a]; 384 | } 385 | 386 | function crypto_scalarmult(q, n, p) { 387 | var z = new Uint8Array(32); 388 | var x = new Float64Array(80), r, i; 389 | var a = gf(), b = gf(), c = gf(), 390 | d = gf(), e = gf(), f = gf(); 391 | for (i = 0; i < 31; i++) z[i] = n[i]; 392 | z[31]=(n[31]&127)|64; 393 | z[0]&=248; 394 | unpack25519(x,p); 395 | for (i = 0; i < 16; i++) { 396 | b[i]=x[i]; 397 | d[i]=a[i]=c[i]=0; 398 | } 399 | a[0]=d[0]=1; 400 | for (i=254; i>=0; --i) { 401 | r=(z[i>>>3]>>>(i&7))&1; 402 | sel25519(a,b,r); 403 | sel25519(c,d,r); 404 | A(e,a,c); 405 | Z(a,a,c); 406 | A(c,b,d); 407 | Z(b,b,d); 408 | S(d,e); 409 | S(f,a); 410 | M(a,c,a); 411 | M(c,b,e); 412 | A(e,a,c); 413 | Z(a,a,c); 414 | S(b,a); 415 | Z(c,d,f); 416 | M(a,c,_121665); 417 | A(a,a,d); 418 | M(c,c,a); 419 | M(a,d,f); 420 | M(d,b,x); 421 | S(b,e); 422 | sel25519(a,b,r); 423 | sel25519(c,d,r); 424 | } 425 | for (i = 0; i < 16; i++) { 426 | x[i+16]=a[i]; 427 | x[i+32]=c[i]; 428 | x[i+48]=b[i]; 429 | x[i+64]=d[i]; 430 | } 431 | var x32 = x.subarray(32); 432 | var x16 = x.subarray(16); 433 | inv25519(x32,x32); 434 | M(x16,x16,x32); 435 | pack25519(q,x16); 436 | return 0; 437 | } 438 | 439 | function crypto_scalarmult_base(q, n) { 440 | return crypto_scalarmult(q, n, _9); 441 | } 442 | 443 | function crypto_box_keypair(y, x) { 444 | randombytes(x, 32); 445 | return crypto_scalarmult_base(y, x); 446 | } 447 | 448 | function crypto_box_beforenm(k, y, x) { 449 | var s = new Uint8Array(32); 450 | crypto_scalarmult(s, x, y); 451 | return crypto_core_hsalsa20(k, _0, s, sigma); 452 | } 453 | 454 | var crypto_box_afternm = crypto_secretbox; 455 | var crypto_box_open_afternm = crypto_secretbox_open; 456 | 457 | function crypto_box(c, m, d, n, y, x) { 458 | var k = new Uint8Array(32); 459 | crypto_box_beforenm(k, y, x); 460 | return crypto_box_afternm(c, m, d, n, k); 461 | } 462 | 463 | function crypto_box_open(m, c, d, n, y, x) { 464 | var k = new Uint8Array(32); 465 | crypto_box_beforenm(k, y, x); 466 | return crypto_box_open_afternm(m, c, d, n, k); 467 | } 468 | 469 | function add64() { 470 | var a = 0, b = 0, c = 0, d = 0, m16 = 65535, l, h, i; 471 | for (i = 0; i < arguments.length; i++) { 472 | l = arguments[i].lo; 473 | h = arguments[i].hi; 474 | a += (l & m16); b += (l >>> 16); 475 | c += (h & m16); d += (h >>> 16); 476 | } 477 | 478 | b += (a >>> 16); 479 | c += (b >>> 16); 480 | d += (c >>> 16); 481 | 482 | return new u64((c & m16) | (d << 16), (a & m16) | (b << 16)); 483 | } 484 | 485 | function shr64(x, c) { 486 | return new u64((x.hi >>> c), (x.lo >>> c) | (x.hi << (32 - c))); 487 | } 488 | 489 | function xor64() { 490 | var l = 0, h = 0, i; 491 | for (i = 0; i < arguments.length; i++) { 492 | l ^= arguments[i].lo; 493 | h ^= arguments[i].hi; 494 | } 495 | return new u64(h, l); 496 | } 497 | 498 | function R(x, c) { 499 | var h, l, c1 = 32 - c; 500 | if (c < 32) { 501 | h = (x.hi >>> c) | (x.lo << c1); 502 | l = (x.lo >>> c) | (x.hi << c1); 503 | } else if (c < 64) { 504 | h = (x.lo >>> c) | (x.hi << c1); 505 | l = (x.hi >>> c) | (x.lo << c1); 506 | } 507 | return new u64(h, l); 508 | } 509 | 510 | function Ch(x, y, z) { 511 | var h = (x.hi & y.hi) ^ (~x.hi & z.hi), 512 | l = (x.lo & y.lo) ^ (~x.lo & z.lo); 513 | return new u64(h, l); 514 | } 515 | 516 | function Maj(x, y, z) { 517 | var h = (x.hi & y.hi) ^ (x.hi & z.hi) ^ (y.hi & z.hi), 518 | l = (x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo); 519 | return new u64(h, l); 520 | } 521 | 522 | function Sigma0(x) { return xor64(R(x,28), R(x,34), R(x,39)); } 523 | function Sigma1(x) { return xor64(R(x,14), R(x,18), R(x,41)); } 524 | function sigma0(x) { return xor64(R(x, 1), R(x, 8), shr64(x,7)); } 525 | function sigma1(x) { return xor64(R(x,19), R(x,61), shr64(x,6)); } 526 | 527 | var K = [ 528 | new u64(0x428a2f98, 0xd728ae22), new u64(0x71374491, 0x23ef65cd), 529 | new u64(0xb5c0fbcf, 0xec4d3b2f), new u64(0xe9b5dba5, 0x8189dbbc), 530 | new u64(0x3956c25b, 0xf348b538), new u64(0x59f111f1, 0xb605d019), 531 | new u64(0x923f82a4, 0xaf194f9b), new u64(0xab1c5ed5, 0xda6d8118), 532 | new u64(0xd807aa98, 0xa3030242), new u64(0x12835b01, 0x45706fbe), 533 | new u64(0x243185be, 0x4ee4b28c), new u64(0x550c7dc3, 0xd5ffb4e2), 534 | new u64(0x72be5d74, 0xf27b896f), new u64(0x80deb1fe, 0x3b1696b1), 535 | new u64(0x9bdc06a7, 0x25c71235), new u64(0xc19bf174, 0xcf692694), 536 | new u64(0xe49b69c1, 0x9ef14ad2), new u64(0xefbe4786, 0x384f25e3), 537 | new u64(0x0fc19dc6, 0x8b8cd5b5), new u64(0x240ca1cc, 0x77ac9c65), 538 | new u64(0x2de92c6f, 0x592b0275), new u64(0x4a7484aa, 0x6ea6e483), 539 | new u64(0x5cb0a9dc, 0xbd41fbd4), new u64(0x76f988da, 0x831153b5), 540 | new u64(0x983e5152, 0xee66dfab), new u64(0xa831c66d, 0x2db43210), 541 | new u64(0xb00327c8, 0x98fb213f), new u64(0xbf597fc7, 0xbeef0ee4), 542 | new u64(0xc6e00bf3, 0x3da88fc2), new u64(0xd5a79147, 0x930aa725), 543 | new u64(0x06ca6351, 0xe003826f), new u64(0x14292967, 0x0a0e6e70), 544 | new u64(0x27b70a85, 0x46d22ffc), new u64(0x2e1b2138, 0x5c26c926), 545 | new u64(0x4d2c6dfc, 0x5ac42aed), new u64(0x53380d13, 0x9d95b3df), 546 | new u64(0x650a7354, 0x8baf63de), new u64(0x766a0abb, 0x3c77b2a8), 547 | new u64(0x81c2c92e, 0x47edaee6), new u64(0x92722c85, 0x1482353b), 548 | new u64(0xa2bfe8a1, 0x4cf10364), new u64(0xa81a664b, 0xbc423001), 549 | new u64(0xc24b8b70, 0xd0f89791), new u64(0xc76c51a3, 0x0654be30), 550 | new u64(0xd192e819, 0xd6ef5218), new u64(0xd6990624, 0x5565a910), 551 | new u64(0xf40e3585, 0x5771202a), new u64(0x106aa070, 0x32bbd1b8), 552 | new u64(0x19a4c116, 0xb8d2d0c8), new u64(0x1e376c08, 0x5141ab53), 553 | new u64(0x2748774c, 0xdf8eeb99), new u64(0x34b0bcb5, 0xe19b48a8), 554 | new u64(0x391c0cb3, 0xc5c95a63), new u64(0x4ed8aa4a, 0xe3418acb), 555 | new u64(0x5b9cca4f, 0x7763e373), new u64(0x682e6ff3, 0xd6b2b8a3), 556 | new u64(0x748f82ee, 0x5defb2fc), new u64(0x78a5636f, 0x43172f60), 557 | new u64(0x84c87814, 0xa1f0ab72), new u64(0x8cc70208, 0x1a6439ec), 558 | new u64(0x90befffa, 0x23631e28), new u64(0xa4506ceb, 0xde82bde9), 559 | new u64(0xbef9a3f7, 0xb2c67915), new u64(0xc67178f2, 0xe372532b), 560 | new u64(0xca273ece, 0xea26619c), new u64(0xd186b8c7, 0x21c0c207), 561 | new u64(0xeada7dd6, 0xcde0eb1e), new u64(0xf57d4f7f, 0xee6ed178), 562 | new u64(0x06f067aa, 0x72176fba), new u64(0x0a637dc5, 0xa2c898a6), 563 | new u64(0x113f9804, 0xbef90dae), new u64(0x1b710b35, 0x131c471b), 564 | new u64(0x28db77f5, 0x23047d84), new u64(0x32caab7b, 0x40c72493), 565 | new u64(0x3c9ebe0a, 0x15c9bebc), new u64(0x431d67c4, 0x9c100d4c), 566 | new u64(0x4cc5d4be, 0xcb3e42b6), new u64(0x597f299c, 0xfc657e2a), 567 | new u64(0x5fcb6fab, 0x3ad6faec), new u64(0x6c44198c, 0x4a475817) 568 | ]; 569 | 570 | function crypto_hashblocks(x, m, n) { 571 | var z = [], b = [], a = [], w = [], t, i, j; 572 | 573 | for (i = 0; i < 8; i++) z[i] = a[i] = dl64(x, 8*i); 574 | 575 | var pos = 0; 576 | while (n >= 128) { 577 | for (i = 0; i < 16; i++) w[i] = dl64(m, 8*i+pos); 578 | for (i = 0; i < 80; i++) { 579 | for (j = 0; j < 8; j++) b[j] = a[j]; 580 | t = add64(a[7], Sigma1(a[4]), Ch(a[4], a[5], a[6]), K[i], w[i%16]); 581 | b[7] = add64(t, Sigma0(a[0]), Maj(a[0], a[1], a[2])); 582 | b[3] = add64(b[3], t); 583 | for (j = 0; j < 8; j++) a[(j+1)%8] = b[j]; 584 | if (i%16 === 15) { 585 | for (j = 0; j < 16; j++) { 586 | w[j] = add64(w[j], w[(j+9)%16], sigma0(w[(j+1)%16]), sigma1(w[(j+14)%16])); 587 | } 588 | } 589 | } 590 | 591 | for (i = 0; i < 8; i++) { 592 | a[i] = add64(a[i], z[i]); 593 | z[i] = a[i]; 594 | } 595 | 596 | pos += 128; 597 | n -= 128; 598 | } 599 | 600 | for (i = 0; i < 8; i++) ts64(x, 8*i, z[i]); 601 | return n; 602 | } 603 | 604 | var iv = new Uint8Array([ 605 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, 606 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, 607 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, 608 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, 609 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, 610 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, 611 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, 612 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 613 | ]); 614 | 615 | function crypto_hash(out, m, n) { 616 | var h = new Uint8Array(64), x = new Uint8Array(256); 617 | var i, b = n; 618 | 619 | for (i = 0; i < 64; i++) h[i] = iv[i]; 620 | 621 | crypto_hashblocks(h, m, n); 622 | n %= 128; 623 | 624 | for (i = 0; i < 256; i++) x[i] = 0; 625 | for (i = 0; i < n; i++) x[i] = m[b-n+i]; 626 | x[n] = 128; 627 | 628 | n = 256-128*(n<112?1:0); 629 | x[n-9] = 0; 630 | ts64(x, n-8, new u64((b / 0x20000000) | 0, b << 3)); 631 | crypto_hashblocks(h, x, n); 632 | 633 | for (i = 0; i < 64; i++) out[i] = h[i]; 634 | 635 | return 0; 636 | } 637 | 638 | function add(p, q) { 639 | var a = gf(), b = gf(), c = gf(), 640 | d = gf(), e = gf(), f = gf(), 641 | g = gf(), h = gf(), t = gf(); 642 | 643 | Z(a, p[1], p[0]); 644 | Z(t, q[1], q[0]); 645 | M(a, a, t); 646 | A(b, p[0], p[1]); 647 | A(t, q[0], q[1]); 648 | M(b, b, t); 649 | M(c, p[3], q[3]); 650 | M(c, c, D2); 651 | M(d, p[2], q[2]); 652 | A(d, d, d); 653 | Z(e, b, a); 654 | Z(f, d, c); 655 | A(g, d, c); 656 | A(h, b, a); 657 | 658 | M(p[0], e, f); 659 | M(p[1], h, g); 660 | M(p[2], g, f); 661 | M(p[3], e, h); 662 | } 663 | 664 | function cswap(p, q, b) { 665 | var i; 666 | for (i = 0; i < 4; i++) { 667 | sel25519(p[i], q[i], b); 668 | } 669 | } 670 | 671 | function pack(r, p) { 672 | var tx = gf(), ty = gf(), zi = gf(); 673 | inv25519(zi, p[2]); 674 | M(tx, p[0], zi); 675 | M(ty, p[1], zi); 676 | pack25519(r, ty); 677 | r[31] ^= par25519(tx) << 7; 678 | } 679 | 680 | function scalarmult(p, q, s) { 681 | var b, i; 682 | set25519(p[0], gf0); 683 | set25519(p[1], gf1); 684 | set25519(p[2], gf1); 685 | set25519(p[3], gf0); 686 | for (i = 255; i >= 0; --i) { 687 | b = (s[(i/8)|0] >> (i&7)) & 1; 688 | cswap(p, q, b); 689 | add(q, p); 690 | add(p, p); 691 | cswap(p, q, b); 692 | } 693 | } 694 | 695 | function scalarbase(p, s) { 696 | var q = [gf(), gf(), gf(), gf()]; 697 | set25519(q[0], X); 698 | set25519(q[1], Y); 699 | set25519(q[2], gf1); 700 | M(q[3], X, Y); 701 | scalarmult(p, q, s); 702 | } 703 | 704 | function crypto_sign_keypair(pk, sk, seeded) { 705 | var d = new Uint8Array(64); 706 | var p = [gf(), gf(), gf(), gf()]; 707 | var i; 708 | 709 | if (!seeded) randombytes(sk, 32); 710 | crypto_hash(d, sk, 32); 711 | d[0] &= 248; 712 | d[31] &= 127; 713 | d[31] |= 64; 714 | 715 | scalarbase(p, d); 716 | pack(pk, p); 717 | 718 | for (i = 0; i < 32; i++) sk[i+32] = pk[i]; 719 | return 0; 720 | } 721 | 722 | var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); 723 | 724 | function modL(r, x) { 725 | var carry, i, j, k; 726 | for (i = 63; i >= 32; --i) { 727 | carry = 0; 728 | for (j = i - 32, k = i - 12; j < k; ++j) { 729 | x[j] += carry - 16 * x[i] * L[j - (i - 32)]; 730 | carry = Math.floor((x[j] + 128) / 256); 731 | x[j] -= carry * 256; 732 | } 733 | x[j] += carry; 734 | x[i] = 0; 735 | } 736 | carry = 0; 737 | for (j = 0; j < 32; j++) { 738 | x[j] += carry - (x[31] >> 4) * L[j]; 739 | carry = x[j] >> 8; 740 | x[j] &= 255; 741 | } 742 | for (j = 0; j < 32; j++) x[j] -= carry * L[j]; 743 | for (i = 0; i < 32; i++) { 744 | x[i+1] += x[i] >> 8; 745 | r[i] = x[i] & 255; 746 | } 747 | } 748 | 749 | function reduce(r) { 750 | var x = new Float64Array(64), i; 751 | for (i = 0; i < 64; i++) x[i] = r[i]; 752 | for (i = 0; i < 64; i++) r[i] = 0; 753 | modL(r, x); 754 | } 755 | 756 | // Note: difference from C - smlen returned, not passed as argument. 757 | function crypto_sign(sm, m, n, sk) { 758 | var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64); 759 | var i, j, x = new Float64Array(64); 760 | var p = [gf(), gf(), gf(), gf()]; 761 | 762 | crypto_hash(d, sk, 32); 763 | d[0] &= 248; 764 | d[31] &= 127; 765 | d[31] |= 64; 766 | 767 | var smlen = n + 64; 768 | for (i = 0; i < n; i++) sm[64 + i] = m[i]; 769 | for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; 770 | 771 | crypto_hash(r, sm.subarray(32), n+32); 772 | reduce(r); 773 | scalarbase(p, r); 774 | pack(sm, p); 775 | 776 | for (i = 32; i < 64; i++) sm[i] = sk[i]; 777 | crypto_hash(h, sm, n + 64); 778 | reduce(h); 779 | 780 | for (i = 0; i < 64; i++) x[i] = 0; 781 | for (i = 0; i < 32; i++) x[i] = r[i]; 782 | for (i = 0; i < 32; i++) { 783 | for (j = 0; j < 32; j++) { 784 | x[i+j] += h[i] * d[j]; 785 | } 786 | } 787 | 788 | modL(sm.subarray(32), x); 789 | return smlen; 790 | } 791 | 792 | function unpackneg(r, p) { 793 | var t = gf(), chk = gf(), num = gf(), 794 | den = gf(), den2 = gf(), den4 = gf(), 795 | den6 = gf(); 796 | 797 | set25519(r[2], gf1); 798 | unpack25519(r[1], p); 799 | S(num, r[1]); 800 | M(den, num, D); 801 | Z(num, num, r[2]); 802 | A(den, r[2], den); 803 | 804 | S(den2, den); 805 | S(den4, den2); 806 | M(den6, den4, den2); 807 | M(t, den6, num); 808 | M(t, t, den); 809 | 810 | pow2523(t, t); 811 | M(t, t, num); 812 | M(t, t, den); 813 | M(t, t, den); 814 | M(r[0], t, den); 815 | 816 | S(chk, r[0]); 817 | M(chk, chk, den); 818 | if (neq25519(chk, num)) M(r[0], r[0], I); 819 | 820 | S(chk, r[0]); 821 | M(chk, chk, den); 822 | if (neq25519(chk, num)) return -1; 823 | 824 | if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); 825 | 826 | M(r[3], r[0], r[1]); 827 | return 0; 828 | } 829 | 830 | function crypto_sign_open(m, sm, n, pk) { 831 | var i; 832 | var t = new Uint8Array(32), h = new Uint8Array(64); 833 | var p = [gf(), gf(), gf(), gf()], 834 | q = [gf(), gf(), gf(), gf()]; 835 | 836 | if (n < 64) return -1; 837 | 838 | if (unpackneg(q, pk)) return -1; 839 | 840 | for (i = 0; i < n; i++) m[i] = sm[i]; 841 | for (i = 0; i < 32; i++) m[i+32] = pk[i]; 842 | crypto_hash(h, m, n); 843 | reduce(h); 844 | scalarmult(p, q, h); 845 | 846 | scalarbase(q, sm.subarray(32)); 847 | add(p, q); 848 | pack(t, p); 849 | 850 | n -= 64; 851 | if (crypto_verify_32(sm, 0, t, 0)) { 852 | for (i = 0; i < n; i++) m[i] = 0; 853 | return -1; 854 | } 855 | 856 | for (i = 0; i < n; i++) m[i] = sm[i + 64]; 857 | return n; 858 | } 859 | 860 | var crypto_secretbox_KEYBYTES = 32, 861 | crypto_secretbox_NONCEBYTES = 24, 862 | crypto_secretbox_ZEROBYTES = 32, 863 | crypto_secretbox_BOXZEROBYTES = 16, 864 | crypto_scalarmult_BYTES = 32, 865 | crypto_scalarmult_SCALARBYTES = 32, 866 | crypto_box_PUBLICKEYBYTES = 32, 867 | crypto_box_SECRETKEYBYTES = 32, 868 | crypto_box_BEFORENMBYTES = 32, 869 | crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, 870 | crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, 871 | crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, 872 | crypto_sign_BYTES = 64, 873 | crypto_sign_PUBLICKEYBYTES = 32, 874 | crypto_sign_SECRETKEYBYTES = 64, 875 | crypto_sign_SEEDBYTES = 32, 876 | crypto_hash_BYTES = 64; 877 | 878 | nacl.lowlevel = { 879 | crypto_core_hsalsa20: crypto_core_hsalsa20, 880 | crypto_stream_xor: crypto_stream_xor, 881 | crypto_stream: crypto_stream, 882 | crypto_stream_salsa20_xor: crypto_stream_salsa20_xor, 883 | crypto_stream_salsa20: crypto_stream_salsa20, 884 | crypto_onetimeauth: crypto_onetimeauth, 885 | crypto_onetimeauth_verify: crypto_onetimeauth_verify, 886 | crypto_verify_16: crypto_verify_16, 887 | crypto_verify_32: crypto_verify_32, 888 | crypto_secretbox: crypto_secretbox, 889 | crypto_secretbox_open: crypto_secretbox_open, 890 | crypto_scalarmult: crypto_scalarmult, 891 | crypto_scalarmult_base: crypto_scalarmult_base, 892 | crypto_box_beforenm: crypto_box_beforenm, 893 | crypto_box_afternm: crypto_box_afternm, 894 | crypto_box: crypto_box, 895 | crypto_box_open: crypto_box_open, 896 | crypto_box_keypair: crypto_box_keypair, 897 | crypto_hash: crypto_hash, 898 | crypto_sign: crypto_sign, 899 | crypto_sign_keypair: crypto_sign_keypair, 900 | crypto_sign_open: crypto_sign_open, 901 | 902 | crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES, 903 | crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES, 904 | crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES, 905 | crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES, 906 | crypto_scalarmult_BYTES: crypto_scalarmult_BYTES, 907 | crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES, 908 | crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES, 909 | crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES, 910 | crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES, 911 | crypto_box_NONCEBYTES: crypto_box_NONCEBYTES, 912 | crypto_box_ZEROBYTES: crypto_box_ZEROBYTES, 913 | crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES, 914 | crypto_sign_BYTES: crypto_sign_BYTES, 915 | crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, 916 | crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, 917 | crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, 918 | crypto_hash_BYTES: crypto_hash_BYTES, 919 | 920 | gf: gf, 921 | D: D, 922 | L: L, 923 | pack25519: pack25519, 924 | unpack25519: unpack25519, 925 | M: M, 926 | A: A, 927 | S: S, 928 | Z: Z, 929 | pow2523: pow2523, 930 | add: add, 931 | set25519: set25519, 932 | modL: modL, 933 | scalarmult: scalarmult, 934 | scalarbase: scalarbase, 935 | }; 936 | 937 | /* High-level API */ 938 | 939 | function checkLengths(k, n) { 940 | if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size'); 941 | if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size'); 942 | } 943 | 944 | function checkBoxLengths(pk, sk) { 945 | if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size'); 946 | if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); 947 | } 948 | 949 | function checkArrayTypes() { 950 | for (var i = 0; i < arguments.length; i++) { 951 | if (!(arguments[i] instanceof Uint8Array)) 952 | throw new TypeError('unexpected type, use Uint8Array'); 953 | } 954 | } 955 | 956 | function cleanup(arr) { 957 | for (var i = 0; i < arr.length; i++) arr[i] = 0; 958 | } 959 | 960 | nacl.randomBytes = function(n) { 961 | var b = new Uint8Array(n); 962 | randombytes(b, n); 963 | return b; 964 | }; 965 | 966 | nacl.secretbox = function(msg, nonce, key) { 967 | checkArrayTypes(msg, nonce, key); 968 | checkLengths(key, nonce); 969 | var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); 970 | var c = new Uint8Array(m.length); 971 | for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; 972 | crypto_secretbox(c, m, m.length, nonce, key); 973 | return c.subarray(crypto_secretbox_BOXZEROBYTES); 974 | }; 975 | 976 | nacl.secretbox.open = function(box, nonce, key) { 977 | checkArrayTypes(box, nonce, key); 978 | checkLengths(key, nonce); 979 | var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); 980 | var m = new Uint8Array(c.length); 981 | for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; 982 | if (c.length < 32) return null; 983 | if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null; 984 | return m.subarray(crypto_secretbox_ZEROBYTES); 985 | }; 986 | 987 | nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES; 988 | nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES; 989 | nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES; 990 | 991 | nacl.scalarMult = function(n, p) { 992 | checkArrayTypes(n, p); 993 | if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); 994 | if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); 995 | var q = new Uint8Array(crypto_scalarmult_BYTES); 996 | crypto_scalarmult(q, n, p); 997 | return q; 998 | }; 999 | 1000 | nacl.scalarMult.base = function(n) { 1001 | checkArrayTypes(n); 1002 | if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); 1003 | var q = new Uint8Array(crypto_scalarmult_BYTES); 1004 | crypto_scalarmult_base(q, n); 1005 | return q; 1006 | }; 1007 | 1008 | nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; 1009 | nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES; 1010 | 1011 | nacl.box = function(msg, nonce, publicKey, secretKey) { 1012 | var k = nacl.box.before(publicKey, secretKey); 1013 | return nacl.secretbox(msg, nonce, k); 1014 | }; 1015 | 1016 | nacl.box.before = function(publicKey, secretKey) { 1017 | checkArrayTypes(publicKey, secretKey); 1018 | checkBoxLengths(publicKey, secretKey); 1019 | var k = new Uint8Array(crypto_box_BEFORENMBYTES); 1020 | crypto_box_beforenm(k, publicKey, secretKey); 1021 | return k; 1022 | }; 1023 | 1024 | nacl.box.after = nacl.secretbox; 1025 | 1026 | nacl.box.open = function(msg, nonce, publicKey, secretKey) { 1027 | var k = nacl.box.before(publicKey, secretKey); 1028 | return nacl.secretbox.open(msg, nonce, k); 1029 | }; 1030 | 1031 | nacl.box.open.after = nacl.secretbox.open; 1032 | 1033 | nacl.box.keyPair = function() { 1034 | var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); 1035 | var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); 1036 | crypto_box_keypair(pk, sk); 1037 | return {publicKey: pk, secretKey: sk}; 1038 | }; 1039 | 1040 | nacl.box.keyPair.fromSecretKey = function(secretKey) { 1041 | checkArrayTypes(secretKey); 1042 | if (secretKey.length !== crypto_box_SECRETKEYBYTES) 1043 | throw new Error('bad secret key size'); 1044 | var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); 1045 | crypto_scalarmult_base(pk, secretKey); 1046 | return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; 1047 | }; 1048 | 1049 | nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES; 1050 | nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES; 1051 | nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES; 1052 | nacl.box.nonceLength = crypto_box_NONCEBYTES; 1053 | nacl.box.overheadLength = nacl.secretbox.overheadLength; 1054 | 1055 | nacl.sign = function(msg, secretKey) { 1056 | checkArrayTypes(msg, secretKey); 1057 | if (secretKey.length !== crypto_sign_SECRETKEYBYTES) 1058 | throw new Error('bad secret key size'); 1059 | var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); 1060 | crypto_sign(signedMsg, msg, msg.length, secretKey); 1061 | return signedMsg; 1062 | }; 1063 | 1064 | nacl.sign.open = function(signedMsg, publicKey) { 1065 | checkArrayTypes(signedMsg, publicKey); 1066 | if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) 1067 | throw new Error('bad public key size'); 1068 | var tmp = new Uint8Array(signedMsg.length); 1069 | var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey); 1070 | if (mlen < 0) return null; 1071 | var m = new Uint8Array(mlen); 1072 | for (var i = 0; i < m.length; i++) m[i] = tmp[i]; 1073 | return m; 1074 | }; 1075 | 1076 | nacl.sign.detached = function(msg, secretKey) { 1077 | var signedMsg = nacl.sign(msg, secretKey); 1078 | var sig = new Uint8Array(crypto_sign_BYTES); 1079 | for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; 1080 | return sig; 1081 | }; 1082 | 1083 | nacl.sign.detached.verify = function(msg, sig, publicKey) { 1084 | checkArrayTypes(msg, sig, publicKey); 1085 | if (sig.length !== crypto_sign_BYTES) 1086 | throw new Error('bad signature size'); 1087 | if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) 1088 | throw new Error('bad public key size'); 1089 | var sm = new Uint8Array(crypto_sign_BYTES + msg.length); 1090 | var m = new Uint8Array(crypto_sign_BYTES + msg.length); 1091 | var i; 1092 | for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; 1093 | for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; 1094 | return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); 1095 | }; 1096 | 1097 | nacl.sign.keyPair = function() { 1098 | var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); 1099 | var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); 1100 | crypto_sign_keypair(pk, sk); 1101 | return {publicKey: pk, secretKey: sk}; 1102 | }; 1103 | 1104 | nacl.sign.keyPair.fromSecretKey = function(secretKey) { 1105 | checkArrayTypes(secretKey); 1106 | if (secretKey.length !== crypto_sign_SECRETKEYBYTES) 1107 | throw new Error('bad secret key size'); 1108 | var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); 1109 | for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; 1110 | return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; 1111 | }; 1112 | 1113 | nacl.sign.keyPair.fromSeed = function(seed) { 1114 | checkArrayTypes(seed); 1115 | if (seed.length !== crypto_sign_SEEDBYTES) 1116 | throw new Error('bad seed size'); 1117 | var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); 1118 | var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); 1119 | for (var i = 0; i < 32; i++) sk[i] = seed[i]; 1120 | crypto_sign_keypair(pk, sk, true); 1121 | return {publicKey: pk, secretKey: sk}; 1122 | }; 1123 | 1124 | nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES; 1125 | nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES; 1126 | nacl.sign.seedLength = crypto_sign_SEEDBYTES; 1127 | nacl.sign.signatureLength = crypto_sign_BYTES; 1128 | 1129 | nacl.hash = function(msg) { 1130 | checkArrayTypes(msg); 1131 | var h = new Uint8Array(crypto_hash_BYTES); 1132 | crypto_hash(h, msg, msg.length); 1133 | return h; 1134 | }; 1135 | 1136 | nacl.hash.hashLength = crypto_hash_BYTES; 1137 | 1138 | nacl.verify = function(x, y) { 1139 | checkArrayTypes(x, y); 1140 | // Zero length arguments are considered not equal. 1141 | if (x.length === 0 || y.length === 0) return false; 1142 | if (x.length !== y.length) return false; 1143 | return (vn(x, 0, y, 0, x.length) === 0) ? true : false; 1144 | }; 1145 | 1146 | nacl.setPRNG = function(fn) { 1147 | randombytes = fn; 1148 | }; 1149 | 1150 | (function() { 1151 | // Initialize PRNG if environment provides CSPRNG. 1152 | // If not, methods calling randombytes will throw. 1153 | var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; 1154 | if (crypto && crypto.getRandomValues) { 1155 | // Browsers. 1156 | var QUOTA = 65536; 1157 | nacl.setPRNG(function(x, n) { 1158 | var i, v = new Uint8Array(n); 1159 | for (i = 0; i < n; i += QUOTA) { 1160 | crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); 1161 | } 1162 | for (i = 0; i < n; i++) x[i] = v[i]; 1163 | cleanup(v); 1164 | }); 1165 | } else if (typeof require !== 'undefined') { 1166 | // Node.js. 1167 | crypto = require('crypto'); 1168 | if (crypto && crypto.randomBytes) { 1169 | nacl.setPRNG(function(x, n) { 1170 | var i, v = crypto.randomBytes(n); 1171 | for (i = 0; i < n; i++) x[i] = v[i]; 1172 | cleanup(v); 1173 | }); 1174 | } 1175 | } 1176 | })(); 1177 | 1178 | })(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); 1179 | --------------------------------------------------------------------------------