Code Monkey home page Code Monkey logo

crypto.rs's Introduction

crypto.rs

tests coverage dependency status FOSSA Status

A boundary crate of selected implementations of crypto primitives that are considered to be safe to use within the IOTA Foundation.

To be included in this list an implementation must:

  • expose a minimal interface using the simplest possible types with high semantic density
  • be explicit what algorithm they perform (e.g. PBKDF_HMAC_SHA512)
  • use explicit memory allocation whenever possible and prefer no_std
  • be proven by: mathematical proofs, audits, reviews by security experts, mass adoption
  • be tested using independently generated test vectors from well-established reference implementations as well as available test vectors in relevant specifications

List of Algorithms

Type Name Feature Spec/RFC Rust Source Test Source Rating*
ciphers AES-256-GCM aes spec aes-gcm nist ★★★☆☆
ciphers AES-KW aes-kw spec aes-crate nist ★★★☆☆
ciphers XCHACHA20-POLY1305 chacha rfc chacha20poly1305 official ★★★★★
ciphers AES-CBC aes-cbc rfc crypto.rs official ☆☆☆☆☆
hashes BLAKE2b-160 blake2b rfc blake2 official ★★★★☆
hashes BLAKE2b-256 blake2b rfc blake2 official ★★★★☆
hashes CURL-P curl-p rfc bee-ternary official ★★☆☆☆
hashes SHA2-256 sha spec sha2 nist ★★★★★
hashes SHA2-384 sha spec sha2 nist ★★★★★
hashes SHA2-512 sha spec sha2 nist ★★★★★
keys X25519 x25519 RFC7748 x25519-dalek official ★★★★★
keys PBKDF2-HMAC-SHA256 pbkdf rfc pbkdf2 self ★★★★☆
keys PBKDF2-HMAC-SHA384 pbkdf rfc pbkdf2 self ★★★★☆
keys PBKDF2-HMAC-SHA512 pbkdf rfc pbkdf2 self ★★★★☆
keys BIP-39 bip39 rfc crypto.rs multilang ★★☆☆☆
keys SLIP-10 slip10 rfc crypto.rs official ★★★☆☆
macs HMAC-SHA2-256 hmac rfc hmac official ★★★★☆
macs HMAC-SHA2-384 hmac rfc hmac official ★★★★☆
macs HMAC-SHA2-512 hmac rfc hmac official ★★★★☆
signatures Ed25519 ed25519 rfc (draft) ed25519-zebra extended ★★★★☆
signatures Secp256k1 ECDSA secp256k1 spec k256 extended ★★★☆☆
utility RANDOM random getrandom math ★★★★★

* We have chosen a fully arbitrary rating for each algorithm based on how we generally feel about them.

Usage

Cargo.toml


[dependencies.iota-crypto]
git = "https://github.com/iotaledger/crypto.rs"
# be sure to grab the latest github commit revision hash!!!
rev = "09ff1a94d6a87838589ccf1b874cfa3283a00f26"
features = [ "random", "ed25519", "sha", "hmac", "bip39-en" ]
version = "*"

[features]
default = [ "crypto" ]
crypto = [ "iota-crypto" ]

src/main.rs

use crypto::{
    ciphers::{aes, aes-kw}
    hashes::{blake2b, curl-p, sha}
    keys::{bip39, pbkdf, slip10, x25519}
    macs::hmac
    signatures::ed25519
    utils::random
}

Reference

cargo doc --workspace --no-deps --open

WARNING

This library has not yet been audited for security, so use at your own peril. Until a formal third-party security audit has taken place, the IOTA Foundation makes no guarantees to the fitness of this library for any purposes.

As such they are to be seen as experimental and not ready for real-world applications.

Nevertheless, we are very interested in feedback about the design and implementation, and encourage you to reach out with any concerns or suggestions you may have.

Reviewers

Review the implementation and API seperately. Verify the dependency tree with different feature flags.

Contributors

  • Focusing on providing a variety of test vectors outweighs any concerns regarding the chosen initial implementation (such as performance).
  • Review the imported code

Community Testing of Hardware / OS

  • todo Matrix of tested hardware tbd.

Discussions

If you have questions about how to use this library, or why certain decisions were made, please create a new discussion.

Tests

cargo test --lib --all --all-features --tests

Doctest

We aim to supply at least one docstest for every interface, so to see real world usage consult the rustdocs.

License

Apache 2.0

FOSSA Status

crypto.rs's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

crypto.rs's Issues

BLAKE2b: Provide an implementation of Digest

Currently, there is only hash computing the BLAKE2b hash of variable output sizes. This might not be sufficient in some scenarios and there should be BLAKE2b-256 implementation of Digest.

Bindings

Description

This is a tracking issue for the bindings needed for this library.

Requirements

  • go (required for hornet, wasp etc.)
  • javascript (node module type with NEON)

Stretch goals

  • c (not strictly necessary per sé, but a primitive for go and python)
  • python (might be useful for external projects / market adoption)
  • wasm (could be a community task)

RUSTSEC-2021-0060: merged into the `aes` crate

merged into the aes crate

Details
Status unmaintained
Package aes-soft
Version 0.6.4
URL RustCrypto/block-ciphers#200
Date 2021-04-29

The aes-soft crate has been merged into the aes crate. The new repository
location is at:

<https://github.com/RustCrypto/block-ciphers/tree/master/aes>

AES-NI is now autodetected at runtime on i686/x86-64 platforms.
If AES-NI is not present, the aes crate will fallback to a constant-time
portable software implementation.

To force the use of a constant-time portable implementation on these platforms,
even if AES-NI is available, use the new force-soft feature of the aes
crate to disable autodetection.

See advisory page for additional details.

Beta Cleanup

Description

In anticipation of the forthcoming beta release, we will need to make sure that we have done a number of things:

Meta

  • Add and use CODEOWNERS file

Cargo.toml

  • Allocate authorship of crate to IOTA Foundation
  • Cleanup and group dependency ordering
  • Verify that all dependencies are up to date
  • Supply a proper software BOM

Documentation

  • Add crate level introduction to lib.rs
  • Catch missing docs #![warn(missing_docs)]

Readme

  • Readme that defines the library
  • Must reference license
  • Should be ref'd in the Cargo.toml
  • When published, should have a crates.io badge
  • Should provide a link to the CHANGELOG (top level should link to ALL changelogs)

CI

  • Should also run examples (if feasible)
  • Audit all external workflows
  • Do more careful checks for running tests (e.g. don't need to run tests if we only change the README)

ARCHITECTURE.md

  • We need a very verbose explanation of the architecture from a general perspective as well as go into detail about each feature and what it does.

Cleaner API for Ciphers

Description

The current Cipher API is pretty complicated and inconsistent. The heavy use of the generic_array library makes type conversion tricky from standard types such as Vectors and Slices. Also, when the cypher fails due to a type error, the error messages are not very descriptive; apparently it depends on the type. If you specify a slice without the appropriate length, in some cases you get an error describing that the length is wrong and in other cases you just get a generic panic.

Example (from stronghold):

let mut tag = [0u8; Self::TAG_LEN];

...

XChaCha20Poly1305::encrypt(
            ...
            &mut tag
                .try_into()?,
            ...
           )?;

Despite the tag being a mutable slice of size 16 and the GenericArray implementing a TryInto trait for the conversion (&mut [u8; 16]), the tag doesn't get updated by the encryption call. There is no compile time error for this and instead it becomes a runtime error. An appropriate implementation looks more like this:

let mut tag = vec![0u8; Self::TAG_LEN];

...

XChaCha20Poly1305::encrypt(
            ...
            tag.as_mut_slice()
                .try_into()?,
            ...
           )?;

This becomes confusing because the nonce can be written like so without causing the same kind of errors:

let mut nonce = [0u8; Self::NONCE_LEN];

...

 XChaCha20Poly1305::encrypt(
            ...
            &nonce.try_into()?,
            ...
        )?;

Also, the ordering of the parameters for the encryption and decryption functions are inconsistent. The Encryption function looks like this:

XChaCha20Poly1305::encrypt(
           key,
           nonce,
           associated_data,
           plaintext,
           ciphertext,
           tag,
        )

Where as the decryption function looks like this:

XChaCha20Poly1305::decrypt(
            key,
            nonce,
            associated_data,
            tag,
            ciphertext,
            plaintext
        )

The API would be much smoother if the position parameters stayed the same across the two different functions. The functions try_encrypt and try_decrypt also contain the same parameter order and the try_encrypt function does not allow you to specify a tag.

Motivation

The point of this feature is to make the overall cipher API much more user friendly. As it is right now, its unnecessarily troublesome and unpredictable. Documentation will help with some of this needless complexity, but the type conversion problems will still persist. Presumably the try functions are meant to lessen this complexity, but the lack of a tag on try_encrypt makes using it inefficient.

Requirements

Write a list of what you want this feature to do.

  1. Add more descriptive errors for failure states; mainly length errors and type errors.
  2. Fix the ordering of the parameter lists on the methods and the lack of the tag parameter on the try_encrypt method (or make it clear in the docs that the try_encrypt function returns a new tag).
  3. Add a better example of these methods in use then what exists in the tests folders at the moment. Doc testing would be useful for something like this.

Are you planning to do it yourself in a pull request?

Yes

RUSTSEC-2021-0059: merged into the `aes` crate

merged into the aes crate

Details
Status unmaintained
Package aesni
Version 0.10.0
URL RustCrypto/block-ciphers#200
Date 2021-04-29

The aesni crate has been merged into the aes crate. The new repository
location is at:

<https://github.com/RustCrypto/block-ciphers/tree/master/aes>

AES-NI is now autodetected at runtime on i686/x86-64 platforms.
If AES-NI is not present, the aes crate will fallback to a constant-time
portable software implementation.

To prevent this fallback (and have absence of AES-NI result in an illegal
instruction crash instead), continue to pass the same RUSTFLAGS which were
previously required for the aesni crate to compile:

RUSTFLAGS=-Ctarget-feature=+aes,+ssse3

See advisory page for additional details.

Add alloc feature for easier lib usage

Description

Continuing the discussion from #3 - crypto.rs should provide an alloc feature that allows opting in to more convenient usage patterns (eg. returning Vec<T> from a function) and to provide support for primitives requiring allocation (eg. RSA)

Motivation

This improves usability of crypto.rs and is required to support certain algorithms (eg. RSA)

Requirements

  1. Add an alloc cargo feature to enable condition compilation with #[cfg(feature = "alloc")]
  2. Add *_vec functions where they make sense (eg. AES_256_GCM::encrypt_vec)

Are you planning to do it yourself in a pull request?

Maybe.

Verify latest versions of dependencies

Description

Some dependencies are potentially out of date (like pbkdf2). Currently we are running a cargo audit via cron in our workflows. We should have a workflow that detects out of date dependencies and flags them for review / or alternatively use the renovate bot.

Motivation

This crate will soon enter stable maintenance, and as such it is not expected that developers will be continuously working on it.

Requirements (if we roll our own)

  1. Detect which versions of dependencies are in use
  2. Compare that with latest stable as available from crates.io
  3. Compare fails with a permissioned list
  4. Do not fail fast, just collect info. At the end:
  • create new issue with the results as content
  • process.exit(1) if any truthy values persist after analysis.
  1. Have a badge on the repo that notifies of DEPS: up to date / DEPS: out of date
  2. Badge should link to workflow run.

Improve BIP39 implementation

          The implementation of bip39 is questionable. From the first glance the following looks suspicious to me:
  1. mnemonic_to_seed modifies the input mnemonic (which is a secret) and doesn't clean up the local result (which is also secret). I'd advise against modifying secrets, it feels weird. Maybe there should be some sort of validation, or Mnemonic type should encapsulate only valid mnemonics (with unnecessary spaces stripped and in NFKD form).
  2. salt intermediate value is not cleared in mnemonic_to_seed.
  3. Wordlist accepts some "bad" and "incorrect" words and separators. Maybe, there should be a constructor for normalizing and checking words.
  4. data in encode should be called secret_entropy or something to indicate its purpose: it should be handled with care and zeroized after use.
  5. encode should return Mnemonic, not just String.
  6. CS is not zeroized in encode.
  7. decode takes secret mnemonic as input ms of type &str and is modified (normalized to NFKD form). NFKD form should be validated/converted to in a Mnemonic constructor, decode should take a (valid) Mnemonic as input and can't modify it (leak it into stack/heap memory). ms local variable should be zeroized.
  8. separator in decode should already be normalized/valid in Wordlist; no need to normalize it all the time.
  9. Why separator is &str? Why not char? Is it correct to accept different spaces (tabs, space, invisible space, etc.) in one mnemonic?
  10. In decode there's no need for sub_whole_byte_case function and multiple calls to it. Just compute the last argument once and run the function once.

Originally posted by @semenov-vladyslav in #197 (comment)

Publish to crates.io

The vast majority of users of crypto.rs as a rust library will expect to be able to pull its crates from crates.io and also to be able to publish their crate to crates.io - this however was proven NOT to work for stronghold when pulling in crypto.rs from git, i.e. stronghold could not publish to crates.io if it consumed a crate from any git source.

We should provide guidance for both types of users.

Add Cipher trait

Description

crypto.rs should provide a Cipher trait to expose a consistent API and make it easier to use multiple algorithms with generic types.

Motivation

This ensures all implementations have a consistent API and allows the following code:

use crate::ciphers::{aes::Aes256Gcm, chacha::XChaCha20Poly1305, traits::Cipher}

fn generic_encrypt<C: Cipher>(...) -> Result<<C as Cipher>::Tag> {
  C::encrypt(...)
}

let tag = generic_encrypt::<Aes256Gcm>(...)?;
// OR
let tag = generic_encrypt::<XChaCha20Poly1305>(...)?;

Requirements

  1. Add a Cipher trait, available at crate::ciphers::traits::Cipher
  2. Provide a Cipher implementation for all relevant types in crate::ciphers
  3. 🎉 Party 🎉

Open questions

An example of what this trait might look like is below.

Implementations need to specify:

  • key/nonce/tag lengths (as typenum values, exposed via consts)
  • a custom error type (this example simply ignores the underlying implementation error)
  • a user-friendly name for error messages
  • encrypt/decrypt functions with explicitly sized arguments (where appropriate)

The trait would also provide easier-to-use try_encrypt/try_decrypt functions that accept rust slices as arguments.

Notes:

  • The conversion in try_generic_array is simply a length check/pointer cast - no data is being copied
  • decrypt and try_decrypt return the length of the plaintext. This is to accommodate implementations that may apply padding.
  • It may be worthwhile to add a function to calculate the padding of a plaintext buffer (fn pad(plaintext: &[u8]) -> usize;)
    • This is to further accommodate implementations with padding (a default implementation could be provided and just return 0)
use aes::cipher::generic_array::{ArrayLength, GenericArray};
use core::convert::TryInto;

pub mod consts {
  pub use aes::cipher::generic_array::typenum::*;
}

pub type Key<T> = GenericArray<u8, T>;

pub type Nonce<T> = GenericArray<u8, T>;

pub type Tag<T> = GenericArray<u8, T>;

pub trait Cipher {
  type KeyLength: ArrayLength<u8>;
  type NonceLength: ArrayLength<u8>;
  type TagLength: ArrayLength<u8>;

  type Error;

  const NAME: &'static str;

  fn encrypt(
    key: &Key<Self::KeyLength>,
    iv: &Nonce<Self::NonceLength>,
    aad: &[u8],
    ptx: &[u8],
    ctx: &mut [u8],
    tag: &mut Tag<Self::TagLength>,
  ) -> Result<(), Self::Error>;

  fn decrypt(
    key: &Key<Self::KeyLength>,
    iv: &Nonce<Self::NonceLength>,
    aad: &[u8],
    tag: &Tag<Self::TagLength>,
    ctx: &[u8],
    ptx: &mut [u8],
  ) -> Result<usize, Self::Error>;

  fn try_encrypt(
    key: &[u8],
    iv: &[u8],
    aad: &[u8],
    ptx: &[u8],
    ctx: &mut [u8],
  ) -> crate::Result<Tag<Self::TagLength>> {
    let key: &Key<Self::KeyLength> = try_generic_array(key)?;
    let iv: &Nonce<Self::NonceLength> = try_generic_array(iv)?;
    let mut tag: Tag<Self::TagLength> = Default::default();

    Self::encrypt(key, iv, aad, ptx, ctx, &mut tag)
      .map_err(|_| crate::Error::CipherError { alg: Self::NAME })?;

    Ok(tag)
  }

  fn try_decrypt(
    key: &[u8],
    iv: &[u8],
    aad: &[u8],
    tag: &[u8],
    ctx: &[u8],
    ptx: &mut [u8],
  ) -> crate::Result<usize> {
    let key: &Key<Self::KeyLength> = try_generic_array(key)?;
    let iv: &Nonce<Self::NonceLength> = try_generic_array(iv)?;
    let tag: &Tag<Self::TagLength> = try_generic_array(tag)?;

    Self::decrypt(key, iv, aad, tag, ctx, ptx)
      .map_err(|_| crate::Error::CipherError { alg: Self::NAME })
  }
}

fn try_generic_array<T>(slice: &[u8]) -> crate::Result<&GenericArray<u8, T>>
where
  T: ArrayLength<u8>,
{
  if slice.len() == T::USIZE {
    Ok(slice.into())
  } else {
    Err(crate::Error::BufferSize {
      needs: T::USIZE,
      has: slice.len(),
    })
  }
}

Are you planning to do it yourself in a pull request?

Yes

Ed25519: generation, storage, sign & verify

Description

As far as I observed in the code, stronghold currently support Ed25519 signing and verification in relation to BIP39 mnemonics.
Due to the use of Ed25519 across the board we also need facilities to securely generate Ed25519 key pairs, storing them at rest, sign messages and verify them.

Motivation

Ed25519 has emerged in our discussion to be the selected standard we are gonna use pretty much for every signing purpose.

Requirements

Write a list of what you want this feature to do.

  1. Key generation using good source of entropy (time bounded though);
  2. Non-volatile secure storage of private key;
  3. Memory guarantees for private key;
  4. Sign arbitrary messages;
  5. Verify arbitrary messages -- this may be optional as it is not a "secure" operation, but since the rest it is needed it kinda makes sense to implement this as well.

Open questions (optional)

  1. Similarly to signing, we should establish an encryption standard that we want to establish across the board; so far I am only aware of Keccak-f[1600] sponges used by the Stream guys,

Are you planning to do it yourself in a pull request?

No.

BLS and Distributed Key Generation (DKG)

Description

To implement DKG and distributed private key management for BLS threshold cryptography

Motivation

  • IOTA Smart Contract security depends on the key management. Essentially, IOTA Smart Contract is a distributed automated wallet.
  • each participation and identity of the Wasp node in a smart contract is represented by a partial private key share. It must be generated by the participating node during Distributed Key Generation (DKG) protocol session, based on BLS cryptography, Shamir secret sharing etc. The DKG protocol is security sensitive. Each Wasp node keeps its generated private keys for each contract's lifetime.
  • by hacking private keys from the part of Wasp nodes would allow to stop smart contract from running. The event of stealing keys from the quorum of nodes will mean take over of the smart contract by the malicious party.
  • the feature of the Stronghold would be to include secure implementations for the BLS signature generation and signing, DKG protocol and secure registry for keys. In the future, in hardware.
  • as Wasp node is implemented in Go, there's a need for Go bindings of Stronghold

Requirements

  1. Decentralized and secure DKG protocol for BLS threshold private key shares with metadata. Only participants can know private keys and no third party can know or reconstruct the master key.
  2. Validation of consistency of generated distributed key sets
  3. Storing and managing registry of private key shares with relevant metadata.
  4. Secure backup and transfer of key(s) with metadata to another Stronghold instance
  5. Go binding for Stronghold.

Open questions (optional)

  • particular DKG protocols and algorithms

Are you planning to do it yourself in a pull request?

No.

Implement BLAKE2b-160

Currently, the only supported version is BLAKE2b-256. This should be extended to also support the 160-bit version of BLAKE2b:

  • Add a new wrapper for VarBlake2b with 160-bit output length, matching Blake2b256.
  • Add test vectors, at least using b2sum --length 160
  • Add BLAKE2b-160 to the List of Algorithms

Flaky tests

Bug description

During a recent merge, we noticed that suddenly coverage went down in a part of the library that we hadn't touched. After some examination, we discovered that these two tests are flaky:

This test is flaky around 20% of the time:
test_wordlist_codec_error_detection

This one is flaky about 5% of the time:
test_wordlist_codec_different_data_different_encodings

To prove this, you can run:

$ while true; do; cargo test --features bip39,bip39-en,bip39-jp --test bip39; done

These two tests have something in common:

            OsRng.fill_bytes(&mut data);
            let ws = choose_wordlist();
            let ms = wordlist::encode(&data, ws).unwrap();

Need help to transfer token from trinity wallet to firely

Discussed in #28

Originally posted by nothingismagick December 11, 2020

👋 Welcome!

We’re using Discussions as a place to connect with other members of our community. We hope that you:

  • Ask questions you’re wondering about.
  • Share ideas.
  • Engage with other community members.
  • Welcome others and are open-minded. Remember that this is a community we
    build together 💪.

To get started, comment below with an introduction of yourself and tell us about what you do with this community.

Enhancements for ed25519 and x25519

Description

Naming convention in ed25519 and x25519 modules is messy, some convenient methods/traits are not implemented, some functionality is missing.

Motivation

  1. In ed25519 there is no reason to specify compressed public key. Compressed representation is only used for serialization, uncompressed public key is not used. Why not just public key? Proposal: remove or deprecate names with compressed word and introduce corresponding names without it.

  2. Unify xxx_LENGTH (ed25519::PUBLIC_KEY_LENGTH) and xxx_LEN (x25519::PUBLIC_KEY_LEN). LEN just looks ugly when other words are not shortened. Proposal: remove or deprecate xxx_LEN and introduce corresponding xxx_LENGTH.

  3. There's no naming convention for conversions to/from bytes for PublicKey types (eg. fn from_compressed_bytes(bs: &[u8]) -> Result<ed25519::PublicKey>). Proposal to implement the following methods and traits:

    • pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH]
    • pub fn as_slice(&self) -> &[u8]
    • pub fn from_bytes(bytes: [u8; PUBLIC_KEY_LENGTH]) -> Self or pub fn try_from_bytes(bytes: [u8; PUBLIC_KEY_LENGTH]) -> Result<Self>
    • impl Into<[u8; PUBLIC_KEY_LENGTH]> for &PublicKey
    • impl AsRef<[u8]> for PublicKey
    • impl From<[u8; PUBLIC_KEY_LENGTH]> for PublicKey or impl TryFrom<[u8; PUBLIC_KEY_LENGTH]> for PublicKey
  4. What is the endianness of to/from bytes conversions? Is it a "network" byte order or "native"? RFC 8032 states "All values are coded as octet strings, and integers are coded using little-endian convention", so LE must be the "network" byte order when converting x25519::SecretKey, PublicKeys, ed25519::Signature and x25519::SharedSecret as bytes as they are essentially big integers internally. ed25519::SecretKey is represented as seed bytes and not as a scalar that is derived from the seed, so the byte order here is natural. The old implementation is mixed up: ed25519::SecretKey used to_le_bytes()/from_le_bytes() which is not correct, and x25519::SecretKey bytes is scalar bytes in LE byte order used to_bytes()/from_bytes() with le infix missing. Also le functions suggest there are be variants which is confusing. Proposal: agree on "network" byte order which is LE (following RFC 8032), remove or deprecate to_le_bytes/from_le_bytes, use to_bytes()/from_bytes().

  5. Wrappers for PublicKey types do not currently implement common traits: Copy, Clone, PartialEq, Eq, Hash, Debug. Proposal: implement these traits. Rationale is trivial for each trait.

  6. Generate SecretKey with prng. This allows SecretKeys to be deterministically generated from seed. Proposal: implement generate_with<R>(rng: &mut R) constructor.

  7. Allow the use of the same secret key for ed25519 and x25519. Rationale: this is helpful as it simplifies key management: instead of two key pairs for signature and DH implementations can use only one (ed25519::SecretKey,ed25519::PublicKey) and convert it to x25519 keys when needed. Proposal: impl From<ed25519::SecretKey/PublicKey> for x25519::SecretKey/PublicKey.

  8. Why utils::rand::gens type is unrestricted? Proposal: Restrict to Sized + Copy. Rationale: Sized is obviously required to get size of T at compile time. Copy is needed by types that are copyable with memmove, ie. they are simple and don't contain pointers.

  9. Deprecate or just remove/rename/breaking change? If deprecate, then since which version? Proposal: deprecate old names since "1.0.0" version.

  10. What should be the convention for conversions for Copy types: to_bytes(&self) and impl From<&PublicKey> for [u8; 32] vs to_bytes(self) and impl From<PublicKey> for [u8; 32]? Proposal: follow this clippy convention and use the latter syntax.

Requirements

Write a list of what you want this feature to do.

  1. Address topics above.

Open questions (optional)

Use this section to ask any questions that are related to the feature.

Are you planning to do it yourself in a pull request?

Yes.

Provide `From<ed25519::PublicKey> for x25519::PublicKey` instead of `TryFrom`

Description

Is there a particular case where the conversion would fail? Particularly, the current implementation implies there might be a case where decompressing the ed25519 public key as a CompressedEdwardsY might fail. However, a comment also states that in the happy path of the conversion "pk is a valid ed25519::PublicKey". This is however already an invariant of the conversion (as we are converting from a ed25519::PublicKey), making one think the conversion is infallible in practice:

match curve25519_dalek::edwards::CompressedEdwardsY(y_bytes).decompress() {
    Some(decompressed_edwards) => {
        // `pk` is a valid `ed25519::PublicKey` hence contains valid `EdwardsPoint`.
        // x25519 uses Montgomery form, and `x25519::PublicKey` is just a `MontgomeryPoint`.
        // `MontgomeryPoint` can be constructed from `EdwardsPoint` with `to_montgomery()` method.
        // Can't construct `x25519::PublicKey` directly from `MontgomeryPoint`,
        // do it via intermediate bytes.
        Ok(PublicKey::from_bytes(decompressed_edwards.to_montgomery().to_bytes()))
    }
    None => Err(crate::error::Error::ConvertError {
        from: "ed25519 public key",
        to: "x25519 public key",
    }),
}

Motivation

If the conversion is in fact infallible, the trait should be From instead of TryFrom. Currently https://github.com/iotaledger/streams relies on this conversion being infallible. If it in fact isn't, I'd appreciate some clarification so that we can adjust our error handling.

Are you planning to do it yourself in a pull request?

Yes (upon confirmation)

Secret/public key wrapper guidelines

Description

Secret/public key wrapper guidelines are needed: naming convention, interoperability traits, security concerns.

Motivation

Wrappers for asymmetric and secret keys are common (ed25519, x25519, slip10). Often they use different names and argument/result types to do the same task and implement (or not) different traits, this is inconvenient. Also, secret key bytes can be leaked via local variables which is discouraged.

Requirements

This issue should introduce a guideline (maybe, a wiki page) and check the current implementations for conformance. A draft can be found here: wrappers-guidelines.

Are you planning to do it yourself in a pull request?

Yes.

bip39::wordlist::Error should implement Display

Description

The crate's main Error enum implements Display but the one on bip39.rs > wordlist doesn't.

Motivation

It's a standard and simplifies error handling on consumers.

Requirements

  1. Implement Display on the crypto::bip39::wordlist::Error

Are you planning to do it yourself in a pull request?

No.

mnemonic_to_seed() accepts any str and verify() also doesn't check for spaces

pub fn mnemonic_to_seed(m: &Mnemonic, p: &Passphrase, s: &mut Seed) {

accepts any str and
pub fn verify(ms: &str, wordlist: &Wordlist) -> Result<(), Error> {
also accepts mnemonics with a space added.

Should the verify function return an error if there is a space added or should the mnemonic_to_seed function trim spaces? Also speaks anything against calling the verify function inside of mnemonic_to_seed?

use crypto::{
    keys::bip39::{mnemonic_to_seed, wordlist},
    utils::rand,
};

fn main() {
    let mut entropy = [0u8; 32];
    rand::fill(&mut entropy).unwrap();
    let mnemonic = wordlist::encode(&entropy, &wordlist::ENGLISH).unwrap();

    let mut seed1 = [0u8; 64];
    mnemonic_to_seed(&mnemonic, "", &mut seed1);
    println!("seed {:?}", seed1);

    // add space after mnemonic
    let mnemonic_with_space = format!("{} ", mnemonic);
    crypto::keys::bip39::wordlist::verify(
        &mnemonic_with_space,
        &crypto::keys::bip39::wordlist::ENGLISH,
    )
    .unwrap();

    let mut seed2 = [0u8; 64];
    mnemonic_to_seed(&mnemonic_with_space, "", &mut seed2);
    println!("seed2 {:?}", seed2);
}

returns

seed1 [117, 243, 116, 246, 236, 156, 24, 14, 156, 200, 253, 204, 198, 202, 93, 73, 218, 90, 144, 218, 171, 118, 103, 134, 223, 233, 111, 3, 249, 194, 39, 111, 20, 138, 223, 95, 177, 16, 97, 85, 146, 32, 74, 73, 109, 52, 212, 83, 145, 199, 171, 231, 165, 26, 98, 187, 147, 181, 143, 212, 188, 113, 252, 9]
seed2 [143, 70, 253, 26, 35, 87, 146, 146, 203, 134, 198, 38, 253, 47, 231, 16, 251, 71, 22, 111, 152, 155, 144, 195, 196, 121, 232, 104, 20, 12, 235, 5, 55, 22, 182, 253, 135, 183, 123, 196, 29, 253, 63, 205, 194, 11, 219, 117, 4, 188, 126, 238, 27, 185, 159, 162, 132, 81, 48, 6, 249, 173, 170, 11]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.