openssl rust crate: ECDSA signature size is not 64 bytes? - rust

I want to use OpenSSL rust crate to perform cryptography operations, specifically using the ECDSA algorithm.
I use the following code to generate an ECDSA key (elliptic curve P-256) and use that to sign data and get the signature:
use openssl::sign::{Signer, Verifier};
use openssl::ec::{EcKey, EcGroup};
use openssl::pkey::PKey;
use openssl::hash::MessageDigest;
use openssl::nid::Nid;
// ec key
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let keypair = EcKey::generate(&group).unwrap();
let keypair = PKey::from_ec_key(keypair).unwrap();
// data to sign
let data = b"hello, world!";
// hash: sha-256
let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap();
let buf_size = signer.len().unwrap(); // Computes an upper bound on the signature length.
println!("buffer size {}", buf_size); // 72
let mut buf: [u8; 72] = [0; 72];
// sign
let exact_bytes = signer.sign_oneshot(&mut buf, data).unwrap(); //the number of bytes written.
println!("{}", exact_bytes); // 70
I don't understand why the exact_bytes is 70. In my understanding, it should be 64.
ECDSA signatures are 2 times longer than the signer's private key for the curve used during the signing process. For example, for 256-bit elliptic curves (like secp256k1) the ECDSA signature is 512 bits (64 bytes) and for 521-bit curves (like secp521r1) the signature is 1042 bits.
Any help? Thank you!

From here it seems that it depends also on the encoding uaed by the signature, which might increase the length.
Also, your understanding about the signature length is explained, which is not quite the same as you said.

Related

How To Calculate Elliptic Curve Pairing Function Given BLS Public Key and Message

I'm trying to calculate curve pairings for the BLS cryptosystem given a public key and message. I generate the key with the bls_signatures crate and ultimately want to crunch e(pub_key, HashToCurve(message)) using the blstrs crate (since I found a pairing function there).
let priv_key = bls_signatures::PrivateKey::new(&[0_u8; 32]); // not secure, but repeatable
let mut buff = std::io::Cursor::new(vec![]);
let _bytes_written = priv_key
.public_key()
.as_affine()
.write_raw(&mut buff);
let mut pub_key_affine_bytes: Vec<u8> = buff.into_inner();
The first problem is that paired::bls12_381::G1Affine::write_raw() seems to be adding an extraneous zero to the beginning, giving me 97 bytes instead of 96:
assert!(pub_key_affine_bytes.len() == 97_usize); // instead of 96
assert!(pub_key_affine_bytes[0] == 0_u8); // regardless of key used... which seems wrong
I can "fix" it for now via let _ = pub_key_affine_bytes.remove(0); but when I try to convert to a blstrs::G1Affine (in the hopes of using blstrs::pairing() to reach my goal, but maybe there's a better way?), the blstrs library doesn't like it:
let pub_key_affine_bytes: [u8; 96] = pub_key_affine_bytes.try_into().unwrap();
assert!(blstrs::G1Affine::from_uncompressed(&pub_key_affine_bytes) == None); // instead of Some(_)
It's probably obvious by now, but I'm new to both Rust and this type of cryptography, so any guidance is welcome. How would you calculate pairings given a public key and message?
I just realized this simple solution as I was done looking through all the source code and writing up my original answer. It's as easy as changing the enabled features in your Cargo.toml to disable the usage of paired and enable blstrs to be used internally.
[package]
name = "blst_test"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
blstrs = "^0.3"
bls-signatures = {version="0.10.0", default-features= false, features=["blst"] }
With that fixed, the following works just fine
fn main() {
let priv_key = bls_signatures::PrivateKey::new(&[0_u8; 32]); // not secure, but repeatable
let affine = priv_key
.public_key()
.as_affine(); // blstrs::G1Affine, no longer from paired!
println!("{:?}", affine);
}

How to achieve blake2AsHex functionality from Polkadot.js in Substrate?

I want to use the blake2AsHex kind of function in Rust. This function exists in javascript but I am looking for a corresponding function in rust. So far, using the primitives of Substrate which are:
pub fn blake2_256(data: &[u8]) -> [u8; 32]
// Do a Blake2 256-bit hash and return result.
I am getting a different value.
When I execute this in console:
util_crypto.blake2AsHex("0x0000000000000000000000000000000000000000000000000000000000000001")
I get the desired value: 0x33e423980c9b37d048bd5fadbd4a2aeb95146922045405accc2f468d0ef96988. However, when I execute this rust code:
let res = hex::encode(&blake2_256("0x0000000000000000000000000000000000000000000000000000000000000001".as_bytes()));
println!("File Hash encoding: {:?}", res);
I get a different value:
47016246ca22488cf19f5e2e274124494d272c69150c3db5f091c9306b6223fc
Hence, how can I implement blake2AsHex in Rust?
Again you have an issue with data types here.
"0x0000000000000000000000000000000000000000000000000000000000000001".as_bytes()
is converting a big string to bytes, not the hexadecimal representation.
You need to correctly create the bytearray that you want to represent, and then it should work.
You are already using hex::encode for bytes to hex string... you should be using hex::decode for hex string to bytes:
https://docs.rs/hex/0.3.1/hex/fn.decode.html
Decodes a hex string into raw bytes.

How do I take the first 4 bytes of SHA256 in Rust?

How do I elegantly take first 4 bytes of SHA256 in Rust? Specifically from generic_array produced by:
sha2::Sha256::new().chain(b"blabla_93794926").result();
(without using unsafe Rust)
This should work:
let first_bytes = &(Sha256::new().chain(b"blabla_93794926").result()[0..4]);

Cryptopals challenge 6 incorrect results when computing key size

I'm working on the Cryptopals challenges and I'm stuck on challenge 6. I've written the following Rust code to compute key sizes as specified in the challenge and I'm getting weird results.
fn get_keysizes(mut ciphertext: Vec<u8>) -> Vec<(usize, u64)> {
let mut sizelist: Vec<(usize, u64)> = Vec::new();
for keysize in 2..41 {
let blocks: Vec<&[u8]> = ciphertext.chunks(keysize).collect();
sizelist.push((keysize, get_hamming_distance(blocks[0], blocks[1]) / keysize as u64));
}
sizelist.sort_by(|x, y| x.1.cmp(&y.1));
println!("{:?}", sizelist);
sizelist
}
I encrypted the string For each KEYSIZE, take the first KEYSIZE worth of bytes, and the second KEYSIZE worth of bytes, and find the edit distance between them. Normalize this result by dividing by KEYSIZE. with repeating key XOR using the cryptopals crypto challenges as the key and passed the ciphertext into my function and it computed the key length to be 3.
Even though I've followed the algorithm in the challenge, I may have misinterpreted it.
I have no idea why its not working, I've read a lot of articles on how to solve this challenge but none of them follow the algorithm in the challenge.

Extract 7 bits signed integer from u8 byte

I am using the Human Interface Device protocol to get data from an external device. The library I'm using returns an array of bytes ([u8; 64]) which I want to extract an i7 (which will be i8 in Rust) from one byte.
The byte I want to manipulate has two different pieces of information in it:
1 bit for something
the 7 other bits (which I have to decode as a signed integer) for another thing.
Do you know what can I do to achieve this?
Using the crate bitreader I have been able to properly decode the signed integer of 7 bits.
let mut bit_reader = BitReader::new(buffer);
let first_useless_bit: u8 = bit_reader.read_u8(1).unwrap();
let extracted_value: i8 = bit_reader.read_i8(7).unwrap();
Your question is pretty unclear, but I think you are just asking about normal bit manipulation. Mask the 7 bits (assuming the lower 7 bits, although you did not say) and convert the remaining bits to a signed number:
fn main() {
let byte = 0xFFu8;
let byte2 = (byte & 0b0111_1111) as i8;
println!("{}", byte2);
}
If you want to turn an array of u8 into a vector of i8 while ignoring the most significant bit, you can do it in the following manner:
fn main() {
let array_unsigned = [1u8, 2, 3]; // this will work for 64 values too
let vec_signed: Vec<i8> = array_unsigned.into_iter()
.map(|&e| if e <= 127 { e as i8 } else { (e - 128) as i8 }).collect();
println!("{:?}", vec_signed);
}
This way consumes the input array. It could probably be done in a nicer way with some bit-fiddling.

Resources