mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-26 08:11:39 +00:00
Replace secp256k1
crate with libsecp256k1
. (#1029)
* Replace `secp256k1` crate with `libsecp256k1`. Unfortunately we could not implement `AsRef<[u8]>` for `SecretKey` as the crate does not provide a means to do so. * Fix `DecodingError` invocation. * Remove the cc for wasm * Revert "Remove the cc for wasm" This reverts commit 3a19db35e62931c6e9ffbff6c21f9b0d7ae5403a. * Fix CircleCI build
This commit is contained in:
committed by
Pierre Krieger
parent
43d9084735
commit
057b379541
@ -10,8 +10,8 @@ keywords = ["peer-to-peer", "libp2p", "networking"]
|
|||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["secio-secp256k1", "libp2p-websocket"]
|
default = ["secp256k1", "libp2p-websocket"]
|
||||||
secio-secp256k1 = ["libp2p-secio/secp256k1"]
|
secp256k1 = ["libp2p-core/secp256k1", "libp2p-secio/secp256k1"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
|
@ -27,7 +27,7 @@ protobuf = "2.3"
|
|||||||
quick-error = "1.2"
|
quick-error = "1.2"
|
||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
rw-stream-sink = { version = "0.1.1", path = "../misc/rw-stream-sink" }
|
rw-stream-sink = { version = "0.1.1", path = "../misc/rw-stream-sink" }
|
||||||
secp256k1 = { version = "0.12", features = ["rand"], optional = true }
|
libsecp256k1 = { version = "0.2.2", optional = true }
|
||||||
sha2 = "0.8.0"
|
sha2 = "0.8.0"
|
||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
tokio-executor = "0.1.4"
|
tokio-executor = "0.1.4"
|
||||||
@ -57,3 +57,5 @@ tokio-mock-task = "0.1"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["secp256k1"]
|
default = ["secp256k1"]
|
||||||
|
secp256k1 = ["libsecp256k1"]
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ impl Keypair {
|
|||||||
#[cfg(not(any(target_os = "emscripten", target_os = "unknown")))]
|
#[cfg(not(any(target_os = "emscripten", target_os = "unknown")))]
|
||||||
Rsa(ref pair) => pair.sign(msg),
|
Rsa(ref pair) => pair.sign(msg),
|
||||||
#[cfg(feature = "secp256k1")]
|
#[cfg(feature = "secp256k1")]
|
||||||
Secp256k1(ref pair) => Ok(pair.secret().sign(msg)),
|
Secp256k1(ref pair) => pair.secret().sign(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ impl PublicKey {
|
|||||||
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
|
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
|
||||||
#[allow(unused_mut)] // Due to conditional compilation.
|
#[allow(unused_mut)] // Due to conditional compilation.
|
||||||
let mut pubkey = protobuf::parse_from_bytes::<keys_proto::PublicKey>(bytes)
|
let mut pubkey = protobuf::parse_from_bytes::<keys_proto::PublicKey>(bytes)
|
||||||
.map_err(|e| DecodingError::new("Protobuf", e))?;
|
.map_err(|e| DecodingError::new("Protobuf").source(e))?;
|
||||||
|
|
||||||
match pubkey.get_Type() {
|
match pubkey.get_Type() {
|
||||||
keys_proto::KeyType::Ed25519 => {
|
keys_proto::KeyType::Ed25519 => {
|
||||||
@ -193,7 +193,7 @@ impl PublicKey {
|
|||||||
#[cfg(any(target_os = "emscripten", target_os = "unknown"))]
|
#[cfg(any(target_os = "emscripten", target_os = "unknown"))]
|
||||||
keys_proto::KeyType::RSA => {
|
keys_proto::KeyType::RSA => {
|
||||||
log::debug!("support for RSA was disabled at compile-time");
|
log::debug!("support for RSA was disabled at compile-time");
|
||||||
Err("Unsupported".to_string().into())
|
Err(DecodingError::new("Unsupported"))
|
||||||
},
|
},
|
||||||
#[cfg(feature = "secp256k1")]
|
#[cfg(feature = "secp256k1")]
|
||||||
keys_proto::KeyType::Secp256k1 => {
|
keys_proto::KeyType::Secp256k1 => {
|
||||||
|
@ -46,7 +46,7 @@ impl Keypair {
|
|||||||
pub fn decode(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
|
pub fn decode(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
|
||||||
ed25519::Keypair::from_bytes(kp)
|
ed25519::Keypair::from_bytes(kp)
|
||||||
.map(|k| { kp.zeroize(); Keypair(k) })
|
.map(|k| { kp.zeroize(); Keypair(k) })
|
||||||
.map_err(|e| DecodingError::new("Ed25519 keypair", e.compat()))
|
.map_err(|e| DecodingError::new("Ed25519 keypair").source(e.compat()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sign a message using the private key of this keypair.
|
/// Sign a message using the private key of this keypair.
|
||||||
@ -112,7 +112,7 @@ impl PublicKey {
|
|||||||
/// Decode a public key from a byte array as produced by `encode`.
|
/// Decode a public key from a byte array as produced by `encode`.
|
||||||
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
|
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
|
||||||
ed25519::PublicKey::from_bytes(k)
|
ed25519::PublicKey::from_bytes(k)
|
||||||
.map_err(|e| DecodingError::new("Ed25519 public key", e.compat()))
|
.map_err(|e| DecodingError::new("Ed25519 public key").source(e.compat()))
|
||||||
.map(PublicKey)
|
.map(PublicKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ impl SecretKey {
|
|||||||
pub fn from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
|
pub fn from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
|
||||||
let sk_bytes = sk_bytes.as_mut();
|
let sk_bytes = sk_bytes.as_mut();
|
||||||
let secret = ed25519::SecretKey::from_bytes(&*sk_bytes)
|
let secret = ed25519::SecretKey::from_bytes(&*sk_bytes)
|
||||||
.map_err(|e| DecodingError::new("Ed25519 secret key", e.compat()))?;
|
.map_err(|e| DecodingError::new("Ed25519 secret key").source(e.compat()))?;
|
||||||
sk_bytes.zeroize();
|
sk_bytes.zeroize();
|
||||||
Ok(SecretKey(secret))
|
Ok(SecretKey(secret))
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,12 @@ pub struct DecodingError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DecodingError {
|
impl DecodingError {
|
||||||
pub(crate) fn new(msg: &str, source: impl Error + Send + Sync + 'static) -> DecodingError {
|
pub(crate) fn new<S: ToString>(msg: S) -> Self {
|
||||||
DecodingError { msg: msg.to_string(), source: Some(Box::new(source)) }
|
Self { msg: msg.to_string(), source: None }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for DecodingError {
|
pub(crate) fn source(self, source: impl Error + Send + Sync + 'static) -> Self {
|
||||||
fn from(s: String) -> DecodingError {
|
Self { source: Some(Box::new(source)), .. self }
|
||||||
DecodingError { msg: s, source: None }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +61,12 @@ pub struct SigningError {
|
|||||||
|
|
||||||
/// An error during encoding of key material.
|
/// An error during encoding of key material.
|
||||||
impl SigningError {
|
impl SigningError {
|
||||||
pub(crate) fn new(msg: &str, source: impl Error + Send + Sync + 'static) -> SigningError {
|
pub(crate) fn new<S: ToString>(msg: S) -> Self {
|
||||||
SigningError { msg: msg.to_string(), source: Some(Box::new(source)) }
|
Self { msg: msg.to_string(), source: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn source(self, source: impl Error + Send + Sync + 'static) -> Self {
|
||||||
|
Self { source: Some(Box::new(source)), .. self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,12 +76,6 @@ impl fmt::Display for SigningError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for SigningError {
|
|
||||||
fn from(s: String) -> SigningError {
|
|
||||||
SigningError { msg: s, source: None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for SigningError {
|
impl Error for SigningError {
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
self.source.as_ref().map(|s| &**s as &dyn Error)
|
self.source.as_ref().map(|s| &**s as &dyn Error)
|
||||||
|
@ -41,7 +41,7 @@ impl Keypair {
|
|||||||
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
|
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
|
||||||
pub fn from_pkcs8(der: &mut [u8]) -> Result<Keypair, DecodingError> {
|
pub fn from_pkcs8(der: &mut [u8]) -> Result<Keypair, DecodingError> {
|
||||||
let kp = RsaKeyPair::from_pkcs8(Input::from(&der[..]))
|
let kp = RsaKeyPair::from_pkcs8(Input::from(&der[..]))
|
||||||
.map_err(|e| DecodingError::new("RSA PKCS#8 PrivateKeyInfo", e))?;
|
.map_err(|e| DecodingError::new("RSA PKCS#8 PrivateKeyInfo").source(e))?;
|
||||||
der.zeroize();
|
der.zeroize();
|
||||||
Ok(Keypair(Arc::new(kp)))
|
Ok(Keypair(Arc::new(kp)))
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ impl Keypair {
|
|||||||
let rng = SystemRandom::new();
|
let rng = SystemRandom::new();
|
||||||
match self.0.sign(&RSA_PKCS1_SHA256, &rng, &data, &mut signature) {
|
match self.0.sign(&RSA_PKCS1_SHA256, &rng, &data, &mut signature) {
|
||||||
Ok(()) => Ok(signature),
|
Ok(()) => Ok(signature),
|
||||||
Err(e) => Err(SigningError::new("RSA", e))
|
Err(e) => Err(SigningError::new("RSA").source(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ impl PublicKey {
|
|||||||
/// structure. See also `encode_x509`.
|
/// structure. See also `encode_x509`.
|
||||||
pub fn decode_x509(pk: &[u8]) -> Result<PublicKey, DecodingError> {
|
pub fn decode_x509(pk: &[u8]) -> Result<PublicKey, DecodingError> {
|
||||||
Asn1SubjectPublicKeyInfo::deserialize(pk.iter())
|
Asn1SubjectPublicKeyInfo::deserialize(pk.iter())
|
||||||
.map_err(|e| DecodingError::new("RSA X.509", e))
|
.map_err(|e| DecodingError::new("RSA X.509").source(e))
|
||||||
.map(|spki| spki.subjectPublicKey.0)
|
.map(|spki| spki.subjectPublicKey.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,18 +21,12 @@
|
|||||||
//! Secp256k1 keys.
|
//! Secp256k1 keys.
|
||||||
|
|
||||||
use asn1_der::{FromDerObject, DerObject};
|
use asn1_der::{FromDerObject, DerObject};
|
||||||
use lazy_static::lazy_static;
|
use rand::RngCore;
|
||||||
use sha2::{Digest as ShaDigestTrait, Sha256};
|
use sha2::{Digest as ShaDigestTrait, Sha256};
|
||||||
use secp256k1 as secp;
|
use secp256k1::{Message, Signature};
|
||||||
use secp::{Message, Signature};
|
use super::error::{DecodingError, SigningError};
|
||||||
use super::error::DecodingError;
|
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
// Cached `Secp256k1` context, to avoid recreating it every time.
|
|
||||||
lazy_static! {
|
|
||||||
static ref SECP: secp::Secp256k1<secp::All> = secp::Secp256k1::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A Secp256k1 keypair.
|
/// A Secp256k1 keypair.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Keypair {
|
pub struct Keypair {
|
||||||
@ -60,7 +54,7 @@ impl Keypair {
|
|||||||
/// Promote a Secp256k1 secret key into a keypair.
|
/// Promote a Secp256k1 secret key into a keypair.
|
||||||
impl From<SecretKey> for Keypair {
|
impl From<SecretKey> for Keypair {
|
||||||
fn from(secret: SecretKey) -> Keypair {
|
fn from(secret: SecretKey) -> Keypair {
|
||||||
let public = PublicKey(secp::key::PublicKey::from_secret_key(&SECP, &secret.0));
|
let public = PublicKey(secp256k1::PublicKey::from_secret_key(&secret.0));
|
||||||
Keypair { secret, public }
|
Keypair { secret, public }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,19 +68,21 @@ impl From<Keypair> for SecretKey {
|
|||||||
|
|
||||||
/// A Secp256k1 secret key.
|
/// A Secp256k1 secret key.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SecretKey(secp::key::SecretKey);
|
pub struct SecretKey(secp256k1::SecretKey);
|
||||||
|
|
||||||
/// View the bytes of the secret key.
|
|
||||||
impl AsRef<[u8]> for SecretKey {
|
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
&self.0[..]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SecretKey {
|
impl SecretKey {
|
||||||
/// Generate a new Secp256k1 secret key.
|
/// Generate a new Secp256k1 secret key.
|
||||||
pub fn generate() -> SecretKey {
|
pub fn generate() -> SecretKey {
|
||||||
SecretKey(secp::key::SecretKey::new(&mut secp::rand::thread_rng()))
|
let mut r = rand::thread_rng();
|
||||||
|
let mut b = [0; secp256k1::util::SECRET_KEY_SIZE];
|
||||||
|
// This is how it is done in `secp256k1::SecretKey::random` which
|
||||||
|
// we do not use here because it uses `rand::Rng` from rand-0.4.
|
||||||
|
loop {
|
||||||
|
r.fill_bytes(&mut b);
|
||||||
|
if let Ok(k) = secp256k1::SecretKey::parse(&b) {
|
||||||
|
return SecretKey(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a secret key from a byte slice, zeroing the slice on success.
|
/// Create a secret key from a byte slice, zeroing the slice on success.
|
||||||
@ -94,8 +90,8 @@ impl SecretKey {
|
|||||||
/// error is returned.
|
/// error is returned.
|
||||||
pub fn from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
|
pub fn from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
|
||||||
let sk_bytes = sk.as_mut();
|
let sk_bytes = sk.as_mut();
|
||||||
let secret = secp::key::SecretKey::from_slice(&*sk_bytes)
|
let secret = secp256k1::SecretKey::parse_slice(&*sk_bytes)
|
||||||
.map_err(|e| DecodingError::new("Secp256k1 secret key", e))?;
|
.map_err(|_| DecodingError::new("failed to parse secp256k1 secret key"))?;
|
||||||
sk_bytes.zeroize();
|
sk_bytes.zeroize();
|
||||||
Ok(SecretKey(secret))
|
Ok(SecretKey(secret))
|
||||||
}
|
}
|
||||||
@ -108,12 +104,12 @@ impl SecretKey {
|
|||||||
// TODO: Stricter parsing.
|
// TODO: Stricter parsing.
|
||||||
let der_obj = der.as_mut();
|
let der_obj = der.as_mut();
|
||||||
let obj: Vec<DerObject> = FromDerObject::deserialize((&*der_obj).iter())
|
let obj: Vec<DerObject> = FromDerObject::deserialize((&*der_obj).iter())
|
||||||
.map_err(|e| DecodingError::new("Secp256k1 DER ECPrivateKey", e))?;
|
.map_err(|e| DecodingError::new("Secp256k1 DER ECPrivateKey").source(e))?;
|
||||||
der_obj.zeroize();
|
der_obj.zeroize();
|
||||||
let sk_obj = obj.into_iter().nth(1)
|
let sk_obj = obj.into_iter().nth(1)
|
||||||
.ok_or_else(|| "Not enough elements in DER".to_string())?;
|
.ok_or_else(|| DecodingError::new("Not enough elements in DER"))?;
|
||||||
let mut sk_bytes: Vec<u8> = FromDerObject::from_der_object(sk_obj)
|
let mut sk_bytes: Vec<u8> = FromDerObject::from_der_object(sk_obj)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(DecodingError::new)?;
|
||||||
let sk = SecretKey::from_bytes(&mut sk_bytes)?;
|
let sk = SecretKey::from_bytes(&mut sk_bytes)?;
|
||||||
sk_bytes.zeroize();
|
sk_bytes.zeroize();
|
||||||
Ok(sk)
|
Ok(sk)
|
||||||
@ -123,36 +119,38 @@ impl SecretKey {
|
|||||||
/// ECDSA signature, as defined in [RFC3278].
|
/// ECDSA signature, as defined in [RFC3278].
|
||||||
///
|
///
|
||||||
/// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
|
/// [RFC3278]: https://tools.ietf.org/html/rfc3278#section-8.2
|
||||||
pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
|
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
|
||||||
let m = Message::from_slice(Sha256::digest(&msg).as_ref())
|
let m = Message::parse_slice(Sha256::digest(msg).as_ref())
|
||||||
.expect("digest output length doesn't match secp256k1 input length");
|
.map_err(|_| SigningError::new("failed to parse secp256k1 digest"))?;
|
||||||
SECP.sign(&m, &self.0).serialize_der()
|
secp256k1::sign(&m, &self.0)
|
||||||
|
.map(|s| s.0.serialize_der().as_ref().into())
|
||||||
|
.map_err(|_| SigningError::new("failed to create secp256k1 signature"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Secp256k1 public key.
|
/// A Secp256k1 public key.
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
pub struct PublicKey(secp::key::PublicKey);
|
pub struct PublicKey(secp256k1::PublicKey);
|
||||||
|
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
/// Verify the Secp256k1 signature on a message using the public key.
|
/// Verify the Secp256k1 signature on a message using the public key.
|
||||||
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
|
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
|
||||||
Message::from_slice(&Sha256::digest(msg))
|
Message::parse_slice(Sha256::digest(msg).as_ref())
|
||||||
.and_then(|m| Signature::from_der(sig)
|
.and_then(|m| Signature::parse_der(sig).map(|s| secp256k1::verify(&m, &s, &self.0)))
|
||||||
.and_then(|s| SECP.verify(&m, &s, &self.0))).is_ok()
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode the public key in compressed form, i.e. with one coordinate
|
/// Encode the public key in compressed form, i.e. with one coordinate
|
||||||
/// represented by a single bit.
|
/// represented by a single bit.
|
||||||
pub fn encode(&self) -> [u8; 33] {
|
pub fn encode(&self) -> [u8; 33] {
|
||||||
self.0.serialize()
|
self.0.serialize_compressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a public key from a byte slice in the the format produced
|
/// Decode a public key from a byte slice in the the format produced
|
||||||
/// by `encode`.
|
/// by `encode`.
|
||||||
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
|
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
|
||||||
secp256k1::PublicKey::from_slice(k)
|
secp256k1::PublicKey::parse_slice(k, Some(secp256k1::PublicKeyFormat::Compressed))
|
||||||
.map_err(|e| DecodingError::new("Secp256k1 public key", e))
|
.map_err(|_| DecodingError::new("failed to parse secp256k1 public key"))
|
||||||
.map(PublicKey)
|
.map(PublicKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,9 +163,9 @@ mod tests {
|
|||||||
fn secp256k1_secret_from_bytes() {
|
fn secp256k1_secret_from_bytes() {
|
||||||
let sk1 = SecretKey::generate();
|
let sk1 = SecretKey::generate();
|
||||||
let mut sk_bytes = [0; 32];
|
let mut sk_bytes = [0; 32];
|
||||||
sk_bytes.copy_from_slice(sk1.as_ref());
|
sk_bytes.copy_from_slice(&sk1.0.serialize()[..]);
|
||||||
let sk2 = SecretKey::from_bytes(&mut sk_bytes).unwrap();
|
let sk2 = SecretKey::from_bytes(&mut sk_bytes).unwrap();
|
||||||
assert_eq!(sk1.as_ref(), sk2.as_ref());
|
assert_eq!(sk1.0.serialize(), sk2.0.serialize());
|
||||||
assert_eq!(sk_bytes, [0; 32]);
|
assert_eq!(sk_bytes, [0; 32]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ libp2p-core = { version = "0.7.0", path = "../../core" }
|
|||||||
log = "0.4.6"
|
log = "0.4.6"
|
||||||
protobuf = "2.3"
|
protobuf = "2.3"
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
secp256k1 = { version = "0.12", features = ["rand"], optional = true }
|
|
||||||
aes-ctr = "0.3"
|
aes-ctr = "0.3"
|
||||||
aesni = { version = "0.6", features = ["nocheck"], optional = true }
|
aesni = { version = "0.6", features = ["nocheck"], optional = true }
|
||||||
twofish = "0.2.0"
|
twofish = "0.2.0"
|
||||||
@ -41,6 +40,7 @@ web-sys = { version = "0.3.10", features = ["Crypto", "CryptoKey", "SubtleCrypto
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["secp256k1"]
|
default = ["secp256k1"]
|
||||||
|
secp256k1 = []
|
||||||
aes-all = ["aesni"]
|
aes-all = ["aesni"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
Reference in New Issue
Block a user