Skip to content

Commit

Permalink
feature: service::AuthVerifier
Browse files Browse the repository at this point in the history
  • Loading branch information
edouardparis committed Aug 18, 2020
1 parent 304cd3f commit 9d10152
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ documentation = "https://docs.rs/lnurl/"
[lib]
name = "lnurl"

[features]
# Include nothing by default
default = []
service = ["bitcoin_hashes", "hex", "secp256k1"]

[dependencies]
bitcoin_hashes = { version = "^0.7.6", optional = true }
hex = { version = "0.4.2", optional = true }
secp256k1 = { version = "^0.17.2", optional = true }
serde = { version = "^1.0.93", features =["derive"]}
serde_json = "^1.0.39"

3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use serde::{Deserialize, Serialize};

#[cfg(feature = "service")]
pub mod service;

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum Event {
#[serde(rename = "REGISTERED")]
Expand Down
88 changes: 88 additions & 0 deletions src/service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
extern crate bitcoin_hashes;
extern crate hex;
extern crate secp256k1;

use bitcoin_hashes::{sha256, Hash};
use secp256k1::{Error, Message, PublicKey, Secp256k1, Signature, Verification, VerifyOnly};

/// VerifierError is the AuthVerifier errors.
pub enum VerifierError {
Secp256k1Error(Error),
HexError(hex::FromHexError),
}

/// AuthVerifier verifies the secp256k1 signature of a message with a given pubkey.
pub struct AuthVerifier {
secp: Secp256k1<VerifyOnly>,
}

impl AuthVerifier {
pub fn new() -> Self {
AuthVerifier {
secp: Secp256k1::verification_only(),
}
}

/// verifies the secp256k1 signature of a message with a given pubkey.
pub fn verify(self, hk1: &str, hsig: &str, hpubkey: &str) -> Result<bool, VerifierError> {
let msg = hex::decode(hk1).map_err(|e| VerifierError::HexError(e))?;
let sig = hex::decode(hsig).map_err(|e| VerifierError::HexError(e))?;
let pubkey = hex::decode(hpubkey).map_err(|e| VerifierError::HexError(e))?;
return verify_sig(&self.secp, &msg, &sig, &pubkey)
.map_err(|e| VerifierError::Secp256k1Error(e));
}
}

/// verify_sig checks if the signature of a key for a given message is valid.
pub fn verify_sig<C: Verification>(
secp: &Secp256k1<C>,
msg: &[u8],
sig: &[u8],
pubkey: &[u8],
) -> Result<bool, Error> {
let msg = sha256::Hash::hash(msg);
let msg = Message::from_slice(&msg)?;
let sig = Signature::from_compact(sig)?;
let pubkey = PublicKey::from_slice(pubkey)?;

Ok(secp.verify(&msg, &sig, &pubkey).is_ok())
}

#[cfg(test)]
mod tests {
use super::*;

extern crate bitcoin_hashes;
use secp256k1::{Error, Message, Secp256k1, SecretKey, Signature, Signing};

fn sign<C: Signing>(
secp: &Secp256k1<C>,
msg: &[u8],
seckey: [u8; 32],
) -> Result<Signature, Error> {
let msg = sha256::Hash::hash(msg);
let msg = Message::from_slice(&msg)?;
let seckey = SecretKey::from_slice(&seckey)?;
Ok(secp.sign(&msg, &seckey))
}

#[test]
fn test_verify_sig() {
let secp = Secp256k1::new();
let seckey = [
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174,
253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
];
let pubkey = [
2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91,
141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
];
let msg = b"This is some message";

let signature = sign(&secp, msg, seckey).unwrap();

let serialize_sig = signature.serialize_compact();

assert!(verify_sig(&secp, msg, &serialize_sig, &pubkey).unwrap());
}
}

0 comments on commit 9d10152

Please sign in to comment.