-
Notifications
You must be signed in to change notification settings - Fork 111
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
How to serialize/deserialize PublicKey? #40
Comments
I fixed /src/elliptic/curves/secp256_k1.rs#L317 fn from_bytes(bytes: &[u8]) -> Result<Secp256k1Point, ErrorKey> {
if bytes.len() < 1 {
return Err(ErrorKey::InvalidPublicKey);
}
let prefix = bytes[0];
let byte_len = bytes.len();
if byte_len == 33 && (prefix == 2 || prefix == 3) {
let result = PK::from_slice(bytes[..33]);
let test = result.map(|pk| Secp256k1Point {
purpose: "random",
ge: pk,
});
test.map_err(|_err| ErrorKey::InvalidPublicKey)
} else if byte_len == 65 && prefix == 4 {
let result = PK::from_slice(bytes[..65]);
let test = result.map(|pk| Secp256k1Point {
purpose: "random",
ge: pk,
});
test.map_err(|_err| ErrorKey::InvalidPublicKey)
} else {
Err(ErrorKey::InvalidPublicKey)
}
} |
Hi, @namuyan. A few comments:
Please let me know if (1) or (2) works for your application |
Thank you for comment! pub fn public_from_bytes(bytes: &[u8]) -> Result<Secp256k1Point, ErrorKey> {
if bytes.len() < 32 {
return Err(ErrorKey::InvalidPublicKey);
}
let prefix = bytes[0];
let byte_len = bytes.len();
let public =
if byte_len == 33 && (prefix == 2 || prefix == 3) {
PK::from_slice(bytes).map_err(|_err| ErrorKey::InvalidPublicKey)
} else if byte_len == 65 && prefix == 4 {
PK::from_slice(bytes).map_err(|_err| ErrorKey::InvalidPublicKey)
} else {
Err(ErrorKey::InvalidPublicKey)
}?;
Secp256k1Point::from_bytes(&public.serialize_uncompressed()[1..])
} |
If you use it for ecdsa than my option 2 should work for you with the compressed format:
let me know if you have any problem |
Thank you for reply. |
That's true in the general case, but in the case of ECDSA it doesn't matter. you can verify ecdsa even with public key and R with wrong parity. |
I try to use pubic key without prefix, but often verification failed. use curv::{BigInt,GE};
use curv::elliptic::curves::traits::ECPoint;
use curv::arithmetic::traits::Converter;
fn point2point(p: &GE) -> GE {
let tmp = p.bytes_compressed_to_big_int();
let tmp = BigInt::to_vec(&tmp);
GE::from_bytes(&tmp[1..]).unwrap()
} point2point wrapper covert public key with prefix 2 or 3 to prefix 2. #[cfg(test)]
mod tests {
use super::point2point;
use curv::BigInt;
use curv::GE;
use protocols::aggsig::{verify, verify_partial, EphemeralKey, KeyAgg, KeyPair};
extern crate hex;
use curv::elliptic::curves::traits::*;
#[test]
fn test_multiparty_signing_for_two_parties() {
let is_musig = true;
let message: [u8; 4] = [79, 77, 69, 82];
// round 0: generate signing keys
let party1_key = KeyPair::create();
let party2_key = KeyPair::create();
// round 1: send commitments to ephemeral public keys
let party1_ephemeral_key = EphemeralKey::create();
let party2_ephemeral_key = EphemeralKey::create();
let party1_commitment = &party1_ephemeral_key.commitment;
let party2_commitment = &party2_ephemeral_key.commitment;
// round 2: send ephemeral public keys and check commitments
// p1 release R1' and p2 test com(R1') = com(R1):
assert!(EphemeralKey::test_com(
&point2point(&party2_ephemeral_key.keypair.public_key),
&party2_ephemeral_key.blind_factor,
party2_commitment
));
// p2 release R2' and p1 test com(R2') = com(R2):
assert!(EphemeralKey::test_com(
&point2point(&party1_ephemeral_key.keypair.public_key),
&party1_ephemeral_key.blind_factor,
party1_commitment
));
// compute apk:
let mut pks: Vec<GE> = Vec::new();
pks.push(party1_key.public_key.clone());
pks.push(party2_key.public_key.clone());
let party1_key_agg = KeyAgg::key_aggregation_n(&pks, 0);
let party2_key_agg = KeyAgg::key_aggregation_n(&pks, 1);
assert_eq!(party1_key_agg.apk, party2_key_agg.apk);
// compute R' = R1+R2:
let party1_r_tag = EphemeralKey::add_ephemeral_pub_keys(
&point2point(&party1_ephemeral_key.keypair.public_key),
&point2point(&party2_ephemeral_key.keypair.public_key),
);
let party2_r_tag = EphemeralKey::add_ephemeral_pub_keys(
&point2point(&party1_ephemeral_key.keypair.public_key),
&point2point(&party2_ephemeral_key.keypair.public_key),
);
assert_eq!(party1_r_tag, party2_r_tag);
// compute c = H0(Rtag || apk || message)
let party1_h_0 =
EphemeralKey::hash_0(&party1_r_tag, &party1_key_agg.apk, &message, is_musig);
let party2_h_0 =
EphemeralKey::hash_0(&party2_r_tag, &party2_key_agg.apk, &message, is_musig);
assert_eq!(party1_h_0, party2_h_0);
// compute partial signature s_i and send to the other party:
let s1 = EphemeralKey::sign(
&party1_ephemeral_key,
&party1_h_0,
&party1_key,
&party1_key_agg.hash,
);
let s2 = EphemeralKey::sign(
&party2_ephemeral_key,
&party2_h_0,
&party2_key,
&party2_key_agg.hash,
);
let r = party1_ephemeral_key.keypair.public_key.x_coor().unwrap();
assert!(verify_partial(
&ECScalar::from(&s1),
&r,
&ECScalar::from(&party1_h_0),
&ECScalar::from(&party1_key_agg.hash),
&party1_key.public_key
)
.is_ok());
// signature s:
let (r, s) = EphemeralKey::add_signature_parts(s1, &s2, &party1_r_tag);
// verify:
assert!(verify(&s, &r, &point2point(&party1_key_agg.apk), &message, is_musig,).is_ok())
}
} Is this code use prefix on process? or is something wrong with my idea? |
Hi @namuyan, if I understand correctly, you are trying |
Thank you for advice. |
I agree that Schnorr requires correct Y coordinate. |
I want to recover from bytes.
It looks work, but paniced 'THIS: InvalidPublicKey.
I cannot find correct way to serialize/deserialize except this.
What's wrong is this way?
The text was updated successfully, but these errors were encountered: