1
0
Fork 0
mirror of https://git.sr.ht/~noisytoot/randomsync synced 2025-04-01 06:00:53 +01:00

Add support for authenticated control commands

This commit is contained in:
Ron Nazarov 2021-11-02 03:42:35 +00:00
parent 6fce1c32e4
commit b534e18447
Signed by: noisytoot
GPG key ID: 1D43EF4F4492268B
3 changed files with 87 additions and 3 deletions

22
keygen.js Normal file
View file

@ -0,0 +1,22 @@
// -*- mode: javascript; indent-tabs-mode: nil -*-
// Copyright (C) 2021 Noisytoot
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const ed25519 = require('ed25519')
const crypto = require('crypto')
let keypair = ed25519.MakeKeypair(crypto.randomBytes(32))
console.log('private key: ' + keypair.privateKey.toString('base64'))
console.log('public key: ' + keypair.publicKey.toString('base64'))

View file

@ -16,6 +16,7 @@
const fs = require('fs')
const irc = require('irc-framework')
const ed25519 = require('ed25519')
const random = fs.openSync('/dev/urandom', 'r+')
function getRandom(bytes) {
@ -46,14 +47,20 @@ const config = JSON.parse(fs.readFileSync('./config.json', 'utf8')),
LEADER_PROBABLILITY = config['leader-probability'] || 0.75,
PASSWORD = config.password,
SASL_USERNAME = config['sasl-username'],
SASL_PASSWORD = config['sasl-password']
SASL_PASSWORD = config['sasl-password'],
CONTROL_ID = config['control-id']
let SASL_MECHANISM = config['sasl-mechanism']
let SASL_MECHANISM = config['sasl-mechanism'],
CONTROL_KEY = config['control-key']
// Make SASL_MECHANISM uppercase if defined
if (SASL_MECHANISM)
SASL_MECHANISM = SASL_MECHANISM.toUpperCase()
// Decode control key if defined
if (CONTROL_KEY)
CONTROL_KEY = Buffer.from(CONTROL_KEY, 'base64')
let key, cert
if (TLS_KEY && TLS_CERT) {
key = fs.readFileSync(TLS_KEY, 'utf8')
@ -61,7 +68,8 @@ if (TLS_KEY && TLS_CERT) {
}
let lastSync = 0,
syncLeader = false
syncLeader = false,
otps = new Set()
let client = new irc.Client({
nick: NICK,
@ -97,6 +105,36 @@ client.on('registered', event => {
client.on('privmsg', msg => {
if (CHANNELS.includes(msg.target)) {
putRandom(msg.message)
if (msg.message.includes('$RANDSYNC-OTP$ ' + CONTROL_ID || client.user.nick)) {
let otp = getRandom(32).toString('base64')
otps.add(otp)
client.say(msg.target, otp)
}
if (msg.message.includes('$RANDSYNC-CONTROL$ ' + CONTROL_ID || client.user.nick)
&& CONTROL_KEY) {
let args = msg.message.split(' ')
args = args.slice(args.indexOf('$RANDSYNC-CONTROL$') + 2)
if (args.length >= 3) {
let signature = Buffer.from(args[0], 'base64')
let otp = args[1]
if (signature.length == 64
&& ed25519.Verify(Buffer.from(args.slice(1).join(' '), 'utf8'), signature, CONTROL_KEY)
&& otps.has(otp)) {
args = args.slice(2)
otps.delete(otp)
switch (args[0]) {
case "OTPS":
client.say(msg.target, Array.from(otps).join(' '))
break
case "CLEAROTPS":
otps = new Set()
break
}
} else {
client.say(msg.target, 'Invalid signature or OTP')
}
}
}
if (msg.message.includes('$RANDSYNCv2$')) {
let args = msg.message.split(' ')
args = args.slice(args.indexOf('$RANDSYNCv2$') + 1)

24
sign.js Normal file
View file

@ -0,0 +1,24 @@
// -*- mode: javascript; indent-tabs-mode: nil -*-
// Copyright (C) 2021 Noisytoot
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const fs = require('fs')
const ed25519 = require('ed25519')
let privatekey = Buffer.from(fs.readFileSync(process.argv[2]).toString('utf8'), 'base64')
process.stdin.on('data', function (data) {
console.log(ed25519.Sign(Buffer.from(data, 'utf8'), privatekey).toString('base64') + ' ' + data)
})