mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-02 04:03:35 +00:00
Directory Restructure (#1163)
* Move tests -> testing * Directory restructure * Update Cargo.toml during restructure * Update Makefile during restructure * Fix arbitrary path
This commit is contained in:
75
crypto/eth2_keystore/src/json_keystore/checksum_module.rs
Normal file
75
crypto/eth2_keystore/src/json_keystore/checksum_module.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
//! Defines the JSON representation of the "checksum" module.
|
||||
//!
|
||||
//! This file **MUST NOT** contain any logic beyond what is required to serialize/deserialize the
|
||||
//! data structures. Specifically, there should not be any actual crypto logic in this file.
|
||||
|
||||
use super::hex_bytes::HexBytes;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{Map, Value};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Used for ensuring that serde only decodes valid checksum functions.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "String", into = "String")]
|
||||
pub enum ChecksumFunction {
|
||||
Sha256,
|
||||
}
|
||||
|
||||
impl Into<String> for ChecksumFunction {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
ChecksumFunction::Sha256 => "sha256".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for ChecksumFunction {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
match s.as_ref() {
|
||||
"sha256" => Ok(ChecksumFunction::Sha256),
|
||||
other => Err(format!("Unsupported checksum function: {}", other)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for ensuring serde only decodes an empty map.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "Value", into = "Value")]
|
||||
pub struct EmptyMap;
|
||||
|
||||
impl Into<Value> for EmptyMap {
|
||||
fn into(self) -> Value {
|
||||
Value::Object(Map::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Value> for EmptyMap {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(v: Value) -> Result<Self, Self::Error> {
|
||||
match v {
|
||||
Value::Object(map) if map.is_empty() => Ok(Self),
|
||||
_ => Err("Checksum params must be an empty map"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checksum module for `Keystore`.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ChecksumModule {
|
||||
pub function: ChecksumFunction,
|
||||
pub params: EmptyMap,
|
||||
pub message: HexBytes,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct Sha256Checksum(String);
|
||||
|
||||
impl Sha256Checksum {
|
||||
pub fn function() -> ChecksumFunction {
|
||||
ChecksumFunction::Sha256
|
||||
}
|
||||
}
|
||||
64
crypto/eth2_keystore/src/json_keystore/cipher_module.rs
Normal file
64
crypto/eth2_keystore/src/json_keystore/cipher_module.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! Defines the JSON representation of the "cipher" module.
|
||||
//!
|
||||
//! This file **MUST NOT** contain any logic beyond what is required to serialize/deserialize the
|
||||
//! data structures. Specifically, there should not be any actual crypto logic in this file.
|
||||
|
||||
use super::hex_bytes::HexBytes;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Used for ensuring that serde only decodes valid cipher functions.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "String", into = "String")]
|
||||
pub enum CipherFunction {
|
||||
Aes128Ctr,
|
||||
}
|
||||
|
||||
impl Into<String> for CipherFunction {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
CipherFunction::Aes128Ctr => "aes-128-ctr".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for CipherFunction {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
match s.as_ref() {
|
||||
"aes-128-ctr" => Ok(CipherFunction::Aes128Ctr),
|
||||
other => Err(format!("Unsupported cipher function: {}", other)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Cipher module representation.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CipherModule {
|
||||
pub function: CipherFunction,
|
||||
pub params: Cipher,
|
||||
pub message: HexBytes,
|
||||
}
|
||||
|
||||
/// Parameters for AES128 with ctr mode.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Aes128Ctr {
|
||||
pub iv: HexBytes,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged, deny_unknown_fields)]
|
||||
pub enum Cipher {
|
||||
Aes128Ctr(Aes128Ctr),
|
||||
}
|
||||
|
||||
impl Cipher {
|
||||
pub fn function(&self) -> CipherFunction {
|
||||
match &self {
|
||||
Cipher::Aes128Ctr(_) => CipherFunction::Aes128Ctr,
|
||||
}
|
||||
}
|
||||
}
|
||||
72
crypto/eth2_keystore/src/json_keystore/hex_bytes.rs
Normal file
72
crypto/eth2_keystore/src/json_keystore/hex_bytes.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// To allow serde to encode/decode byte arrays from HEX ASCII strings.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "String", into = "String")]
|
||||
pub struct HexBytes(Vec<u8>);
|
||||
|
||||
impl HexBytes {
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for HexBytes {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
Self(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for HexBytes {
|
||||
fn into(self) -> String {
|
||||
hex::encode(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for HexBytes {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
// Left-pad with a zero if there is not an even number of hex digits to ensure
|
||||
// `hex::decode` doesn't return an error.
|
||||
let s = if s.len() % 2 != 0 {
|
||||
format!("0{}", s)
|
||||
} else {
|
||||
s
|
||||
};
|
||||
|
||||
hex::decode(s)
|
||||
.map(Self)
|
||||
.map_err(|e| format!("Invalid hex: {}", e))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn decode(json: &str) -> Vec<u8> {
|
||||
serde_json::from_str::<HexBytes>(&format!("\"{}\"", json))
|
||||
.expect("should decode json")
|
||||
.as_bytes()
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn odd_hex_bytes() {
|
||||
let empty: Vec<u8> = vec![];
|
||||
|
||||
assert_eq!(decode(""), empty, "should decode nothing");
|
||||
assert_eq!(decode("00"), vec![0], "should decode 00");
|
||||
assert_eq!(decode("0"), vec![0], "should decode 0");
|
||||
assert_eq!(decode("01"), vec![1], "should decode 01");
|
||||
assert_eq!(decode("1"), vec![1], "should decode 1");
|
||||
assert_eq!(decode("0101"), vec![1, 1], "should decode 0101");
|
||||
assert_eq!(decode("101"), vec![1, 1], "should decode 101");
|
||||
}
|
||||
}
|
||||
128
crypto/eth2_keystore/src/json_keystore/kdf_module.rs
Normal file
128
crypto/eth2_keystore/src/json_keystore/kdf_module.rs
Normal file
@@ -0,0 +1,128 @@
|
||||
//! Defines the JSON representation of the "kdf" module.
|
||||
//!
|
||||
//! This file **MUST NOT** contain any logic beyond what is required to serialize/deserialize the
|
||||
//! data structures. Specifically, there should not be any actual crypto logic in this file.
|
||||
|
||||
use super::hex_bytes::HexBytes;
|
||||
use crypto::sha2::Sha256;
|
||||
use crypto::{hmac::Hmac, mac::Mac};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// KDF module representation.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct KdfModule {
|
||||
pub function: KdfFunction,
|
||||
pub params: Kdf,
|
||||
pub message: EmptyString,
|
||||
}
|
||||
|
||||
/// Used for ensuring serde only decodes an empty string.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "String", into = "String")]
|
||||
pub struct EmptyString;
|
||||
|
||||
impl Into<String> for EmptyString {
|
||||
fn into(self) -> String {
|
||||
"".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for EmptyString {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
match s.as_ref() {
|
||||
"" => Ok(Self),
|
||||
_ => Err("kdf message must be empty"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged, deny_unknown_fields)]
|
||||
pub enum Kdf {
|
||||
Scrypt(Scrypt),
|
||||
Pbkdf2(Pbkdf2),
|
||||
}
|
||||
|
||||
impl Kdf {
|
||||
pub fn function(&self) -> KdfFunction {
|
||||
match &self {
|
||||
Kdf::Pbkdf2(_) => KdfFunction::Pbkdf2,
|
||||
Kdf::Scrypt(_) => KdfFunction::Scrypt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// PRF for use in `pbkdf2`.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub enum Prf {
|
||||
#[serde(rename = "hmac-sha256")]
|
||||
HmacSha256,
|
||||
}
|
||||
|
||||
impl Prf {
|
||||
pub fn mac(&self, password: &[u8]) -> impl Mac {
|
||||
match &self {
|
||||
_hmac_sha256 => Hmac::new(Sha256::new(), password),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Prf {
|
||||
fn default() -> Self {
|
||||
Prf::HmacSha256
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters for `pbkdf2` key derivation.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Pbkdf2 {
|
||||
pub c: u32,
|
||||
pub dklen: u32,
|
||||
pub prf: Prf,
|
||||
pub salt: HexBytes,
|
||||
}
|
||||
|
||||
/// Used for ensuring that serde only decodes valid KDF functions.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(try_from = "String", into = "String")]
|
||||
pub enum KdfFunction {
|
||||
Scrypt,
|
||||
Pbkdf2,
|
||||
}
|
||||
|
||||
impl Into<String> for KdfFunction {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
KdfFunction::Scrypt => "scrypt".into(),
|
||||
KdfFunction::Pbkdf2 => "pbkdf2".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for KdfFunction {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
match s.as_ref() {
|
||||
"scrypt" => Ok(KdfFunction::Scrypt),
|
||||
"pbkdf2" => Ok(KdfFunction::Pbkdf2),
|
||||
other => Err(format!("Unsupported kdf function: {}", other)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters for `scrypt` key derivation.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Scrypt {
|
||||
pub dklen: u32,
|
||||
pub n: u32,
|
||||
pub r: u32,
|
||||
pub p: u32,
|
||||
pub salt: HexBytes,
|
||||
}
|
||||
52
crypto/eth2_keystore/src/json_keystore/mod.rs
Normal file
52
crypto/eth2_keystore/src/json_keystore/mod.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
//! This module intends to separate the JSON representation of the keystore from the actual crypto
|
||||
//! logic.
|
||||
//!
|
||||
//! This module **MUST NOT** contain any logic beyond what is required to serialize/deserialize the
|
||||
//! data structures. Specifically, there should not be any actual crypto logic in this file.
|
||||
|
||||
mod checksum_module;
|
||||
mod cipher_module;
|
||||
mod hex_bytes;
|
||||
mod kdf_module;
|
||||
|
||||
pub use checksum_module::{ChecksumModule, EmptyMap, Sha256Checksum};
|
||||
pub use cipher_module::{Aes128Ctr, Cipher, CipherModule};
|
||||
pub use hex_bytes::HexBytes;
|
||||
pub use kdf_module::{EmptyString, Kdf, KdfModule, Pbkdf2, Prf, Scrypt};
|
||||
pub use uuid::Uuid;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::*;
|
||||
|
||||
/// JSON representation of [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335) keystore.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct JsonKeystore {
|
||||
pub crypto: Crypto,
|
||||
pub uuid: Uuid,
|
||||
pub path: String,
|
||||
pub pubkey: String,
|
||||
pub version: Version,
|
||||
}
|
||||
|
||||
/// Version for `JsonKeystore`.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize_repr, Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum Version {
|
||||
V4 = 4,
|
||||
}
|
||||
|
||||
impl Version {
|
||||
pub fn four() -> Self {
|
||||
Version::V4
|
||||
}
|
||||
}
|
||||
|
||||
/// Crypto module for keystore.
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Crypto {
|
||||
pub kdf: KdfModule,
|
||||
pub checksum: ChecksumModule,
|
||||
pub cipher: CipherModule,
|
||||
}
|
||||
Reference in New Issue
Block a user