Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
56795d4
pkc%fix(bls): consistently return `InvalidKeyMaterial` for bad IKMs
kwvg Sep 13, 2026
cc6163c
pkc%fix(bls): distinguish between too low shares and mismatched count
kwvg Sep 13, 2026
723c898
pkc%refac: rename `ThresholdTooLarge` to `InvalidThreshold` for accuracy
kwvg Sep 13, 2026
dd7e8bf
pkc%refac: `InvalidVerificationVector` -> `InsufficientCoefficients`
kwvg Sep 13, 2026
c2b6ec4
pkc%refac(bls): disambiguate threshold recovery with `recover_shares()`
kwvg Sep 12, 2026
f3675f3
pkc%refac(bls): disambiguate KDF-based generation with `from_ikm()`
kwvg Sep 15, 2026
85f28f5
pkc%refac(bls): move `verify{_with}()` to public key to match w/ ECDSA
kwvg Sep 12, 2026
c1719b8
pkc%feat(bls): add `verify_pubkey` for parity w/ ECDSA counterpart
kwvg Sep 15, 2026
7788357
pkc%perf(bls): add `deserialize()` to speed up `pk_to_g1`/`sig_to_g2()`
kwvg Sep 13, 2026
ef72a99
pkc%feat(bls): expose big-endian scalar reduction
kwvg Sep 14, 2026
ea430f2
pkc%feat(bls): recover a master public key from its shares
kwvg Sep 14, 2026
9a7210a
pkc%feat(bls): add scalar and point tweaks
kwvg Sep 15, 2026
e412290
pkc%feat(bls): add helper to generate secret key with an RNG
kwvg Sep 13, 2026
ac04d1d
pkc%refac(bls): seal `BlsScheme` to prevent external implementations
kwvg Sep 15, 2026
a4c3754
pkc%feat(bls): name the public key hash `BlsPkHash`
kwvg Sep 15, 2026
9b022b5
pkc%fix(bls): read a share id in the order the curve reads it
kwvg Sep 15, 2026
eb1af57
pkc%fix(bls): refuse an identity recovered from cancelling shares
kwvg Sep 15, 2026
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
3 changes: 3 additions & 0 deletions maint/codeql/rust/lib/policy.qll
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ predicate isSecretType(TypeItem t) {
// A share *of a signature* is published, so it's non-secret. Excluded by exact name because
// `BlsSkShare` and `RawShare` match the same Share substring and do carry secret scalars.
"BlsSigShare",
// A share *of a public key* is the point the quorum publishes for a participant, and what it
// recovers to is the master key, which is also public.
"BlsPkShare",
// The identifier a share is issued against is the participant's, known to every member of the
// quorum; only the scalar the share carries is secret.
"BlsShareId",
Expand Down
46 changes: 23 additions & 23 deletions pkgs/pkc/bench/bls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rand_core::UnwrapErr;
/// Single signature creation.
#[divan::bench(types = [BlsScChia, BlsScIetf])]
fn sign<S: BlsScheme>(bencher: Bencher) {
let sk = BlsSecretKey::<S>::generate(&test_ikm(1)).unwrap();
let sk = BlsSecretKey::<S>::from_ikm(&test_ikm(1)).unwrap();
bencher
.counter(ItemsCount::new(1u32))
.bench(|| sk.sign(S::msg_ref(&test_msg(42))));
Expand All @@ -24,20 +24,20 @@ fn sign<S: BlsScheme>(bencher: Bencher) {
/// Single signature verification.
#[divan::bench(types = [BlsScChia, BlsScIetf])]
fn verify<S: BlsScheme>(bencher: Bencher) {
let sk = BlsSecretKey::<S>::generate(&test_ikm(2)).unwrap();
let sk = BlsSecretKey::<S>::from_ikm(&test_ikm(2)).unwrap();
let msg = test_msg(99);
let sig = sk.sign(S::msg_ref(&msg));
let pk = sk.public_key();
bencher
.counter(ItemsCount::new(1u32))
.bench(|| sig.verify(S::msg_ref(&msg), &pk));
.bench(|| pk.verify(S::msg_ref(&msg), &sig));
}

/// Public key aggregation at various quorum sizes.
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [2, 5, 25, 50, 100])]
fn aggregate_pk_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let pks: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap().public_key())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap().public_key())
.collect();
let pk_refs: Vec<_> = pks.iter().collect();
bencher
Expand All @@ -49,7 +49,7 @@ fn aggregate_pk_n<S: BlsScheme>(bencher: Bencher, n: usize) {
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [2, 10, 100])]
fn aggregate_sig_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let keys: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap())
.collect();
let sigs: Vec<_> = keys
.iter()
Expand All @@ -66,7 +66,7 @@ fn aggregate_sig_n<S: BlsScheme>(bencher: Bencher, n: usize) {
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [100, 1000])]
fn verify_n_individual<S: BlsScheme>(bencher: Bencher, n: usize) {
let keys: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap())
.collect();
let msgs: Vec<[u8; 32]> = (0..n).map(test_msg).collect();
let pks: Vec<_> = keys.iter().map(BlsSecretKey::public_key).collect();
Expand All @@ -78,7 +78,7 @@ fn verify_n_individual<S: BlsScheme>(bencher: Bencher, n: usize) {

bencher.counter(ItemsCount::new(n)).bench(|| {
for i in 0..n {
let _ = sigs[i].verify(S::msg_ref(&msgs[i]), &pks[i]);
let _ = pks[i].verify(S::msg_ref(&msgs[i]), &sigs[i]);
}
});
}
Expand All @@ -87,7 +87,7 @@ fn verify_n_individual<S: BlsScheme>(bencher: Bencher, n: usize) {
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [10, 100, 1000])]
fn fast_verify_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let keys: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap())
.collect();
let msg = test_msg(42);
let pks: Vec<_> = keys.iter().map(BlsSecretKey::public_key).collect();
Expand All @@ -104,14 +104,14 @@ fn fast_verify_n<S: BlsScheme>(bencher: Bencher, n: usize) {
/// Public key serialization.
#[divan::bench(types = [BlsScChia, BlsScIetf])]
fn ser_pk<S: BlsScheme>(bencher: Bencher) {
let pk = BlsSecretKey::<S>::generate(&test_ikm(1)).unwrap().public_key();
let pk = BlsSecretKey::<S>::from_ikm(&test_ikm(1)).unwrap().public_key();
bencher.bench(|| pk.to_bytes());
}

/// Public key deserialization.
#[divan::bench(types = [BlsScChia, BlsScIetf])]
fn deser_pk<S: BlsScheme>(bencher: Bencher) {
let bytes = BlsSecretKey::<S>::generate(&test_ikm(1))
let bytes = BlsSecretKey::<S>::from_ikm(&test_ikm(1))
.unwrap()
.public_key()
.to_bytes();
Expand All @@ -121,7 +121,7 @@ fn deser_pk<S: BlsScheme>(bencher: Bencher) {
/// Signature serialization.
#[divan::bench(types = [BlsScChia, BlsScIetf])]
fn ser_sig<S: BlsScheme>(bencher: Bencher) {
let sig = BlsSecretKey::<S>::generate(&test_ikm(1))
let sig = BlsSecretKey::<S>::from_ikm(&test_ikm(1))
.unwrap()
.sign(S::msg_ref(&test_msg(0)));
bencher.bench(|| sig.to_bytes());
Expand All @@ -130,7 +130,7 @@ fn ser_sig<S: BlsScheme>(bencher: Bencher) {
/// Signature deserialization.
#[divan::bench(types = [BlsScChia, BlsScIetf])]
fn deser_sig<S: BlsScheme>(bencher: Bencher) {
let bytes = BlsSecretKey::<S>::generate(&test_ikm(1))
let bytes = BlsSecretKey::<S>::from_ikm(&test_ikm(1))
.unwrap()
.sign(S::msg_ref(&test_msg(0)))
.to_bytes();
Expand All @@ -140,7 +140,7 @@ fn deser_sig<S: BlsScheme>(bencher: Bencher) {
/// Threshold secret key splitting at various quorum sizes.
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [5, 10, 50])]
fn split_threshold<S: BlsScheme>(bencher: Bencher, n: usize) {
let sk = BlsSecretKey::<S>::generate(&test_ikm(1)).unwrap();
let sk = BlsSecretKey::<S>::from_ikm(&test_ikm(1)).unwrap();
let threshold = n.div_ceil(2);
let ids = sequential_ids(n);
bencher
Expand All @@ -151,15 +151,15 @@ fn split_threshold<S: BlsScheme>(bencher: Bencher, n: usize) {
/// Threshold signature recovery via Lagrange interpolation.
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [3, 5, 10])]
fn recover_threshold<S: BlsScheme>(bencher: Bencher, threshold: usize) {
let sk = BlsSecretKey::<S>::generate(&test_ikm(1)).unwrap();
let sk = BlsSecretKey::<S>::from_ikm(&test_ikm(1)).unwrap();
let ids = sequential_ids(threshold * 2);
let shares = sk.split(threshold, &ids, &mut UnwrapErr(SysRng)).unwrap();
let msg = test_msg(42);
let sig_shares: Vec<_> = shares.iter().map(|share| share.sign(S::msg_ref(&msg))).collect();
let subset: Vec<&BlsSigShare<S>> = sig_shares.iter().take(threshold).collect();
bencher
.counter(ItemsCount::new(threshold))
.bench(|| BlsSignature::<S>::recover(&subset));
.bench(|| BlsSignature::<S>::recover_shares(&subset));
}

/// Aggregate signatures over distinct messages, then verify.
Expand All @@ -169,7 +169,7 @@ where
S::Msg: Sync,
{
let keys: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap())
.collect();
let msgs: Vec<[u8; 32]> = (0..n).map(test_msg).collect();
let pks: Vec<_> = keys.iter().map(BlsSecretKey::public_key).collect();
Expand All @@ -193,7 +193,7 @@ where
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [2, 10, 100])]
fn secure_aggregate_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let keys: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap())
.collect();
let msg = test_msg(42);
let pks: Vec<_> = keys.iter().map(BlsSecretKey::public_key).collect();
Expand All @@ -211,7 +211,7 @@ fn secure_aggregate_n<S: BlsScheme>(bencher: Bencher, n: usize) {
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [2, 5, 10])]
fn derive_share_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let master: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap())
.collect();
let master_refs: Vec<&BlsSecretKey<S>> = master.iter().collect();
let id = sequential_ids(1)[0];
Expand All @@ -224,7 +224,7 @@ fn derive_share_n<S: BlsScheme>(bencher: Bencher, n: usize) {
/// Sealing one blob to one recipient, over a plaintext of `n` blocks.
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [1, 2, 16])]
fn ies_encrypt_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let pk = BlsSecretKey::<S>::generate(&test_ikm(1)).unwrap().public_key();
let pk = BlsSecretKey::<S>::from_ikm(&test_ikm(1)).unwrap().public_key();
let plaintext = vec![0x42u8; n * 16];
let mut rng = UnwrapErr(SysRng);

Expand All @@ -236,7 +236,7 @@ fn ies_encrypt_n<S: BlsScheme>(bencher: Bencher, n: usize) {
/// Opening one blob, paying for a DH exchange.
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [1, 2, 16])]
fn ies_decrypt_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let sk = BlsSecretKey::<S>::generate(&test_ikm(1)).unwrap();
let sk = BlsSecretKey::<S>::from_ikm(&test_ikm(1)).unwrap();
let plaintext = vec![0x42u8; n * 16];
let blob = sk.public_key().ies_encrypt(&plaintext, &mut UnwrapErr(SysRng)).unwrap();

Expand All @@ -247,7 +247,7 @@ fn ies_decrypt_n<S: BlsScheme>(bencher: Bencher, n: usize) {
#[divan::bench(types = [BlsScChia, BlsScIetf], args = [2, 10, 100])]
fn ies_encrypt_multi_n<S: BlsScheme>(bencher: Bencher, n: usize) {
let pks: Vec<_> = (0..n)
.map(|i| BlsSecretKey::<S>::generate(&test_ikm(i)).unwrap().public_key())
.map(|i| BlsSecretKey::<S>::from_ikm(&test_ikm(i)).unwrap().public_key())
.collect();
let pk_refs: Vec<&BlsPublicKey<S>> = pks.iter().collect();
let plaintexts = vec![[0x42u8; 32]; n];
Expand All @@ -266,14 +266,14 @@ mod ietf {
/// Proof of possession creation.
#[divan::bench]
fn prove_pop(bencher: Bencher) {
let sk = BlsSecretKey::<BlsScIetf>::generate(&test_ikm(1)).unwrap();
let sk = BlsSecretKey::<BlsScIetf>::from_ikm(&test_ikm(1)).unwrap();
bencher.bench(|| sk.prove_possession());
}

/// Proof of possession verification.
#[divan::bench]
fn verify_pop(bencher: Bencher) {
let sk = BlsSecretKey::<BlsScIetf>::generate(&test_ikm(1)).unwrap();
let sk = BlsSecretKey::<BlsScIetf>::from_ikm(&test_ikm(1)).unwrap();
let pop = sk.prove_possession();
let pk = sk.public_key();
bencher.bench(|| pk.verify_possession(&pop));
Expand Down
36 changes: 18 additions & 18 deletions pkgs/pkc/corpus/bls_llmq_100.json5
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"t": 2,
"n": 3,
"member_ids": [
"3c2e73326b4bca39433fd0059fcced12cb57fe8a30b00895f1b41b67ac94a28b",
"d876b7f4b6a1ca8ee6703ce4f30341556c0f6af047b5294a427407aa065b7564",
"e07311fbdb796b3cc482ea34969e67eb6ef88bce50441682327d26d38ef6d115"
"8ba294ac671bb4f19508b0308afe57cb12edcc9f05d03f4339ca4b6b32732e3c",
"64755b06aa0774424a29b547f06a0f6c554103f3e43c70e68ecaa1b6f4b776d8",
"15d1f68ed3267d3282164450ce8bf86eeb679e9634ea82c43c6b79dbfb1173e0"
]
},
"contribute": [
{
"quorum_hash": "327186a034d2dac99bc5c3557fd204ffca52aa8d21cbe426fe39a09145b6dd59",
"llmq_type": 100,
"member_idx": 0,
"member_id": "3c2e73326b4bca39433fd0059fcced12cb57fe8a30b00895f1b41b67ac94a28b",
"member_id": "8ba294ac671bb4f19508b0308afe57cb12edcc9f05d03f4339ca4b6b32732e3c",
"vvec": [
"8909e5ae37f2096a9d74f29b46153540abc1c22e0fab2727d1c13b84975acab50b9d9d2d1d9351eadd2167b9f85d83e8",
"03b8fc232a21fac07928b5fb339ebc9fe908d9597a30e4b9e1b60484900975f69852617bb2e9f95613ef236d0fe75742"
Expand All @@ -30,7 +30,7 @@
"quorum_hash": "327186a034d2dac99bc5c3557fd204ffca52aa8d21cbe426fe39a09145b6dd59",
"llmq_type": 100,
"member_idx": 1,
"member_id": "d876b7f4b6a1ca8ee6703ce4f30341556c0f6af047b5294a427407aa065b7564",
"member_id": "64755b06aa0774424a29b547f06a0f6c554103f3e43c70e68ecaa1b6f4b776d8",
"vvec": [
"17f1975a973f905c6242c966dbf0d0ee7b18892850516b17ba37860d12459ef1ed3ed90ded5dfd66a21f6340b89d8bf0",
"8a108caf8b51b0b79f64bdce6b4ba57b41c53caf5acb4b36d1e8c2a4d4c25442cdc43b1011fdf60ee242c53766f10e97"
Expand All @@ -45,7 +45,7 @@
"quorum_hash": "327186a034d2dac99bc5c3557fd204ffca52aa8d21cbe426fe39a09145b6dd59",
"llmq_type": 100,
"member_idx": 2,
"member_id": "e07311fbdb796b3cc482ea34969e67eb6ef88bce50441682327d26d38ef6d115",
"member_id": "15d1f68ed3267d3282164450ce8bf86eeb679e9634ea82c43c6b79dbfb1173e0",
"vvec": [
"924d93a80009fee628ef86114d48e123f88f8ce985f86b4793f3109ce27d609167a6eed4440d12241c6439673bf4d7d5",
"043c0fdf9503194bbaa7baea4024a1678173c7df7cf47805a02ba8aa31ca76f972d13164c6f9036ee76009e2cc2f4214"
Expand Down Expand Up @@ -206,9 +206,9 @@
"quorum_hash": "327186a034d2dac99bc5c3557fd204ffca52aa8d21cbe426fe39a09145b6dd59",
"llmq_type": 100,
"signer_ids": [
"d876b7f4b6a1ca8ee6703ce4f30341556c0f6af047b5294a427407aa065b7564",
"e07311fbdb796b3cc482ea34969e67eb6ef88bce50441682327d26d38ef6d115",
"3c2e73326b4bca39433fd0059fcced12cb57fe8a30b00895f1b41b67ac94a28b"
"64755b06aa0774424a29b547f06a0f6c554103f3e43c70e68ecaa1b6f4b776d8",
"15d1f68ed3267d3282164450ce8bf86eeb679e9634ea82c43c6b79dbfb1173e0",
"8ba294ac671bb4f19508b0308afe57cb12edcc9f05d03f4339ca4b6b32732e3c"
],
"threshold_sigs": [
"891c7dd2352567408501984716e07ea5d2180edcf5f692a0d602a7f67fd1f8e42939106e0b1fa74441c1cd742b914071125931c2cfad37986c9c2f52a0deea3a66573bcf4f683f1185f3d49b233d0899452fabd976c068d96fa2e985af997fcb",
Expand All @@ -235,17 +235,17 @@
"t": 2,
"n": 3,
"member_ids": [
"e07311fbdb796b3cc482ea34969e67eb6ef88bce50441682327d26d38ef6d115",
"d876b7f4b6a1ca8ee6703ce4f30341556c0f6af047b5294a427407aa065b7564",
"3c2e73326b4bca39433fd0059fcced12cb57fe8a30b00895f1b41b67ac94a28b"
"15d1f68ed3267d3282164450ce8bf86eeb679e9634ea82c43c6b79dbfb1173e0",
"64755b06aa0774424a29b547f06a0f6c554103f3e43c70e68ecaa1b6f4b776d8",
"8ba294ac671bb4f19508b0308afe57cb12edcc9f05d03f4339ca4b6b32732e3c"
]
},
"contribute": [
{
"quorum_hash": "255258ad1a339cd05cbecb5517eac0e2511f12ead05b24390d4bc4db74895b8e",
"llmq_type": 100,
"member_idx": 0,
"member_id": "e07311fbdb796b3cc482ea34969e67eb6ef88bce50441682327d26d38ef6d115",
"member_id": "15d1f68ed3267d3282164450ce8bf86eeb679e9634ea82c43c6b79dbfb1173e0",
"vvec": [
"b87aa119acd3fab719fb63a55e820373a66dd09b9947cd6c267a1c291b3cd2bbc2c96f55e01172fe7bdad0e90ff1d052",
"a0402a8d9446920e75db62509eb22ec5292d38118a734e50a52c311eb6cd5ff44ca40b8dfd703ef4f762176b2010eb72"
Expand All @@ -260,7 +260,7 @@
"quorum_hash": "255258ad1a339cd05cbecb5517eac0e2511f12ead05b24390d4bc4db74895b8e",
"llmq_type": 100,
"member_idx": 1,
"member_id": "d876b7f4b6a1ca8ee6703ce4f30341556c0f6af047b5294a427407aa065b7564",
"member_id": "64755b06aa0774424a29b547f06a0f6c554103f3e43c70e68ecaa1b6f4b776d8",
"vvec": [
"88f334f0b6a8041dddec22e2394e1285dbf97f35a51db822b767317b40276a3a754ad07ddd2e42e9f91bf1d86e9b4981",
"878cb8a5571a7e3b3005e5f08dbdcc21c1cff31f6c5b2404514e94e3b618cda90cff03cfd58e1827e2a67c6632c62784"
Expand All @@ -275,7 +275,7 @@
"quorum_hash": "255258ad1a339cd05cbecb5517eac0e2511f12ead05b24390d4bc4db74895b8e",
"llmq_type": 100,
"member_idx": 2,
"member_id": "3c2e73326b4bca39433fd0059fcced12cb57fe8a30b00895f1b41b67ac94a28b",
"member_id": "8ba294ac671bb4f19508b0308afe57cb12edcc9f05d03f4339ca4b6b32732e3c",
"vvec": [
"9151e824541fe71097c5264314d23e94246a17cc00c8aae6a82f8497da35a86a30b43adb7a926d301972dd95f70835f9",
"828caa3890dcce53d7e5b6cb81de2d113c7e6a39d20a7a9860aaac43234fd90347cbd3b649f4d2e6d9d7a35feed0af0b"
Expand Down Expand Up @@ -436,9 +436,9 @@
"quorum_hash": "255258ad1a339cd05cbecb5517eac0e2511f12ead05b24390d4bc4db74895b8e",
"llmq_type": 100,
"signer_ids": [
"d876b7f4b6a1ca8ee6703ce4f30341556c0f6af047b5294a427407aa065b7564",
"e07311fbdb796b3cc482ea34969e67eb6ef88bce50441682327d26d38ef6d115",
"3c2e73326b4bca39433fd0059fcced12cb57fe8a30b00895f1b41b67ac94a28b"
"64755b06aa0774424a29b547f06a0f6c554103f3e43c70e68ecaa1b6f4b776d8",
"15d1f68ed3267d3282164450ce8bf86eeb679e9634ea82c43c6b79dbfb1173e0",
"8ba294ac671bb4f19508b0308afe57cb12edcc9f05d03f4339ca4b6b32732e3c"
],
"threshold_sigs": [
"9672626d610163865918c1c94f40b63f39041d2236234752043c25d99fa30a0b9ba22c5087bc5d284f8a400196825cba17889af1a1012da65a0ded0e5a180e3195f9857328fe2cf82193cc014557f011d24d02dcc77e7e2e0361ca6a39e2d8fc",
Expand Down
30 changes: 30 additions & 0 deletions pkgs/pkc/src/bls/blst_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,21 @@ impl G1Affine {
}
Ok(Self(aff))
}

/// Deserialize a 96-byte uncompressed G1 point.
///
/// # Errors
///
/// Returns the blst error code when the bytes do not encode a point on the
/// curve.
pub(crate) fn deserialize(bytes: &[u8; 96]) -> Result<Self, BLST_ERROR> {
let mut aff = blst_p1_affine::default();
let rc = unsafe { blst_p1_deserialize(&mut aff, bytes.as_ptr()) };
if rc != BLST_ERROR::BLST_SUCCESS {
return Err(rc);
}
Ok(Self(aff))
}
}

impl G2 {
Expand Down Expand Up @@ -527,4 +542,19 @@ impl G2Affine {
}
Ok(Self(aff))
}

/// Deserialize a 192-byte uncompressed G2 point.
///
/// # Errors
///
/// Returns the blst error code when the bytes do not encode a point on the
/// curve.
pub(crate) fn deserialize(bytes: &[u8; 192]) -> Result<Self, BLST_ERROR> {
let mut aff = blst_p2_affine::default();
let rc = unsafe { blst_p2_deserialize(&mut aff, bytes.as_ptr()) };
if rc != BLST_ERROR::BLST_SUCCESS {
return Err(rc);
}
Ok(Self(aff))
}
}
Loading