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
2 changes: 2 additions & 0 deletions backend/rs/ic_vetkeys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- Added MasterPublicKey::production_key which allows accessing the production public keys

- Added IbeCiphertext plaintextSize and ciphertextSize helpers
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, we should change this to the snake case later.


## [0.3.0] - 2025-06-30

### Added
Expand Down
25 changes: 21 additions & 4 deletions backend/rs/ic_vetkeys/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ const IBE_HEADER: [u8; 8] = [b'I', b'C', b' ', b'I', b'B', b'E', 0x00, 0x01];

const IBE_HEADER_BYTES: usize = IBE_HEADER.len();

const IBE_OVERHEAD: usize = IBE_HEADER_BYTES + IBE_SEED_BYTES + G2AFFINE_BYTES;

#[derive(Clone, Debug, Eq, PartialEq)]
/// An IBE (identity based encryption) ciphertext
pub struct IbeCiphertext {
Expand Down Expand Up @@ -599,8 +601,7 @@ impl IbeDomainSep {
impl IbeCiphertext {
/// Serialize this IBE ciphertext
pub fn serialize(&self) -> Vec<u8> {
let mut output =
Vec::with_capacity(self.header.len() + G2AFFINE_BYTES + IBE_SEED_BYTES + self.c3.len());
let mut output = Vec::with_capacity(IBE_OVERHEAD + self.c3.len());

output.extend_from_slice(&self.header);
output.extend_from_slice(&self.c1.to_compressed());
Expand All @@ -614,7 +615,7 @@ impl IbeCiphertext {
///
/// Returns Err if the encoding is not valid
pub fn deserialize(bytes: &[u8]) -> Result<Self, String> {
if bytes.len() < IBE_HEADER_BYTES + G2AFFINE_BYTES + IBE_SEED_BYTES {
if bytes.len() < IBE_OVERHEAD {
return Err("IbeCiphertext too short to be valid".to_string());
}

Expand All @@ -637,7 +638,6 @@ impl IbeCiphertext {
}

fn hash_to_mask(header: &[u8], seed: &[u8; IBE_SEED_BYTES], msg: &[u8]) -> Scalar {

/*
It would have been better to instead use the SHA-256 of the message instead of the
message directly, since that would avoid having to allocate an extra buffer of
Expand Down Expand Up @@ -763,6 +763,23 @@ impl IbeCiphertext {
Err("decryption failed".to_string())
}
}

/// Helper function for determining size of the IBE ciphertext
pub fn ciphertext_size(plaintext_size: usize) -> usize {
plaintext_size + IBE_OVERHEAD
}

/// Helper function for determining size of the IBE plaintext
///
/// Returns None if the indicated length would be a ciphertext
/// that is not possibly valid (due to missing required elements)
pub fn plaintext_size(ciphertext_size: usize) -> Option<usize> {
if ciphertext_size >= IBE_OVERHEAD {
Some(ciphertext_size - IBE_OVERHEAD)
} else {
None
}
}
}

/// Verify an augmented BLS signature
Expand Down
10 changes: 7 additions & 3 deletions backend/rs/ic_vetkeys/tests/utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use hex_literal::hex;
use ic_bls12_381::*;
use ic_vetkeys::*;
use ic_vetkeys_test_utils::*;
use rand::Rng;
use hex_literal::hex;

#[test]
fn test_hkdf_test_vector() {
Expand All @@ -28,7 +28,10 @@ fn test_hkdf_test_vector() {

#[test]
fn test_is_valid_transport_public_key() {
assert_eq!(is_valid_transport_public_key_encoding(&hex::decode("F00F00F00F00").unwrap()), false);
assert_eq!(
is_valid_transport_public_key_encoding(&hex::decode("F00F00F00F00").unwrap()),
Comment thread
randombit marked this conversation as resolved.
false
);
assert_eq!(is_valid_transport_public_key_encoding(&hex::decode("97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb").unwrap()), true);
assert_eq!(is_valid_transport_public_key_encoding(&hex::decode("c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()), true);
}
Expand Down Expand Up @@ -68,7 +71,8 @@ fn test_bls_signature_verification() {
fn test_bls_signature_verification_using_identity() {
// Check that the identity element is rejected as a public key

let dpk = DerivedPublicKey::deserialize(&ic_bls12_381::G2Affine::identity().to_compressed()).unwrap();
let dpk =
DerivedPublicKey::deserialize(&ic_bls12_381::G2Affine::identity().to_compressed()).unwrap();

let msg = b"wrong message";

Expand Down
2 changes: 2 additions & 0 deletions frontend/ic_vetkeys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- Added MasterPublicKey.productionKey which allows accessing the production public keys

- Added IbeCiphertext plaintextSize and ciphertextSize helpers

## [0.3.0] - 2025-06-30

### Changed
Expand Down
8 changes: 8 additions & 0 deletions frontend/ic_vetkeys/src/utils/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@ test("AES-GCM encryption", async () => {
}
});

test("IBE ciphertext size utils", () => {
for (let ptextLen: number = 0; ptextLen != 1024; ++ptextLen) {
const ctextLen = IbeCiphertext.ciphertextSize(ptextLen);
const recPtextLen = IbeCiphertext.plaintextSize(ctextLen);
assertEqual(ptextLen, recPtextLen);
}
});

test("hkdf test vectors", () => {
// HKDF test vectors from wycheproof
const testVectors = [
Expand Down
31 changes: 31 additions & 0 deletions frontend/ic_vetkeys/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,11 @@ export class IbeSeed {
}
}

/**
* Total overhead for an IBE ciphertext
*/
const IBE_OVERHEAD = IBE_HEADER_LEN + IBE_SEED_BYTES + G2_BYTES;

/**
* IBE (Identity Based Encryption)
*/
Expand All @@ -937,6 +942,32 @@ export class IbeCiphertext {
readonly #c2: Uint8Array;
readonly #c3: Uint8Array;

/**
* Helper function for determining size of the IBE ciphertext
*/
static ciphertextSize(plaintextSize: number): number {
if (plaintextSize < 0) {
throw new Error(
"IbeCiphertext.ciphertextSize argument cannot be negative",
);
}

return plaintextSize + IBE_OVERHEAD;
}

/**
* Helper function for determining size of the IBE plaintext
*/
static plaintextSize(ciphertextSize: number): number {
if (ciphertextSize < IBE_OVERHEAD) {
throw new Error(
"IbeCiphertext.plaintextSize given ciphertext size is too small to be valid",
);
}

return ciphertextSize - IBE_OVERHEAD;
}

/**
* Serialize the IBE ciphertext to a bytestring
*/
Expand Down