Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 5 additions & 10 deletions acvm-repo/acvm/src/pwg/blackbox/signature/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,21 @@ use acvm_blackbox_solver::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify};

use crate::{
OpcodeResolutionError,
pwg::{
blackbox::utils::{to_u8_array, to_u8_vec},
insert_value,
},
pwg::{blackbox::utils::to_u8_array, insert_value},
};

pub(crate) fn secp256k1_prehashed<F: AcirField>(
initial_witness: &mut WitnessMap<F>,
public_key_x_inputs: &[FunctionInput<F>; 32],
public_key_y_inputs: &[FunctionInput<F>; 32],
signature_inputs: &[FunctionInput<F>; 64],
hashed_message_inputs: &[FunctionInput<F>],
hashed_message_inputs: &[FunctionInput<F>; 32],
output: Witness,
) -> Result<(), OpcodeResolutionError<F>> {
let hashed_message = to_u8_vec(initial_witness, hashed_message_inputs)?;

let pub_key_x: [u8; 32] = to_u8_array(initial_witness, public_key_x_inputs)?;
let pub_key_y: [u8; 32] = to_u8_array(initial_witness, public_key_y_inputs)?;
let signature: [u8; 64] = to_u8_array(initial_witness, signature_inputs)?;
let hashed_message: [u8; 32] = to_u8_array(initial_witness, hashed_message_inputs)?;

let is_valid = ecdsa_secp256k1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?;

Expand All @@ -37,14 +33,13 @@ pub(crate) fn secp256r1_prehashed<F: AcirField>(
public_key_x_inputs: &[FunctionInput<F>; 32],
public_key_y_inputs: &[FunctionInput<F>; 32],
signature_inputs: &[FunctionInput<F>; 64],
hashed_message_inputs: &[FunctionInput<F>],
hashed_message_inputs: &[FunctionInput<F>; 32],
output: Witness,
) -> Result<(), OpcodeResolutionError<F>> {
let hashed_message = to_u8_vec(initial_witness, hashed_message_inputs)?;

let pub_key_x: [u8; 32] = to_u8_array(initial_witness, public_key_x_inputs)?;
let pub_key_y: [u8; 32] = to_u8_array(initial_witness, public_key_y_inputs)?;
let signature: [u8; 64] = to_u8_array(initial_witness, signature_inputs)?;
let hashed_message: [u8; 32] = to_u8_array(initial_witness, hashed_message_inputs)?;

let is_valid = ecdsa_secp256r1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?;

Expand Down
2 changes: 2 additions & 0 deletions acvm-repo/acvm_js/src/black_box_solvers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub fn ecdsa_secp256k1_verify(
public_key_y_bytes: &[u8],
signature: &[u8],
) -> bool {
let hashed_msg: &[u8; 32] = hashed_msg.try_into().unwrap();
let public_key_x_bytes: &[u8; 32] = public_key_x_bytes.try_into().unwrap();
let public_key_y_bytes: &[u8; 32] = public_key_y_bytes.try_into().unwrap();
let signature: &[u8; 64] = signature.try_into().unwrap();
Expand All @@ -66,6 +67,7 @@ pub fn ecdsa_secp256r1_verify(
public_key_y_bytes: &[u8],
signature: &[u8],
) -> bool {
let hashed_msg: &[u8; 32] = hashed_msg.try_into().unwrap();
let public_key_x_bytes: &[u8; 32] = public_key_x_bytes.try_into().unwrap();
let public_key_y_bytes: &[u8; 32] = public_key_y_bytes.try_into().unwrap();
let signature: &[u8; 64] = signature.try_into().unwrap();
Expand Down
4 changes: 2 additions & 2 deletions acvm-repo/blackbox_solver/src/ecdsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod secp256k1;
mod secp256r1;

pub fn ecdsa_secp256k1_verify(
hashed_msg: &[u8],
hashed_msg: &[u8; 32],
public_key_x: &[u8; 32],
public_key_y: &[u8; 32],
signature: &[u8; 64],
Expand All @@ -13,7 +13,7 @@ pub fn ecdsa_secp256k1_verify(
}

pub fn ecdsa_secp256r1_verify(
hashed_msg: &[u8],
hashed_msg: &[u8; 32],
public_key_x: &[u8; 32],
public_key_y: &[u8; 32],
signature: &[u8; 64],
Expand Down
13 changes: 1 addition & 12 deletions acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use k256::{
use k256::{Scalar, ecdsa::Signature};

pub(super) fn verify_signature(
hashed_msg: &[u8],
hashed_msg: &[u8; 32],
public_key_x_bytes: &[u8; 32],
public_key_y_bytes: &[u8; 32],
signature: &[u8; 64],
Expand Down Expand Up @@ -137,15 +137,4 @@ mod secp256k1_tests {

assert!(!valid);
}

#[test]
#[ignore = "ECDSA verification does not currently handle long hashes correctly"]
fn trims_overly_long_hashes_to_correct_length() {
let mut long_hashed_message = HASHED_MESSAGE.to_vec();
long_hashed_message.push(0xff);

let valid = verify_signature(&long_hashed_message, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE);

assert!(valid);
}
}
18 changes: 12 additions & 6 deletions acvm-repo/brillig_vm/src/black_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,18 @@ pub(crate) fn evaluate_black_box<F: AcirField, Solver: BlackBoxFunctionSolver<F>
let hashed_msg = to_u8_vec(read_heap_vector(memory, hashed_msg));

let result = match op {
BlackBoxOp::EcdsaSecp256k1 { .. } => {
ecdsa_secp256k1_verify(&hashed_msg, &public_key_x, &public_key_y, &signature)?
}
BlackBoxOp::EcdsaSecp256r1 { .. } => {
ecdsa_secp256r1_verify(&hashed_msg, &public_key_x, &public_key_y, &signature)?
}
BlackBoxOp::EcdsaSecp256k1 { .. } => ecdsa_secp256k1_verify(
&hashed_msg.try_into().unwrap(),
&public_key_x,
&public_key_y,
&signature,
)?,
BlackBoxOp::EcdsaSecp256r1 { .. } => ecdsa_secp256r1_verify(
&hashed_msg.try_into().unwrap(),
&public_key_x,
&public_key_y,
&signature,
)?,
_ => unreachable!("`BlackBoxOp` is guarded against being a non-ecdsa operation"),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,9 +695,9 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option<usize> {
// witness at a time.
BlackBoxFunc::RANGE => Some(1),

// Signature verification algorithms will take in a variable
// number of inputs, since the message/hashed-message can vary in size.
BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => None,
// 64 bytes for the signature, 32 bytes for the hashed message,
// and 32 bytes each for the x and y coordinates of the public key, plus a predicate.
BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => Some(161),

// Inputs for multi scalar multiplication is an arbitrary number of [point, scalar] pairs.
BlackBoxFunc::MultiScalarMul => None,
Expand Down
26 changes: 22 additions & 4 deletions compiler/noirc_evaluator/src/ssa/interpreter/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,18 @@ impl<W: Write> Interpreter<'_, W> {
size: s_len,
})
})?;
let m_len = m.len();
let m_array: &[u8; 32] = &m.try_into().map_err(|_| {
InterpreterError::Internal(InternalError::InvalidInputSize {
expected_size: 32,
size: m_len,
})
})?;
let result = if predicate {
acvm::blackbox_solver::ecdsa_secp256k1_verify(&m, x_array, y_array, s_array)
.map_err(Self::convert_error)?
acvm::blackbox_solver::ecdsa_secp256k1_verify(
m_array, x_array, y_array, s_array,
)
.map_err(Self::convert_error)?
} else {
true
};
Expand Down Expand Up @@ -230,10 +239,19 @@ impl<W: Write> Interpreter<'_, W> {
size: s_len,
})
})?;
let m_len = m.len();
let m_array: &[u8; 32] = &m.try_into().map_err(|_| {
InterpreterError::Internal(InternalError::InvalidInputSize {
expected_size: 32,
size: m_len,
})
})?;

let result = if predicate {
acvm::blackbox_solver::ecdsa_secp256r1_verify(&m, x_array, y_array, s_array)
.map_err(Self::convert_error)?
acvm::blackbox_solver::ecdsa_secp256r1_verify(
m_array, x_array, y_array, s_array,
)
.map_err(Self::convert_error)?
} else {
true
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ pub(super) fn simplify_hash(
}

type ECDSASignatureVerifier = fn(
hashed_msg: &[u8],
hashed_msg: &[u8; 32],
public_key_x: &[u8; 32],
public_key_y: &[u8; 32],
signature: &[u8; 64],
Expand Down Expand Up @@ -350,7 +350,9 @@ pub(super) fn simplify_signature(
.expect("ECDSA public key fields are 32 bytes");
let signature: [u8; 64] =
to_u8_vec(dfg, signature).try_into().expect("ECDSA signatures are 64 bytes");
let hashed_message: Vec<u8> = to_u8_vec(dfg, hashed_message);
let hashed_message: [u8; 32] = to_u8_vec(dfg, hashed_message)
.try_into()
.expect("ECDSA message hashes are 32 bytes");

let valid_signature =
signature_verifier(&hashed_message, &public_key_x, &public_key_y, &signature)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,6 @@ pub(crate) fn get_slice(
}
}

/// Interpret the input as a slice, then map each element.
/// Returns the values in the slice and the original type.
pub(crate) fn get_slice_map<T>(
interner: &NodeInterner,
(value, location): (Value, Location),
f: impl Fn((Value, Location)) -> IResult<T>,
) -> IResult<(Vec<T>, Type)> {
let (values, typ) = get_slice(interner, (value, location))?;
let values = try_vecmap(values, |value| f((value, location)))?;
Ok((values, typ))
}

/// Interpret the input as an array, then map each element.
/// Returns the values in the array and the original array type.
pub(crate) fn get_array_map<T>(
Expand Down
12 changes: 3 additions & 9 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{
Interpreter,
builtin::builtin_helpers::{
check_arguments, check_one_argument, check_three_arguments, check_two_arguments,
get_array_map, get_bool, get_field, get_fixed_array_map, get_slice_map, get_struct_field,
get_array_map, get_bool, get_field, get_fixed_array_map, get_struct_field,
get_struct_fields, get_u8, get_u32, get_u64, to_byte_slice, to_struct,
},
};
Expand Down Expand Up @@ -170,21 +170,15 @@ fn ecdsa_secp256_verify(
interner: &mut NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
f: impl Fn(&[u8], &[u8; 32], &[u8; 32], &[u8; 64]) -> Result<bool, BlackBoxResolutionError>,
f: impl Fn(&[u8; 32], &[u8; 32], &[u8; 32], &[u8; 64]) -> Result<bool, BlackBoxResolutionError>,
) -> IResult<Value> {
let [pub_key_x, pub_key_y, sig, msg_hash, predicate] = check_arguments(arguments, location)?;
assert_eq!(predicate.0, Value::Bool(true), "verify_signature predicate should be true");

let (pub_key_x, _) = get_fixed_array_map(interner, pub_key_x, get_u8)?;
let (pub_key_y, _) = get_fixed_array_map(interner, pub_key_y, get_u8)?;
let (sig, _) = get_fixed_array_map(interner, sig, get_u8)?;

// Hash can be an array or slice.
let (msg_hash, _) = if matches!(msg_hash.0.get_type().as_ref(), Type::Array(_, _)) {
get_array_map(interner, msg_hash.clone(), get_u8)?
} else {
get_slice_map(interner, msg_hash, get_u8)?
};
let (msg_hash, _) = get_fixed_array_map(interner, msg_hash.clone(), get_u8)?;

let is_valid = f(&msg_hash, &pub_key_x, &pub_key_y, &sig)
.map_err(|e| InterpreterError::BlackBoxError(e, location))?;
Expand Down
8 changes: 4 additions & 4 deletions noir_stdlib/src/ecdsa_secp256k1.nr
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@
/// For more context regarding malleability you can reference BIP 0062.
/// - the hash of the message, as a vector of bytes
/// - output: false for failure and true for success
pub fn verify_signature<let N: u32>(
pub fn verify_signature(
public_key_x: [u8; 32],
public_key_y: [u8; 32],
signature: [u8; 64],
message_hash: [u8; N],
message_hash: [u8; 32],
) -> bool
// docs:end:ecdsa_secp256k1
{
_verify_signature(public_key_x, public_key_y, signature, message_hash, true)
}

#[foreign(ecdsa_secp256k1)]
pub fn _verify_signature<let N: u32>(
pub fn _verify_signature(
public_key_x: [u8; 32],
public_key_y: [u8; 32],
signature: [u8; 64],
message_hash: [u8; N],
message_hash: [u8; 32],
predicate: bool,
) -> bool {}
8 changes: 4 additions & 4 deletions noir_stdlib/src/ecdsa_secp256r1.nr
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
// docs:start:ecdsa_secp256r1
pub fn verify_signature<let N: u32>(
pub fn verify_signature(
public_key_x: [u8; 32],
public_key_y: [u8; 32],
signature: [u8; 64],
message_hash: [u8; N],
message_hash: [u8; 32],
) -> bool
// docs:end:ecdsa_secp256r1
{
_verify_signature(public_key_x, public_key_y, signature, message_hash, true)
}

#[foreign(ecdsa_secp256r1)]
pub fn _verify_signature<let N: u32>(
pub fn _verify_signature(
public_key_x: [u8; 32],
public_key_y: [u8; 32],
signature: [u8; 64],
message_hash: [u8; N],
message_hash: [u8; 32],
predicate: bool,
) -> bool {}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading