Created
June 11, 2020 16:13
-
-
Save lithdew/074cef3f294d7fb167f333ddc90c19c8 to your computer and use it in GitHub Desktop.
Monte.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/hex" | |
"fmt" | |
"github.com/lithdew/monte" | |
"net" | |
) | |
func main() { | |
check := func(err error) { | |
if err != nil { | |
panic(err) | |
} | |
} | |
ln, err := net.Listen("tcp", ":4444") | |
check(err) | |
defer ln.Close() | |
conn, err := ln.Accept() | |
check(err) | |
defer conn.Close() | |
sess, err := monte.NewSession() | |
check(err) | |
check(sess.DoServer(conn)) | |
fmt.Println(hex.EncodeToString(sess.SharedKey())) | |
sc := monte.NewSessionConn(sess.Suite(), conn) | |
buf := make([]byte, 1024) | |
for i := 0; i < 100; i++ { | |
n, err := sc.Read(buf) | |
check(err) | |
fmt.Println("Decrypted:", string(buf[:n])) | |
} | |
for i := 0; i < 100; i++ { | |
_, err = sc.Write([]byte(fmt.Sprintf("[%d] Hello from Go!", i))) | |
check(err) | |
check(sc.Flush()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import nacl from "tweetnacl"; | |
import * as net from "net"; | |
import blake2b from 'blake2b'; | |
import * as crypto from "crypto"; | |
const sized = buf => { | |
const scratch = Buffer.alloc(4); | |
scratch.writeUInt32BE(buf.byteLength); | |
return Buffer.concat([scratch, buf]); | |
} | |
let readNonce = 0n; | |
let writeNonce = 0n; | |
/** | |
* | |
* @param {crypto.BinaryLike} key | |
* @param {crypto.BinaryLike} buf | |
* @returns {Buffer} | |
*/ | |
const encrypt = (key, buf) => { | |
const nonce = Buffer.alloc(12); | |
nonce.writeBigUInt64BE(writeNonce); | |
writeNonce++ | |
const cipher = crypto.createCipheriv("aes-256-gcm", key, nonce, {authTagLength: 16}); | |
const encrypted = cipher.update(buf); | |
cipher.final(); | |
return Buffer.concat([encrypted, cipher.getAuthTag()]); | |
} | |
/** | |
* | |
* @param {crypto.BinaryLike} key | |
* @param {crypto.BinaryLike} buf | |
* @returns {Buffer} | |
*/ | |
const decrypt = (key, buf) => { | |
if (buf.byteLength < 16) { | |
throw new Error("Data to be decrypted must be at least 16 bytes."); | |
} | |
const nonce = Buffer.alloc(12); | |
nonce.writeBigUInt64BE(readNonce); | |
readNonce++ | |
const decipher = crypto.createDecipheriv("aes-256-gcm", key, nonce, {authTagLength: 16}); | |
decipher.setAuthTag(buf.slice(buf.byteLength - 16, buf.byteLength)); | |
const decrypted = decipher.update(buf.slice(0, buf.byteLength - 16)); | |
decipher.final(); | |
return decrypted; | |
} | |
/** | |
* | |
* @param {Socket} sock | |
* @return {Promise<crypto.BinaryLike>} | |
*/ | |
const handshake = (sock) => new Promise((resolve, _) => { | |
const {publicKey, secretKey} = nacl.box.keyPair(); | |
sock.write(publicKey); | |
sock.once('readable', () => { | |
const otherPublicKey = sock.read(32); | |
if (!otherPublicKey) sock.destroy(new Error("Peer did not provide a X25519 key to init the session.")); | |
resolve(Buffer.from(blake2b(32).update(nacl.scalarMult(secretKey, otherPublicKey)).digest())); | |
}); | |
}); | |
/** | |
* | |
* @param {Socket} sock | |
* @return {Promise<Buffer>} | |
*/ | |
const read = sock => new Promise((resolve, _) => { | |
sock.once('readable', () => { | |
const header = sock.read(4); | |
if (!header) return; | |
const length = header.readUInt32BE(); | |
let frame = sock.read(length); | |
if (!frame) { | |
sock.unshift(header); | |
return; | |
} | |
resolve(frame); | |
}); | |
}); | |
async function main() { | |
const sock = new net.Socket(); | |
sock.connect({port: 4444, host: "127.0.0.1"}); | |
const sessionKey = await handshake(sock); | |
console.log("Session Key:", sessionKey.toString("hex")); | |
for (let i = 0; i < 100; i++) { | |
sock.write(sized(encrypt(sessionKey, `[${i}] Hello from NodeJS!`))); | |
} | |
for (let i = 0; i < 100; i++) { | |
console.log("Decrypted:", decrypt(sessionKey, await read(sock)).toString("utf8")); | |
} | |
} | |
main().catch(err => console.error(err)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment