auth utils, log setup

This commit is contained in:
Evan Feenstra
2022-06-10 12:39:07 -07:00
parent 8946a4cd8f
commit 770c474ea1
3 changed files with 111 additions and 12 deletions

View File

@@ -8,6 +8,7 @@ edition = "2018"
secp256k1 = { version = "0.22.0", default-features = false, features = ["std", "rand-std", "bitcoin_hashes"] }
anyhow = {version = "1", features = ["backtrace"]}
log = "0.4"
base64 = { version = "0.13.0" }
[features]
default = [ "no-std", "secp-recovery", "secp-lowmemory" ]

View File

@@ -1,31 +1,102 @@
use anyhow::anyhow;
use anyhow::Result;
use base64::{decode_config, encode_config, URL_SAFE};
use secp256k1::ecdsa::Signature;
use secp256k1::hashes::sha256d::Hash as Sha256dHash;
use secp256k1::hashes::Hash;
use secp256k1::{Message, Secp256k1, SecretKey};
use secp256k1::{Message, PublicKey, Secp256k1, SecretKey};
use std::convert::TryInto;
pub struct Token(u64);
fn now() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
since_the_epoch.as_nanos() as u64
}
pub fn u64_to_bytes(input: u64) -> [u8; 8] {
input.to_le_bytes()
}
pub fn bytes_to_u64(bytes: [u8; 8]) -> u64 {
u64::from_le_bytes(bytes)
}
pub fn base64_encode(input: &Vec<u8>) -> String {
encode_config(input, URL_SAFE)
}
pub fn base64_decode(input: &str) -> Result<Vec<u8>> {
let r = decode_config(input, URL_SAFE)?;
Ok(r)
}
impl Token {
pub fn new() -> Self {
Self(0)
Self(now())
}
pub fn from_bytes(bytes: [u8; 8]) -> Self {
Self(bytes_to_u64(bytes))
}
pub fn from_base64(s: &str) -> Result<Self> {
if s.len() < 8 {
return Err(anyhow!("too short slice".to_string()));
}
let bytes = base64_decode(s)?;
let ts: [u8; 8] = bytes[..8].try_into()?;
Ok(Self(bytes_to_u64(ts)))
}
pub fn expected_len(&self) -> usize {
73
}
pub fn sign(&self, secret_key: &SecretKey) -> Result<Vec<u8>> {
let mut ts = u64_to_bytes(self.0).to_vec();
let sig = self.sign_message(&ts, secret_key)?;
println!("tts {:?}", ts);
ts.extend(sig);
assert_eq!(ts.len(), self.expected_len());
Ok(ts)
}
pub fn verify(&self, sig: Vec<u8>, public_key: &PublicKey) -> Result<()> {
// remove ts
// let (msg, sig) = input.split_at(8);
let msg = u64_to_bytes(self.0);
self.verify_message(&msg.to_vec(), &sig.to_vec(), public_key)
}
/// Sign a Lightning message
pub fn sign_message(
&self,
message: &Vec<u8>,
secret_key: &SecretKey,
) -> anyhow::Result<Vec<u8>> {
let mut buffer = String::from("Lightning Signed Message:").into_bytes();
buffer.extend(message);
pub fn sign_message(&self, message: &Vec<u8>, secret_key: &SecretKey) -> Result<Vec<u8>> {
let encmsg = self.lightning_hash(message)?;
let secp_ctx = Secp256k1::signing_only();
let hash = Sha256dHash::hash(&buffer);
let encmsg = secp256k1::Message::from_slice(&hash[..])?;
let sig = secp_ctx.sign_ecdsa_recoverable(&encmsg, &secret_key);
let (rid, sig) = sig.serialize_compact();
let mut res = sig.to_vec();
res.push(rid.to_i32() as u8);
Ok(res)
}
/// Verify a Lightning message
pub fn verify_message(
&self,
message: &Vec<u8>,
sig: &Vec<u8>,
public_key: &PublicKey,
) -> Result<()> {
let secp_ctx = Secp256k1::verification_only();
let encmsg = self.lightning_hash(message)?;
// remove the rid
let s = Signature::from_compact(&sig[..64])?;
secp_ctx.verify_ecdsa(&encmsg, &s, public_key)?;
Ok(())
}
/// hash lightning message
pub fn lightning_hash(&self, message: &Vec<u8>) -> Result<Message> {
let mut buffer = String::from("Lightning Signed Message:").into_bytes();
buffer.extend(message);
let hash = Sha256dHash::hash(&buffer);
let encmsg = secp256k1::Message::from_slice(&hash[..])?;
Ok(encmsg)
}
}
pub fn sign<T: secp256k1::Signing>(
@@ -61,4 +132,30 @@ mod tests {
let sig = sign(&secp, vec![1, 2, 3], &sk);
assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok());
}
#[test]
fn test_token() {
let sk = secret_key();
let t = Token::new();
let res = t.sign(&sk).expect("couldnt make token");
let secp = Secp256k1::new();
let public_key = PublicKey::from_secret_key(&secp, &sk);
let (_, sig) = res.split_at(8);
t.verify(sig.to_vec(), &public_key).expect("couldnt verify");
println!("token verified!");
}
#[test]
fn test_decode() {
let sk = secret_key();
let secp = Secp256k1::new();
let public_key = PublicKey::from_secret_key(&secp, &sk);
let s = "aHt45kxY9xZCMvT5du5mTw-jx3X2g0Eg7QhHTIi6rBRAFqY_syx1SzcSoriXyPIVCWdG6T0I8xKXSEnoeajFdwmtQbHqC_qfAQ==";
let v = base64_decode(s).expect("couldnt decode");
let (_, sig) = v.split_at(8);
let t = Token::from_base64(s).expect("couldnt parse base64");
t.verify(sig.to_vec(), &public_key)
.expect("failed to verify");
println!("decoded token verified!");
}
}

View File

@@ -11,6 +11,7 @@ use std::env;
use tokio::sync::{mpsc, oneshot};
use vls_proxy::client::UnixClient;
use vls_proxy::connection::{open_parent_fd, UnixConnection};
use vls_proxy::util::setup_logging;
pub struct Channel {
pub sequence: u16,
@@ -33,7 +34,7 @@ pub struct ChannelReply {
fn main() -> anyhow::Result<()> {
let parent_fd = open_parent_fd();
util::setup_logging("hsmd ", "info");
setup_logging("hsmd ", "info");
let app = App::new("signer")
.setting(AppSettings::NoAutoVersion)
.about("CLN:mqtt - connects to an embedded VLS over a MQTT connection")