Skip to content

Commit

Permalink
remove siwe feature gate, fix siwe history issues and rename siwe mod
Browse files Browse the repository at this point in the history
  • Loading branch information
Charles Cunningham authored and Charles Cunningham committed Mar 25, 2022
1 parent c1c63fa commit 07b8a11
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 146 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repository = "https://github.com/spruceid/cacao/"
[features]
eip4361 = ["hex", "ethers-core"]
zcap = ["ssi"]
default = ["eip4361", "zcap", "siwe"]
default = ["eip4361", "zcap"]

[dependencies]
siwe = { version = "0.2" }
Expand Down
8 changes: 3 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ use chrono::{DateTime, Utc};
use http::uri::Authority;
use iri_string::types::{UriAbsoluteString, UriString};
pub use siwe::TimeStamp;
use std::str::FromStr;
use thiserror::Error;

pub mod generic;

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

pub struct CACAO<S>
where
Expand Down Expand Up @@ -102,8 +100,8 @@ pub enum Version {
pub struct Payload {
pub domain: Authority,
pub iss: UriAbsoluteString,
pub statement: String,
pub aud: UriAbsoluteString,
pub statement: Option<String>,
pub aud: UriString,
pub version: Version,
pub nonce: String,
pub iat: TimeStamp,
Expand Down
140 changes: 0 additions & 140 deletions src/siwe.rs
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,140 +0,0 @@
use super::{BasicSignature, Payload, SignatureScheme, VerificationError, Version};
use async_trait::async_trait;
use ethers_core::{types::H160, utils::to_checksum};
use hex::FromHex;
use siwe::{Message, VerificationError as SVE, Version as SVersion};

impl Into<SVersion> for Version {
fn into(self) -> SVersion {
match self {
Self::V1 => SVersion::V1,
}
}
}

impl From<SVersion> for Version {
fn from(v: SVersion) -> Self {
match v {
SVersion::V1 => Self::V1,
}
}
}

impl From<SVE> for VerificationError {
fn from(e: SVE) -> Self {
match e {
SVE::Crypto(_) | SVE::Signer => Self::Crypto,
SVE::Serialization(_) => Self::Serialization,
}
}
}

impl TryInto<Message> for Payload {
type Error = ();
fn try_into(self) -> Result<Message, Self::Error> {
let (chain_id, address) = match &self.iss.as_str().split(":").collect::<Vec<&str>>()[..] {
&["did", "pkh", "eip155", c, h] => {
(c.to_string(), FromHex::from_hex(&h[2..]).map_err(|_| ())?)
}
_ => return Err(()),
};
Ok(Message {
domain: self.domain,
address,
chain_id,
statement: self.statement,
uri: self.aud,
version: self.version.into(),
nonce: self.nonce,
issued_at: self.iat,
not_before: self.nbf,
expiration_time: self.exp,
request_id: self.request_id,
resources: self.resources,
})
}
}

impl From<Message> for Payload {
fn from(m: Message) -> Self {
Self {
domain: m.domain,
iss: format!(
"did:pkh:eip155:{}:0x{}",
m.chain_id,
to_checksum(&H160(&m.address), None)
)
.parse()
.unwrap(),
statement: m.statement,
aud: m.uri,
version: m.version.into(),
nonce: m.nonce,
iat: m.issued_at,
nbf: m.not_before,
exp: m.expiration_time,
request_id: m.request_id,
resources: m.resources,
}
}
}

pub struct SignInWithEthereum;

#[async_trait]
impl SignatureScheme for SignInWithEthereum {
type Signature = BasicSignature<[u8; 65]>;
fn id() -> String {
"eip4361-eip191".into()
}
async fn verify(payload: &Payload, sig: &Self::Signature) -> Result<(), VerificationError> {
if !payload.valid_now() {
return Err(VerificationError::NotCurrentlyValid);
};
let m: Message = payload
.clone()
.try_into()
.map_err(|_| VerificationError::MissingVerificationMaterial)?;
m.verify_eip191(sig.s)?;
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::BasicSignature;
use hex::FromHex;
use siwe::eip4361::Message;
use std::str::FromStr;

#[async_std::test]
async fn validation() {
// from https://github.com/blockdemy/eth_personal_sign
let message: Payload = Message::from_str(
r#"localhost:4361 wants you to sign in with your Ethereum account:
0x6Da01670d8fc844e736095918bbE11fE8D564163
SIWE Notepad Example
URI: http://localhost:4361
Version: 1
Chain ID: 1
Nonce: kEWepMt9knR6lWJ6A
Issued At: 2021-12-07T18:28:18.807Z"#,
)
.unwrap()
.into();
let correct = <[u8; 65]>::from_hex(r#"6228b3ecd7bf2df018183aeab6b6f1db1e9f4e3cbe24560404112e25363540eb679934908143224d746bbb5e1aa65ab435684081f4dbb74a0fec57f98f40f5051c"#).unwrap();
SignInWithEthereum::verify(&message, &BasicSignature { s: correct })
.await
.unwrap();

let incorrect = <[u8; 65]>::from_hex(r#"7228b3ecd7bf2df018183aeab6b6f1db1e9f4e3cbe24560404112e25363540eb679934908143224d746bbb5e1aa65ab435684081f4dbb74a0fec57f98f40f5051c"#).unwrap();
assert!(
SignInWithEthereum::verify(&message, &BasicSignature { s: incorrect })
.await
.is_err()
);
}
}
151 changes: 151 additions & 0 deletions src/siwe_cacao.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use super::{BasicSignature, Payload, SignatureScheme, VerificationError, Version};
use async_trait::async_trait;
use ethers_core::{types::H160, utils::to_checksum};
use hex::FromHex;
use siwe::{Message, VerificationError as SVE, Version as SVersion};

impl Into<SVersion> for Version {
fn into(self) -> SVersion {
match self {
Self::V1 => SVersion::V1,
}
}
}

impl From<SVersion> for Version {
fn from(v: SVersion) -> Self {
match v {
SVersion::V1 => Self::V1,
}
}
}

impl From<SVE> for VerificationError {
fn from(e: SVE) -> Self {
match e {
SVE::Crypto(_) | SVE::Signer => Self::Crypto,
SVE::Serialization(_) => Self::Serialization,
SVE::Time => Self::NotCurrentlyValid,
}
}
}

#[derive(thiserror::Error, Debug)]
pub enum SIWEPayloadConversionError {
#[error(transparent)]
InvalidAddress(#[from] hex::FromHexError),
#[error(transparent)]
InvalidChainId(#[from] std::num::ParseIntError),
#[error("Invalid DID, expected did:pkh")]
InvalidDID,
}

impl TryInto<Message> for Payload {
type Error = SIWEPayloadConversionError;
fn try_into(self) -> Result<Message, Self::Error> {
let (chain_id, address) = match &self.iss.as_str().split(":").collect::<Vec<&str>>()[..] {
&["did", "pkh", "eip155", c, h] if h.get(..2) == Some("0x") => {
(c.parse()?, FromHex::from_hex(&h[2..])?)
}
_ => return Err(Self::Error::InvalidDID),
};
Ok(Message {
domain: self.domain,
address,
chain_id,
statement: self.statement,
uri: self.aud,
version: self.version.into(),
nonce: self.nonce,
issued_at: self.iat,
not_before: self.nbf,
expiration_time: self.exp,
request_id: self.request_id,
resources: self.resources,
})
}
}

impl From<Message> for Payload {
fn from(m: Message) -> Self {
Self {
domain: m.domain,
iss: format!(
"did:pkh:eip155:{}:{}",
m.chain_id,
to_checksum(&H160(m.address), None)
)
.parse()
.unwrap(),
statement: m.statement,
aud: m.uri,
version: m.version.into(),
nonce: m.nonce,
iat: m.issued_at,
nbf: m.not_before,
exp: m.expiration_time,
request_id: m.request_id,
resources: m.resources,
}
}
}

pub struct SignInWithEthereum;

#[async_trait]
impl SignatureScheme for SignInWithEthereum {
type Signature = BasicSignature<[u8; 65]>;
fn id() -> String {
"eip4361-eip191".into()
}
async fn verify(payload: &Payload, sig: &Self::Signature) -> Result<(), VerificationError> {
if !payload.valid_now() {
return Err(VerificationError::NotCurrentlyValid);
};
let m: Message = payload
.clone()
.try_into()
.map_err(|e| VerificationError::MissingVerificationMaterial)?;
m.verify_eip191(&sig.s)?;
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::BasicSignature;
use hex::FromHex;
use siwe::Message;
use std::str::FromStr;

#[async_std::test]
async fn validation() {
// from https://github.com/blockdemy/eth_personal_sign
let message: Payload = Message::from_str(
r#"localhost:4361 wants you to sign in with your Ethereum account:
0x6Da01670d8fc844e736095918bbE11fE8D564163
SIWE Notepad Example
URI: http://localhost:4361
Version: 1
Chain ID: 1
Nonce: kEWepMt9knR6lWJ6A
Issued At: 2021-12-07T18:28:18.807Z"#,
)
.unwrap()
.into();
let correct = <[u8; 65]>::from_hex(r#"6228b3ecd7bf2df018183aeab6b6f1db1e9f4e3cbe24560404112e25363540eb679934908143224d746bbb5e1aa65ab435684081f4dbb74a0fec57f98f40f5051c"#).unwrap();
SignInWithEthereum::verify(&message, &BasicSignature { s: correct })
.await
.unwrap();

let incorrect = <[u8; 65]>::from_hex(r#"7228b3ecd7bf2df018183aeab6b6f1db1e9f4e3cbe24560404112e25363540eb679934908143224d746bbb5e1aa65ab435684081f4dbb74a0fec57f98f40f5051c"#).unwrap();
assert!(
SignInWithEthereum::verify(&message, &BasicSignature { s: incorrect })
.await
.is_err()
);
}
}

0 comments on commit 07b8a11

Please sign in to comment.