Skip to content

Commit

Permalink
refactor: key representation conversion utils
Browse files Browse the repository at this point in the history
  • Loading branch information
BasileiosKal committed Jun 15, 2024
1 parent b9aa7d1 commit 72e0dd2
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 5 deletions.
50 changes: 47 additions & 3 deletions src/common/key_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ macro_rules! bbs_bls_key_pair_impl {
/// Number of bytes needed to represent the public key in compressed
/// form.
pub const SIZE_BYTES: usize = $octet_point_length;
/// Number of bytes needed to represent the public key in uncompressed
/// form.
pub const SIZE_BYTES_UNCOMPRESSED: usize = 2 * Self::SIZE_BYTES;

/// Check if the `PublicKey` is valid.
pub fn is_valid(&self) -> Choice {
Expand All @@ -193,12 +196,25 @@ macro_rules! bbs_bls_key_pair_impl {
self.0.to_affine().to_compressed()
}

/// Get the G2 representation in affine, uncompressed and big-endian
/// form of PublicKey.
pub fn to_octets_uncompressed(&self) -> [u8; Self::SIZE_BYTES_UNCOMPRESSED] {
self.0.to_uncompressed()
}

/// Convert a vector of bytes of big-endian representation of the
/// public key.
pub fn from_vec(bytes: &Vec<u8>) -> Result<Self, Error> {
match vec_to_byte_array::<{ Self::SIZE_BYTES }>(bytes) {
Ok(result) => Self::from_octets(&result),
Err(e) => Err(e),
match bytes.len() {
Self::SIZE_BYTES => {
let byte_array = vec_to_byte_array::<{ Self::SIZE_BYTES }>(bytes)?;
Self::from_octets(&byte_array)
},
Self::SIZE_BYTES_UNCOMPRESSED => {
let byte_array = vec_to_byte_array::<{ Self::SIZE_BYTES_UNCOMPRESSED }>(bytes)?;
Self::from_octets_uncompressed(&byte_array)
},
_ => Err(Error::BadEncoding)
}
}

Expand All @@ -216,6 +232,34 @@ macro_rules! bbs_bls_key_pair_impl {
Err(Error::BadEncoding)
}
}

/// Convert from G2 point in affine, uncompressed and big-endian form
/// to PublicKey.
pub fn from_octets_uncompressed(bytes: &[u8; Self::SIZE_BYTES_UNCOMPRESSED]) -> Result<Self, Error> {
let result = $point_projective_type::from_uncompressed(bytes);

if result.is_some().unwrap_u8() == 1u8 {
Ok(Self(result.unwrap()))
} else {
Err(Error::BadEncoding)
}
}

/// Convert a public key from compressed to uncompressed representation
pub fn compressed_to_uncompressed(bytes: &Vec<u8>) -> Result<[u8; Self::SIZE_BYTES_UNCOMPRESSED], Error> {
match Self::from_vec(bytes) {
Ok(public_key) => Ok(Self::to_octets_uncompressed(&public_key)),
Err(e) => Err(e)
}
}

/// Convert a public key from uncompressed to compressed representation
pub fn uncompressed_to_compressed(bytes: &Vec<u8>) -> Result<[u8; Self::SIZE_BYTES], Error> {
match Self::from_vec(bytes) {
Ok(public_key) => Ok(Self::to_octets(&public_key)),
Err(e) => Err(e)
}
}
}

/// A BBS key pair.
Expand Down
2 changes: 1 addition & 1 deletion src/curves/bls12_381.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use blstrs::{Bls12 as pairing_engine, *};
pub use blstrs::*;

/// Number of bytes to store a scalar.
pub(crate) const OCTET_SCALAR_LENGTH: usize = 32;
Expand Down
45 changes: 45 additions & 0 deletions wrappers/wasm/__tests__/bbs/bls12381/keyGen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

import { bbs } from "../../../lib";
import { utilities } from "../../../lib";

describe("bbs", () => {
describe("bls12381_shake256", () => {
Expand Down Expand Up @@ -61,6 +62,49 @@ describe("bbs", () => {
expect(result.secretKey as Uint8Array).toEqual(value.secretKey);
expect(result.publicKey).toEqual(value.publicKey);
});

it("should be able to map a compressed public key to an uncompressed representation", async () => {
const compressed_keypair = await bbs.bls12381_shake256.generateKeyPair({
ikm: value.ikm,
keyInfo: value.keyInfo,
});

const uncompressed_keypair = await bbs.bls12381_shake256.generateKeyPairUncompressed({
ikm: value.ikm,
keyInfo: value.keyInfo,
});

const uncompressed_from_compressed_pk = await utilities.compressedToUncompressedPublicKey(
compressed_keypair.publicKey
);

const compressed_from_uncompressed_pk = await utilities.uncompressedToCompressedPublicKey(
uncompressed_keypair.publicKey
);

expect(compressed_keypair.publicKey).toBeDefined();
expect(compressed_keypair.secretKey).toBeDefined();

expect(uncompressed_keypair.publicKey).toBeDefined();
expect(uncompressed_keypair.secretKey).toBeDefined();
expect(uncompressed_keypair.publicKey?.length as number).toEqual(
bbs.bls12381_shake256.PUBLIC_KEY_LENGTH * 2
)

expect(uncompressed_from_compressed_pk).toBeDefined();
expect(uncompressed_from_compressed_pk?.length as number).toEqual(
bbs.bls12381_shake256.PUBLIC_KEY_LENGTH * 2
)

expect(uncompressed_keypair.publicKey).toEqual(uncompressed_from_compressed_pk)

expect(compressed_from_uncompressed_pk).toBeDefined();
expect(compressed_from_uncompressed_pk?.length as number).toEqual(
bbs.bls12381_shake256.PUBLIC_KEY_LENGTH
)

expect(compressed_keypair.publicKey).toEqual(compressed_from_uncompressed_pk)
});
});

it("should be able to generate a key pair from random", async () => {
Expand All @@ -73,6 +117,7 @@ describe("bbs", () => {
);
expect(result.publicKey.length).toEqual(bbs.bls12381_shake256.PUBLIC_KEY_LENGTH);
});

});
});
});
74 changes: 74 additions & 0 deletions wrappers/wasm/src/bbs/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use pairing_crypto::bbs::{
ciphersuites::{
bls12_381::{
KeyPair as Bls12381BbsKeyPair,
PublicKey as Bls12381BbsPublicKey,
BBS_BLS12381G1_PUBLIC_KEY_LENGTH,
BBS_BLS12381G1_SECRET_KEY_LENGTH,
BBS_BLS12381G1_SIGNATURE_LENGTH,
Expand All @@ -43,6 +44,7 @@ use pairing_crypto::bbs::{
BbsSignRequest,
BbsVerifyRequest,
};
use pairing_crypto::Error;
use wasm_bindgen::prelude::*;

/// Generate a BBS key pair on BLS 12-381 curve.
Expand Down Expand Up @@ -84,6 +86,78 @@ pub async fn bbs_bls12_381_generate_key_pair(
serde_wasm_bindgen::to_value(&keypair)
}


/// Generate a key pair in uncompressed form
#[wasm_bindgen(js_name = bbs_bls12_381_generate_key_pair_uncompressed)]
pub async fn bbs_bls12_381_generate_key_pair_uncompressed(
request: JsValue,
) -> Result<JsValue, serde_wasm_bindgen::Error> {
// Improves error output in JS based console.log() when built with
// debug feature enabled
set_panic_hook();

// Cast the supplied JSON request into a rust struct
let request: KeyGenerationRequestDto = request.try_into()?;

let ikm = request.ikm.unwrap_or(Vec::new());
let key_info = request.keyInfo.unwrap_or(Vec::new());

// // Derive secret key from supplied IKM and key information
// metadata.
let key_pair = Bls12381BbsKeyPair::new(&ikm, &key_info).ok_or(
serde_wasm_bindgen::Error::new(
"unexpected error, failed to generate keys.",
),
)?;

// Construct the JS DTO of the key pair to return
let keypair = KeyPair {
secretKey: key_pair.secret_key.to_bytes().to_vec(),
publicKey: key_pair.public_key.to_octets_uncompressed().to_vec(),
};
serde_wasm_bindgen::to_value(&keypair)
}



/// Convert the public key representation from compressed to uncompressed
#[wasm_bindgen(js_name = bbs_bls12_381_compressed_to_uncompressed_public_key)]
pub async fn bbs_bls12_381_compressed_to_uncompressed_public_key(
request: Vec<u8>
) -> Result<JsValue, serde_wasm_bindgen::Error> {
// debug feature enabled
set_panic_hook();

match Bls12381BbsPublicKey::compressed_to_uncompressed(&request) {
Ok(bytes) => serde_wasm_bindgen::to_value(&bytes.to_vec()),
Err(e) if e == Error::BadEncoding => Err(serde_wasm_bindgen::Error::new(
"unexpected error, input public key is incorrectly encoded."
)),
Err(_) => Err(serde_wasm_bindgen::Error::new(
"unexpected error, failed to map public key from compressed to uncompressed form."
)),
}
}

/// Convert the public key representation from uncompressed to compressed
#[wasm_bindgen(js_name = bbs_bls12_381_uncompressed_to_compressed_public_key)]
pub async fn bbs_bls12_381_uncompressed_to_compressed_public_key(
request: Vec<u8>
) -> Result<JsValue, serde_wasm_bindgen::Error> {
// debug feature enabled
set_panic_hook();

match Bls12381BbsPublicKey::uncompressed_to_compressed(&request) {
Ok(bytes) => serde_wasm_bindgen::to_value(&bytes.to_vec()),
Err(e) if e == Error::BadEncoding => Err(serde_wasm_bindgen::Error::new(
"unexpected error, input public key is incorrectly encoded."
)),
Err(_) => Err(serde_wasm_bindgen::Error::new(
"unexpected error, failed to map public key from uncompressed to compressed form."
)),
}
}

macro_rules! bbs_wrapper_api_generator {
(
$sign_wrapper_fn:ident,
Expand Down
14 changes: 14 additions & 0 deletions wrappers/wasm/src/js/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export namespace bbs {
function generateKeyPair(
request?: KeyGenerationRequest
): Promise<Required<KeyPair>>;
function generateKeyPairUncompressed(
request?: KeyGenerationRequest
): Promise<Required<KeyPair>>;
function sign(request: BbsSignRequest): Promise<Uint8Array>;
function verify(request: BbsVerifyRequest): Promise<BbsVerifyResult>;
function deriveProof(request: BbsDeriveProofRequest): Promise<Uint8Array>;
Expand All @@ -63,6 +66,9 @@ export namespace bbs {
function generateKeyPair(
request?: KeyGenerationRequest
): Promise<Required<KeyPair>>;
function generateKeyPairUncompressed(
request?: KeyGenerationRequest
): Promise<Required<KeyPair>>;
function sign(request: BbsSignRequest): Promise<Uint8Array>;
function verify(request: BbsVerifyRequest): Promise<BbsVerifyResult>;
function deriveProof(request: BbsDeriveProofRequest): Promise<Uint8Array>;
Expand Down Expand Up @@ -107,4 +113,12 @@ export namespace utilities {
function convertRevealMessageArrayToRevealMap(
messages: { value: Uint8Array; reveal: boolean }[]
): { [key: number]: Uint8Array };

function compressedToUncompressedPublicKey(
request?: Uint8Array
): Promise<Uint8Array>;

function uncompressedToCompressedPublicKey(
request?: Uint8Array
): Promise<Uint8Array>;
}
33 changes: 32 additions & 1 deletion wrappers/wasm/src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ const bbs_bls12_381_generate_key_pair = async (request) => {
};
};

const bbs_bls12_381_generate_key_pair_uncompressed = async (request) => {
await initialize();
var result = await throwErrorOnRejectedPromise(
wasm.bbs_bls12_381_generate_key_pair_uncompressed(request ?? {})
);
return {
secretKey: new Uint8Array(result.secretKey),
publicKey: new Uint8Array(result.publicKey),
};
}

const bbs_bls12_381_compressed_to_uncompressed_public_key = async (request) => {
await initialize();
var result = await throwErrorOnRejectedPromise(
wasm.bbs_bls12_381_compressed_to_uncompressed_public_key(request ?? {})
);
return new Uint8Array(result);
}

const bbs_bls12_381_uncompressed_to_compressed_public_key = async (request) => {
await initialize();
var result = await throwErrorOnRejectedPromise(
wasm.bbs_bls12_381_uncompressed_to_compressed_public_key(request ?? {})
);
return new Uint8Array(result);
}

const bbs_bls12_381_sha_256_sign = async (request) => {
await initialize();
return new Uint8Array(await throwErrorOnRejectedPromise(wasm.bbs_bls12_381_sha_256_sign(request)));
Expand Down Expand Up @@ -198,6 +225,7 @@ module.exports.bbs = {
SIGNATURE_LENGTH: DEFAULT_BLS12381_BBS_SIGNATURE_LENGTH,

generateKeyPair: bbs_bls12_381_generate_key_pair,
generateKeyPairUncompressed: bbs_bls12_381_generate_key_pair_uncompressed,
sign: bbs_bls12_381_sha_256_sign,
verify: bbs_bls12_381_sha_256_verify,
deriveProof: bbs_bls12_381_sha_256_proof_gen,
Expand All @@ -209,6 +237,7 @@ module.exports.bbs = {
SIGNATURE_LENGTH: DEFAULT_BLS12381_BBS_SIGNATURE_LENGTH,

generateKeyPair: bbs_bls12_381_generate_key_pair,
generateKeyPairUncompressed: bbs_bls12_381_generate_key_pair_uncompressed,
sign: bbs_bls12_381_shake_256_sign,
verify: bbs_bls12_381_shake_256_verify,
deriveProof: bbs_bls12_381_shake_256_proof_gen,
Expand Down Expand Up @@ -239,5 +268,7 @@ module.exports.bbs_bound = {

module.exports.utilities = {
convertToRevealMessageArray,
convertRevealMessageArrayToRevealMap
convertRevealMessageArrayToRevealMap,
compressedToUncompressedPublicKey: bbs_bls12_381_compressed_to_uncompressed_public_key,
uncompressedToCompressedPublicKey: bbs_bls12_381_uncompressed_to_compressed_public_key,
}

0 comments on commit 72e0dd2

Please sign in to comment.