This commit is contained in:
kaiwitt 2021-08-28 09:35:27 +02:00
commit 138f82012e
No known key found for this signature in database
GPG Key ID: 2D2F3D411C032247
4 changed files with 70 additions and 35 deletions

View File

@ -14,4 +14,4 @@ publish = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bip39 = "1.0.1" bip39 = "1.0.*"

View File

@ -1,11 +1,11 @@
//! # seed-xor //! # seed-xor
//! //!
//! seed-xor builds on top of [rust-bip39](https://github.com/rust-bitcoin/rust-bip39/) //! seed-xor builds on top of [rust-bip39](https://github.com/rust-bitcoin/rust-bip39/)
//! and lets you XOR bip39 mnemonics as defined in [Coldcards docs](https://github.com/Coldcard/firmware/blob/master/docs/seed-xor.md). //! and lets you XOR bip39 mnemonics as described in [Coldcards docs](https://github.com/Coldcard/firmware/blob/master/docs/seed-xor.md).
//! //!
//! //!
//! It is also possible to XOR mnemonics with differing numbers of words. //! It is also possible to XOR mnemonics with differing numbers of words.
//! For this the shorter one will be extended with 0s during the XOR calculation. //! For this the xored value takes on the entropy surplus of the longer seed.
//! //!
//! //!
//! ## Example //! ## Example
@ -36,39 +36,17 @@ use std::{
str::FromStr, str::FromStr,
}; };
use bip39::Mnemonic as Inner; /// Trait for a `XOR`.
pub trait SeedXor {
/// Wrapper for a [bip39::Mnemonic] which is aliased as `Inner`. /// XOR two values without consuming them.
#[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] fn xor(&self, rhs: &Self) -> Self;
pub struct Mnemonic {
/// Actual [bip39::Mnemonic] which is wrapped to be able to implement the XOR operator.
inner: Inner,
} }
impl Mnemonic { impl SeedXor for bip39::Mnemonic {
/// Private constructor. /// XOR self with another [bip39::Mnemonic] without consuming it or itself.
fn new(inner: Inner) -> Self {
Mnemonic { inner }
}
/// Access the private inner [bip39::Mnemonic] for more functionality.
pub fn inner(&self) -> &Inner {
&self.inner
}
/// Wrapper for the same method as in [bip39::Mnemonic].
pub fn from_entropy(entropy: &[u8]) -> Result<Self, bip39::Error> {
match Inner::from_entropy(entropy) {
Ok(inner) => Ok(Mnemonic::new(inner)),
Err(err) => Err(err),
}
}
/// XOR two [Mnemonic]s without consuming them.
/// If consumption is not of relevance the XOR operator `^` and XOR assigner `^=` can be used as well.
fn xor(&self, rhs: &Self) -> Self { fn xor(&self, rhs: &Self) -> Self {
let mut entropy = self.inner.to_entropy(); let mut entropy = self.to_entropy();
let xor_values = rhs.inner.to_entropy(); let xor_values = rhs.to_entropy();
// XOR each Byte // XOR each Byte
entropy entropy
@ -83,7 +61,35 @@ impl Mnemonic {
// We unwrap here because entropy has either as many Bytes // We unwrap here because entropy has either as many Bytes
// as self or rhs and both are valid mnemonics. // as self or rhs and both are valid mnemonics.
Mnemonic::from_entropy(&entropy).unwrap() bip39::Mnemonic::from_entropy(&entropy).unwrap()
}
}
/// Wrapper for a [bip39::Mnemonic] for the implementation of `^` and `^=` operators.
#[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
pub struct Mnemonic {
/// Actual [bip39::Mnemonic] which is wrapped to be able to implement the XOR operator.
pub inner: bip39::Mnemonic,
}
impl Mnemonic {
/// Private constructor.
fn new(inner: bip39::Mnemonic) -> Self {
Mnemonic { inner }
}
/// Wrapper for the same method as in [bip39::Mnemonic].
pub fn from_entropy(entropy: &[u8]) -> Result<Self, bip39::Error> {
match bip39::Mnemonic::from_entropy(entropy) {
Ok(inner) => Ok(Mnemonic::new(inner)),
Err(err) => Err(err),
}
}
/// XOR two [Mnemonic]s without consuming them.
/// If consumption is not of relevance the XOR operator `^` and XOR assigner `^=` can be used as well.
fn xor(&self, rhs: &Self) -> Self {
Mnemonic::new(self.inner.xor(&rhs.inner))
} }
} }
@ -91,7 +97,7 @@ impl FromStr for Mnemonic {
type Err = bip39::Error; type Err = bip39::Error;
fn from_str(mnemonic: &str) -> Result<Self, <Self as FromStr>::Err> { fn from_str(mnemonic: &str) -> Result<Self, <Self as FromStr>::Err> {
match Inner::from_str(mnemonic) { match bip39::Mnemonic::from_str(mnemonic) {
Ok(inner) => Ok(Mnemonic::new(inner)), Ok(inner) => Ok(Mnemonic::new(inner)),
Err(err) => Err(err), Err(err) => Err(err),
} }

17
workflows/cargo.yml Normal file
View File

@ -0,0 +1,17 @@
on: [push]
name: CI
jobs:
build_and_test:
name: cargo_test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- uses: actions-rs/cargo@v1
with:
command: test
args: --release --all-features

12
workflows/clippy.yml Normal file
View File

@ -0,0 +1,12 @@
on: push
name: Clippy check
jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: rustup component add clippy
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features