Compare commits
No commits in common. "2e3c387ae126e4c6333f7021febf8351729b429f" and "d390834b0e8ae646b7a415fc7e10a1a573d6a6d0" have entirely different histories.
2e3c387ae1
...
d390834b0e
|
@ -1786,7 +1786,6 @@ dependencies = [
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"smex",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -78,8 +78,8 @@ pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box<dyn std::error::Erro
|
||||||
#[cfg(feature = "qrcode")]
|
#[cfg(feature = "qrcode")]
|
||||||
{
|
{
|
||||||
use keyfork_qrcode::{qrencode, ErrorCorrection};
|
use keyfork_qrcode::{qrencode, ErrorCorrection};
|
||||||
let mut qrcode_data = nonce_mnemonic.to_bytes();
|
let mut qrcode_data = nonce_mnemonic.entropy();
|
||||||
qrcode_data.extend(key_mnemonic.as_bytes());
|
qrcode_data.extend(key_mnemonic.entropy());
|
||||||
if let Ok(qrcode) = qrencode(&smex::encode(&qrcode_data), ErrorCorrection::Medium) {
|
if let Ok(qrcode) = qrencode(&smex::encode(&qrcode_data), ErrorCorrection::Medium) {
|
||||||
pm.prompt_message(PromptMessage::Data(qrcode))?;
|
pm.prompt_message(PromptMessage::Data(qrcode))?;
|
||||||
}
|
}
|
||||||
|
@ -120,10 +120,10 @@ pub fn remote_decrypt(w: &mut impl Write) -> Result<(), Box<dyn std::error::Erro
|
||||||
let [pubkey_mnemonic, payload_mnemonic] =
|
let [pubkey_mnemonic, payload_mnemonic] =
|
||||||
pm.prompt_validated_wordlist("Their words: ", &wordlist, 3, validator.to_fn())?;
|
pm.prompt_validated_wordlist("Their words: ", &wordlist, 3, validator.to_fn())?;
|
||||||
let pubkey = pubkey_mnemonic
|
let pubkey = pubkey_mnemonic
|
||||||
.as_bytes()
|
.entropy()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| InvalidData)?;
|
.map_err(|_| InvalidData)?;
|
||||||
let payload = payload_mnemonic.to_bytes();
|
let payload = payload_mnemonic.entropy();
|
||||||
(pubkey, payload)
|
(pubkey, payload)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -495,11 +495,11 @@ pub fn decrypt(
|
||||||
pm.prompt_validated_wordlist("Their words: ", &wordlist, 3, validator.to_fn())?;
|
pm.prompt_validated_wordlist("Their words: ", &wordlist, 3, validator.to_fn())?;
|
||||||
|
|
||||||
let nonce = nonce_mnemonic
|
let nonce = nonce_mnemonic
|
||||||
.as_bytes()
|
.entropy()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| InvalidData)?;
|
.map_err(|_| InvalidData)?;
|
||||||
let pubkey = pubkey_mnemonic
|
let pubkey = pubkey_mnemonic
|
||||||
.as_bytes()
|
.entropy()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| InvalidData)?;
|
.map_err(|_| InvalidData)?;
|
||||||
(nonce, pubkey)
|
(nonce, pubkey)
|
||||||
|
@ -560,8 +560,8 @@ pub fn decrypt(
|
||||||
#[cfg(feature = "qrcode")]
|
#[cfg(feature = "qrcode")]
|
||||||
{
|
{
|
||||||
use keyfork_qrcode::{qrencode, ErrorCorrection};
|
use keyfork_qrcode::{qrencode, ErrorCorrection};
|
||||||
let mut qrcode_data = our_pubkey_mnemonic.to_bytes();
|
let mut qrcode_data = our_pubkey_mnemonic.entropy();
|
||||||
qrcode_data.extend(payload_mnemonic.as_bytes());
|
qrcode_data.extend(payload_mnemonic.entropy());
|
||||||
if let Ok(qrcode) = qrencode(&smex::encode(&qrcode_data), ErrorCorrection::Lowest) {
|
if let Ok(qrcode) = qrencode(&smex::encode(&qrcode_data), ErrorCorrection::Lowest) {
|
||||||
pm.prompt_message(PromptMessage::Data(qrcode))?;
|
pm.prompt_message(PromptMessage::Data(qrcode))?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl RecoverSubcommands {
|
||||||
3,
|
3,
|
||||||
validator.to_fn(),
|
validator.to_fn(),
|
||||||
)?;
|
)?;
|
||||||
Ok(mnemonic.to_bytes())
|
Ok(mnemonic.entropy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,12 @@ repository = "https://git.distrust.co/public/keyfork"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
bin = ["smex"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Included in rust
|
# Included in rust
|
||||||
sha2 = "0.10.7"
|
sha2 = "0.10.7"
|
||||||
|
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
pbkdf2 = "0.12.2"
|
pbkdf2 = "0.12.2"
|
||||||
smex = { version = "0.1.0", path = "../smex", optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bip39 = "2.0.0"
|
bip39 = "2.0.0"
|
||||||
|
|
|
@ -265,27 +265,17 @@ impl Mnemonic {
|
||||||
&self.entropy
|
&self.entropy
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The internal representation of the decoded data, as a [`Vec<u8>`].
|
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
self.entropy.to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Drop self, returning the decoded data.
|
/// Drop self, returning the decoded data.
|
||||||
pub fn into_bytes(self) -> Vec<u8> {
|
pub fn to_bytes(self) -> Vec<u8> {
|
||||||
self.entropy
|
self.entropy
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clone the existing entropy.
|
/// Clone the existing entropy.
|
||||||
#[deprecated]
|
|
||||||
pub fn entropy(&self) -> Vec<u8> {
|
pub fn entropy(&self) -> Vec<u8> {
|
||||||
self.entropy.clone()
|
self.entropy.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a BIP-0032 seed from the provided data and an optional passphrase.
|
/// Create a BIP-0032 seed from the provided data and an optional passphrase.
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// The method may return an error if the pbkdf2 function returns an invalid length, but this
|
|
||||||
/// case should not be reached.
|
|
||||||
pub fn seed<'a>(
|
pub fn seed<'a>(
|
||||||
&self,
|
&self,
|
||||||
passphrase: impl Into<Option<&'a str>>,
|
passphrase: impl Into<Option<&'a str>>,
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
# Developers Guide
|
# Developers Guide
|
||||||
|
|
||||||
- [Handling Data](./dev-guide/handling-data.md)
|
|
||||||
- [Writing Binaries](./dev-guide/index.md)
|
- [Writing Binaries](./dev-guide/index.md)
|
||||||
- [Provisioners](./dev-guide/provisioners.md)
|
- [Provisioners](./dev-guide/provisioners.md)
|
||||||
- [Auditing Dependencies](./dev-guide/auditing.md)
|
- [Auditing Dependencies](./dev-guide/auditing.md)
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
# Handling Data
|
|
||||||
|
|
||||||
In Rust, it is common to name things `as_*`, `to_*`, and `into_*`. These three
|
|
||||||
methods perform three different, but related, functions, and it's important to
|
|
||||||
choose the correct name when writing methods. These methods take data that are
|
|
||||||
stored inside of the struct, and return them in some manner. For example, let's
|
|
||||||
look at the `Mnemonic` struct:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub struct Mnemonic {
|
|
||||||
entropy: Vec<u8>,
|
|
||||||
// fields omitted
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
We're going to define the three methods `as_bytes()`, `to_bytes()`, and
|
|
||||||
`into_bytes()`, explaining what the details of each are. To start with:
|
|
||||||
|
|
||||||
### `Mnemonic::as_bytes()`
|
|
||||||
|
|
||||||
This method will return a `&[u8]`, a reference to a slice of bytes, without
|
|
||||||
allocating anything. The `Mnemonic` type is not consumed by this process.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Mnemonic {
|
|
||||||
/// Return a slice of bytes represented by the mnemonic.
|
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
|
||||||
&self.entropy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `Mnemonic::to_bytes()`
|
|
||||||
|
|
||||||
This method will return a `Vec<u8>`, an allocated type containing the bytes,
|
|
||||||
without consuming the `Mnemonic` type. This is useful if you may need the
|
|
||||||
`Mnemonic` type in the future.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Mnemonic {
|
|
||||||
/// Return a `Vec<u8>` of bytes represented by the mnemonic.
|
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
self.entropy.to_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `Mnemonic::into_bytes()`
|
|
||||||
|
|
||||||
This method will return the internal representation of bytes. No allocation is
|
|
||||||
performed, but the `Mnemonic` value is no longer accessible.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Mnemonic {
|
|
||||||
/// Return a Vec<u8> of bytes represented by the mnemonic.
|
|
||||||
pub fn into_bytes(self) -> Vec<u8> {
|
|
||||||
self.entropy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Creating Data: `Mnemonic::seed()`
|
|
||||||
|
|
||||||
Sometimes you may have an operation (such as creating a seed from a mnemonic)
|
|
||||||
which can't possibly happen without allocating some kind of data. In that case,
|
|
||||||
it is not reasonable - or even possible - to have three methods for that case.
|
|
||||||
In that case, it is reasonable to have a method with a "bare" name, such as
|
|
||||||
`Mnemonic::seed()`. Additionally, unless it makes sense to make the type
|
|
||||||
unusable after such an operation (using the type system to your advantage), it
|
|
||||||
makes sense to borrow from self while returning the allocated value.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Mnemonic {
|
|
||||||
/// Create a seed from the mnemonic's data.
|
|
||||||
pub fn seed(&self) -> Result<Vec<u8>, Error> {
|
|
||||||
let result = perform_secret_operation(self.entropy)?;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Complex Example: `Mnemonic::into_parts()`
|
|
||||||
|
|
||||||
Let's add a `Wordlist` to our `Mnemonic` type, so we can format it as a string.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub struct Mnemonic {
|
|
||||||
entropy: Vec<u8>,
|
|
||||||
wordlist: Wordlist,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Because we now have two expensive-to-allocate variables in our type, we need to
|
|
||||||
change how we deconstruct it into parts:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
impl Mnemonic {
|
|
||||||
/// Split the Mnemonic into its interior parts.
|
|
||||||
pub fn into_parts(self) -> (Vec<u8>, Wordlist) {
|
|
||||||
let Mnemonic { entropy, wordlist } = self;
|
|
||||||
(entropy, wordlist)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a Vec<u8> of bytes represented by the mnemonic.
|
|
||||||
pub fn into_bytes(self) -> Vec<u8> {
|
|
||||||
self.into_parts().0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the Wordlist used by the mnemonic.
|
|
||||||
pub fn into_wordlist(self) -> Wordlist {
|
|
||||||
self.into_parts().1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In practical use, `Mnemonic` stores `wordlist` as an `Arc<T>` to allow reusing
|
|
||||||
the same wordlist (parsing it is expensive!), but we'll ignore that for
|
|
||||||
demonstration purposes.
|
|
Loading…
Reference in New Issue