sphinx_auther/
lib.rs

1pub mod nonce;
2pub mod token;
3
4pub use secp256k1;
5
6use anyhow::{anyhow, Result};
7use secp256k1::ecdsa::{self, Signature};
8use secp256k1::hashes::sha256::Hash as Sha256Hash;
9use secp256k1::hashes::Hash;
10use secp256k1::{Message, PublicKey, Secp256k1, SecretKey};
11
12// 27 + 4 for compressed
13const MAGIC_NUMBER: i32 = 31;
14
15pub fn sign_message(message: &[u8], secret_key: &SecretKey) -> Result<Vec<u8>> {
16    let encmsg = lightning_hash(message)?;
17    let secp_ctx = Secp256k1::signing_only();
18    let sig = secp_ctx.sign_ecdsa_recoverable(&encmsg, &secret_key);
19    let (rid, sig) = sig.serialize_compact();
20    let mut fin = vec![(rid.to_i32() + MAGIC_NUMBER) as u8];
21    fin.extend_from_slice(&sig[..]);
22    Ok(fin)
23}
24
25pub fn verify_message(message: &[u8], sig: &[u8; 65], public_key: &PublicKey) -> Result<()> {
26    let secp_ctx = Secp256k1::verification_only();
27    let encmsg = lightning_hash(message)?;
28    // remove the rid
29    let s = Signature::from_compact(&sig[1..])?;
30    secp_ctx.verify_ecdsa(&encmsg, &s, public_key)?;
31    Ok(())
32}
33
34pub fn recover_pubkey(message: &[u8], sig: &[u8; 65]) -> Result<PublicKey> {
35    if sig.len() < 65 {
36        return Err(anyhow!("too short sig".to_string()));
37    }
38    let encmsg = lightning_hash(message)?;
39    let secp = Secp256k1::verification_only();
40    let id = ecdsa::RecoveryId::from_i32(sig[0] as i32 - MAGIC_NUMBER)?;
41    let s = ecdsa::RecoverableSignature::from_compact(&sig[1..], id)?;
42    Ok(secp.recover_ecdsa(&encmsg, &s)?)
43}
44
45pub fn lightning_hash(message: &[u8]) -> Result<Message> {
46    let mut buffer = String::from("Lightning Signed Message:").into_bytes();
47    buffer.extend(message);
48    let hash1 = Sha256Hash::hash(&buffer[..]);
49    let hash2 = Sha256Hash::hash(&hash1[..]);
50    let encmsg = secp256k1::Message::from_slice(&hash2[..])?;
51    Ok(encmsg)
52}