Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add quick_error to all of our error ADTS #17

Merged
merged 8 commits into from
Oct 19, 2018
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ed25519-dalek = "~0.8"
curve25519-dalek = "0.20" #Can get rid of it as soon as https://github.com/dalek-cryptography/ed25519-dalek/issues/39 is resolved
clear_on_drop = "~0.2"
gridiron = "0.2"
quick-error = "~1.2"

[profile.dev]
opt-level = 2 # Build deps with optimization, don't build ourselves with optimization
Expand Down
104 changes: 62 additions & 42 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,39 +54,53 @@ impl<CR: rand::CryptoRng + rand::RngCore> Api<Sha256, Ed25519, RandomBytes<CR>>
}
}

/// Errors generated by the API
#[derive(Debug, PartialEq)]
pub enum ApiErr {
DecryptFailed,
InvalidAuthHash,
InvalidSignature,
InvalidPublicKey(String),
InvalidReencryptionKey,
InputWrongSize(usize), // necessary size
quick_error!{
/// Errors generated by the API
#[derive(Debug, PartialEq)]
pub enum ApiErr {
DecryptFailed(err: internal::InternalError){
display("The decryption failed. Ensure you're using the correct PrivateKey.")
cause(err)
}
InvalidEncryptedMessageSignature(err: internal::InternalError){
display("The signature of the encrypted value could not be verified.")
cause(err)
}
InvalidPublicKey(err: internal::homogeneouspoint::PointErr){
display("The public key was not valid. Ensure it was generated from a valid PrivateKey.")
from()
cause(err)
}
InvalidTransformKey(err: internal::InternalError){
cause(err)
display("The transform key signature was incorrect.")
}
InputWrongSize(typ: &'static str, req_size: usize){
display("The input value was the wrong size. Expected {} bytes for type {}.", req_size, typ)
}
DecodeFailure(err: internal::bytedecoder::DecodeErr){
display("The bytes could not be decoded into the appropriate data type.")
cause(err)
from()
}
}
}

type Result<T> = std::result::Result<T, ApiErr>;

impl From<internal::InternalError> for ApiErr {
fn from(err: internal::InternalError) -> Self {
match err {
internal::InternalError::AuthHashMatchFailed => ApiErr::InvalidAuthHash,
internal::InternalError::SignatureFailed => ApiErr::InvalidSignature,
internal::InternalError::PrivateKeyFailed
| internal::InternalError::BytesDecodeFailed(_) => ApiErr::DecryptFailed,
internal::InternalError::PointInvalid(_) => {
ApiErr::InvalidPublicKey("The point was not on the curve".to_string())
internal::InternalError::AuthHashMatchFailed => ApiErr::DecryptFailed(err),
internal::InternalError::InvalidEncryptedMessageSignature => {
ApiErr::InvalidEncryptedMessageSignature(err)
}
internal::InternalError::CorruptReencryptionKey => ApiErr::InvalidReencryptionKey,
internal::InternalError::PointInvalid(p_err) => ApiErr::InvalidPublicKey(p_err),
internal::InternalError::CorruptReencryptionKey => ApiErr::InvalidTransformKey(err),
}
}
}

impl From<internal::bytedecoder::DecodeErr> for ApiErr {
fn from(e: DecodeErr) -> Self {
ApiErr::from(internal::InternalError::from(e))
}
}

/// Hashed but not encrypted Plaintext used for envelope encryption
new_bytes_type!(DerivedSymmetricKey, 32);

Expand Down Expand Up @@ -330,7 +344,7 @@ impl EncryptedValue {
ev: EncryptedValue,
) -> std::result::Result<
internal::SignedValue<internal::EncryptedValue<Fp256>>,
internal::InternalError,
internal::bytedecoder::DecodeErr,
> {
match ev {
EncryptedValue::EncryptedOnceValue {
Expand Down Expand Up @@ -454,11 +468,14 @@ impl HashedValue {
const ENCODED_SIZE_BYTES: usize = HomogeneousPoint::<Fp2Elem<Fp256>>::ENCODED_SIZE_BYTES;

pub fn new(bytes: [u8; HashedValue::ENCODED_SIZE_BYTES]) -> Result<Self> {
HomogeneousPoint::<Fp2Elem<Fp256>>::decode(bytes.to_vec())
.map(|hpoint| HashedValue {
bytes,
_internal_value: hpoint,
}).map_err(ApiErr::from)
Ok(
HomogeneousPoint::<Fp2Elem<Fp256>>::decode(bytes.to_vec()).map(|hpoint| {
HashedValue {
bytes,
_internal_value: hpoint,
}
})?,
)
}
pub fn bytes(&self) -> &[u8; HashedValue::ENCODED_SIZE_BYTES] {
&self.bytes
Expand All @@ -469,7 +486,10 @@ impl HashedValue {
dest.copy_from_slice(bytes);
Ok(HashedValue::new(dest)?)
} else {
Err(ApiErr::InputWrongSize(HashedValue::ENCODED_SIZE_BYTES))
Err(ApiErr::InputWrongSize(
"HashedValue",
HashedValue::ENCODED_SIZE_BYTES,
))
}
}
}
Expand Down Expand Up @@ -870,7 +890,7 @@ impl<R: RandomBytesGen, H: Sha256Hashing, S: Ed25519Signing> CryptoOps for Api<H
) -> Result<EncryptedValue> {
let plaintext = self.gen_plaintext();
let random_private_key = self.random_private_key();
internal::reencrypt(
EncryptedValue::try_from(internal::reencrypt(
transform_key._internal_key,
EncryptedValue::try_into(encrypted_value)?,
internal::PrivateKey::from(random_private_key),
Expand All @@ -880,8 +900,7 @@ impl<R: RandomBytesGen, H: Sha256Hashing, S: Ed25519Signing> CryptoOps for Api<H
&self.sha_256,
&self.curve_points,
&self.pairing,
).map_err(ApiErr::from)
.and_then(EncryptedValue::try_from)
)?)
}
}

Expand Down Expand Up @@ -923,13 +942,13 @@ impl PublicKey {
pub const ENCODED_SIZE_BYTES: usize = Fp256::ENCODED_SIZE_BYTES * 2;

fn try_from(internal_key: &internal::PublicKey<Fp256>) -> Result<PublicKey> {
internal_key
Ok(internal_key
.to_byte_vectors_32()
.map(|(x, y)| PublicKey {
x,
y,
_internal_key: *internal_key,
}).ok_or_else(|| ApiErr::InvalidPublicKey("Public key was invalid.".to_string()))
}).ok_or_else(|| internal::homogeneouspoint::PointErr::ZeroPoint)?)
}

pub fn new(
Expand All @@ -938,10 +957,8 @@ impl PublicKey {
[u8; Fp256::ENCODED_SIZE_BYTES],
),
) -> Result<PublicKey> {
let x = Fp256::decode(x_bytes.to_vec())
.map_err(|e| ApiErr::InvalidPublicKey(format!("x decode failed: {:?}", e)))?;
let y = Fp256::decode(y_bytes.to_vec())
.map_err(|e| ApiErr::InvalidPublicKey(format!("y decode failed: {:?}", e)))?;
let x = Fp256::from(x_bytes);
let y = Fp256::from(y_bytes);
let i_pk = internal::PublicKey::from_x_y_fp256(x, y)?;
PublicKey::try_from(&i_pk)
}
Expand All @@ -956,7 +973,10 @@ impl PublicKey {

Ok(PublicKey::new((x_dest, y_dest))?)
} else {
Err(ApiErr::InputWrongSize(PublicKey::ENCODED_SIZE_BYTES))
Err(ApiErr::InputWrongSize(
"PublicKey",
PublicKey::ENCODED_SIZE_BYTES,
))
}
}
pub fn bytes_x_y(&self) -> (&[u8; 32], &[u8; 32]) {
Expand Down Expand Up @@ -1486,7 +1506,7 @@ pub(crate) mod test {
assert_eq!(auth_hash_from_fixed, auth_hash_from_slice.unwrap());

assert_eq!(
ApiErr::InputWrongSize(32),
ApiErr::InputWrongSize("AuthHash", 32),
AuthHash::new_from_slice(&input[..30]).unwrap_err()
)
}
Expand All @@ -1501,7 +1521,7 @@ pub(crate) mod test {
assert_eq!(hv_from_fixed.unwrap(), hv_from_slice.unwrap());

assert_eq!(
ApiErr::InputWrongSize(128),
ApiErr::InputWrongSize("HashedValue", 128),
HashedValue::new_from_slice(&input[..30]).unwrap_err()
)
}
Expand All @@ -1517,7 +1537,7 @@ pub(crate) mod test {
assert_eq!(pk_from_fixed.unwrap(), pk_from_slice.unwrap());

assert_eq!(
ApiErr::InputWrongSize(64),
ApiErr::InputWrongSize("PublicKey", 64),
PublicKey::new_from_slice((&input.0[..30], &input.1[..32])).unwrap_err()
)
}
Expand Down
23 changes: 13 additions & 10 deletions src/internal/bytedecoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,19 @@ impl BytesDecoder for Fp256 {
}
}

#[derive(Debug)]
pub enum DecodeErr {
BytesNotCorrectLength {
required_length: usize,
bad_bytes: ByteVector,
},
BytesInvalid {
message: String,
bad_bytes: ByteVector,
},
quick_error! {
#[derive(Debug, PartialEq, Eq)]
pub enum DecodeErr {
BytesNotCorrectLength {
required_length: usize,
bad_bytes: ByteVector,
} {
}
BytesInvalid {
message: String,
bad_bytes: ByteVector,
}{}
}
}

/// Needed for error handing when ArrayVec.into_inner is called on an instance that is not
Expand Down
1 change: 0 additions & 1 deletion src/internal/curve.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// use gmp::mpz::Mpz;
use gridiron::fp_256::Fp256;
use internal::fp2elem::Fp2Elem;
use internal::homogeneouspoint::HomogeneousPoint;
Expand Down
13 changes: 9 additions & 4 deletions src/internal/homogeneouspoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ use num_traits::Pow;
use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
use std::option::Option;

#[derive(Clone, Debug)]
pub enum PointErr {
PointNotOnCurve(Vec<u8>, Vec<u8>),
InvalidCoordinate(Vec<u8>, String),
quick_error! {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PointErr {
PointNotOnCurve(x: Vec<u8>, y: Vec<u8>) {
//Note that this will print the vectors, but since this error isn't exposed directly to the user that's not a huge concern IMO
display("The point represented by {:?},{:?} is not on the curve.", x, y)
}
ZeroPoint{}
}
}

///HomogeneousPoint which is either Zero or an x,y coordinate which has a z it carries
Expand Down
5 changes: 4 additions & 1 deletion src/internal/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ macro_rules! new_from_slice {
dest.copy_from_slice(bytes);
Ok($t::new(dest))
} else {
Err(ApiErr::InputWrongSize($t::ENCODED_SIZE_BYTES))
Err(ApiErr::InputWrongSize(
&stringify!($t),
$t::ENCODED_SIZE_BYTES,
))
}
}
};
Expand Down
44 changes: 17 additions & 27 deletions src/internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,16 @@ use api;
pub type ByteVector = Vec<u8>;
pub type ErrorOr<T> = Result<T, InternalError>;

#[derive(Debug)]
pub enum InternalError {
AuthHashMatchFailed,
SignatureFailed,
PrivateKeyFailed,
PointInvalid(PointErr),
BytesDecodeFailed(bytedecoder::DecodeErr),
CorruptReencryptionKey,
}

impl From<PointErr> for InternalError {
fn from(p: PointErr) -> InternalError {
InternalError::PointInvalid(p)
}
}

impl From<bytedecoder::DecodeErr> for InternalError {
fn from(decode_err: bytedecoder::DecodeErr) -> Self {
InternalError::BytesDecodeFailed(decode_err)
quick_error! {
#[derive(Debug, PartialEq, Eq)]
pub enum InternalError {
AuthHashMatchFailed {}
InvalidEncryptedMessageSignature {}
PointInvalid(err: PointErr) {
cause(err)
from()
}
CorruptReencryptionKey {}
}
}

Expand All @@ -79,9 +70,8 @@ impl<T: Field + Hashable32> PublicKey<T> {
}

impl PublicKey<Fp256> {
pub fn from_x_y_fp256(x: Fp256, y: Fp256) -> Result<PublicKey<Fp256>, InternalError> {
let result = HomogeneousPoint::from_x_y((x, y)).map(|value| PublicKey { value })?;
Ok(result)
pub fn from_x_y_fp256(x: Fp256, y: Fp256) -> ErrorOr<PublicKey<Fp256>> {
Ok(HomogeneousPoint::from_x_y((x, y)).map(|value| PublicKey { value })?)
}
}

Expand Down Expand Up @@ -481,7 +471,7 @@ where
+ Default,
{
verify_signed_value(signed_encrypted_value, signing).map_or(
Result::Err(InternalError::SignatureFailed),
Result::Err(InternalError::InvalidEncryptedMessageSignature),
|good_encrypted_value| match good_encrypted_value {
EncryptedValue::EncryptedOnce(encrypted_once_value) => {
let unverified_plaintext = decrypt_encrypted_once(
Expand Down Expand Up @@ -819,7 +809,7 @@ impl<FP: Field + NonAdjacentForm> ReencryptionKey<FP> {
///
/// # Return
/// ReencryptedValue - if the value could be successfully reencrypted
/// - Left(SignatureFailed|ReencryptionKeyIsCorrupt) - if the signatures weren't valid.
/// - Left(InvalidEncryptedMessageSignature|ReencryptionKeyIsCorrupt) - if the signatures weren't valid.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess Left isn't technically true here...
Do we have a standard way of documenting errors?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should say Err instead. I'll fix that.

pub fn reencrypt<FP, S, H>(
signed_reencryption_key: SignedValue<ReencryptionKey<FP>>,
signed_encrypted_value: SignedValue<EncryptedValue<FP>>,
Expand All @@ -830,7 +820,7 @@ pub fn reencrypt<FP, S, H>(
sha256: &H,
curve_points: &CurvePoints<FP>,
pairing: &Pairing<FP>,
) -> Result<SignedValue<EncryptedValue<FP>>, InternalError>
) -> ErrorOr<SignedValue<EncryptedValue<FP>>>
where
FP: Field
+ Hashable
Expand Down Expand Up @@ -873,7 +863,7 @@ where
signing_keypair,
ed25519,
)),
(None, _) => Err(InternalError::SignatureFailed),
(None, _) => Err(InternalError::InvalidEncryptedMessageSignature),
(_, None) => Err(InternalError::CorruptReencryptionKey),
}
}
Expand Down Expand Up @@ -1433,7 +1423,7 @@ mod test {
sha256,
&AlwaysFailVerifyEd25519Signing,
);
if let Err(InternalError::SignatureFailed) = decrypt_result {
if let Err(InternalError::InvalidEncryptedMessageSignature) = decrypt_result {
//pass
} else {
assert!(false, "Error should have been returned")
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ extern crate hex;
#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate quick_error;

#[macro_use]
mod internal; // this needs to come before `api` as api relies on macros defined in `internal`
pub mod api;
Expand Down