Skip to main content

sui_sdk_types/crypto/
mod.rs

1mod bls12381;
2mod ed25519;
3mod intent;
4mod mldsa65;
5mod multisig;
6mod passkey;
7mod secp256k1;
8mod secp256r1;
9mod signature;
10mod validator;
11mod zklogin;
12
13pub use bls12381::Bls12381PublicKey;
14pub use bls12381::Bls12381Signature;
15pub use ed25519::Ed25519PublicKey;
16pub use ed25519::Ed25519Signature;
17pub use intent::Intent;
18pub use intent::IntentAppId;
19pub use intent::IntentScope;
20pub use intent::IntentVersion;
21pub use mldsa65::MlDsa65PublicKey;
22pub use mldsa65::MlDsa65Signature;
23pub use multisig::InvalidLegacyBitmapError;
24pub use multisig::MultisigAggregatedSignature;
25pub use multisig::MultisigCommittee;
26pub use multisig::MultisigMember;
27pub use multisig::MultisigMemberPublicKey;
28pub use multisig::MultisigMemberSignature;
29pub use passkey::PasskeyAuthenticator;
30pub use passkey::PasskeyPublicKey;
31pub use secp256k1::Secp256k1PublicKey;
32pub use secp256k1::Secp256k1Signature;
33pub use secp256r1::Secp256r1PublicKey;
34pub use secp256r1::Secp256r1Signature;
35pub use signature::SignatureScheme;
36pub use signature::SimpleSignature;
37pub use signature::UserSignature;
38pub use validator::ValidatorAggregatedSignature;
39pub use validator::ValidatorCommittee;
40pub use validator::ValidatorCommitteeMember;
41pub use validator::ValidatorSignature;
42pub use zklogin::Bn254FieldElement;
43pub use zklogin::CircomG1;
44pub use zklogin::CircomG2;
45pub use zklogin::InvalidZkLoginAuthenticatorError;
46pub use zklogin::Jwk;
47pub use zklogin::JwkId;
48pub use zklogin::ZkLoginAuthenticator;
49pub use zklogin::ZkLoginClaim;
50pub use zklogin::ZkLoginInputs;
51pub use zklogin::ZkLoginProof;
52pub use zklogin::ZkLoginPublicIdentifier;
53
54//
55// Implement various base64 fixed-size array helpers
56//
57
58/// Utility for calculating base64 encoding lengths.
59///
60/// In the Base64 encoding each character is used to represent 6 bits (log2(64) = 6). This means
61/// that 4 characters are used to represent 4*6 = 24 bits = 3 bytes. So you need 4*(`n`/3)
62/// characters in order to represent `n` bytes, and this needs to be rounded up to a multiple of 4.
63/// The number of unused padding characters resulting from the rounding will be 0, 1, 2, or 3.
64const fn base64_encoded_length(len: usize) -> usize {
65    ((4 * len / 3) + 3) & !3
66}
67
68macro_rules! impl_base64_helper {
69    ($base:ident, $display:ident, $fromstr:ident, $test_module:ident, $array_length:literal) => {
70        #[allow(unused)]
71        struct $base;
72
73        impl $base {
74            const LENGTH: usize = $array_length;
75            #[allow(unused)]
76            const ENCODED_LENGTH: usize = base64_encoded_length(Self::LENGTH);
77        }
78
79        #[allow(unused)]
80        struct $display<'a>(&'a [u8; $base::LENGTH]);
81
82        impl<'a> std::fmt::Display for $display<'a> {
83            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84                let mut buf = [0; $base::ENCODED_LENGTH];
85                let encoded =
86                    <base64ct::Base64 as base64ct::Encoding>::encode(self.0, &mut buf).unwrap();
87                f.write_str(encoded)
88            }
89        }
90
91        #[allow(unused)]
92        #[derive(Debug, PartialEq)]
93        #[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
94        struct $fromstr([u8; $base::LENGTH]);
95
96        impl std::str::FromStr for $fromstr {
97            type Err = base64ct::Error;
98
99            fn from_str(s: &str) -> Result<Self, Self::Err> {
100                let mut buf = [0; $base::LENGTH];
101                let decoded = <base64ct::Base64 as base64ct::Encoding>::decode(s, &mut buf)?;
102                if decoded.len() != $base::LENGTH {
103                    return Err(base64ct::Error::InvalidLength);
104                }
105                Ok(Self(buf))
106            }
107        }
108
109        #[cfg(feature = "serde")]
110        #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
111        impl serde_with::SerializeAs<[u8; Self::LENGTH]> for $base {
112            fn serialize_as<S>(
113                source: &[u8; Self::LENGTH],
114                serializer: S,
115            ) -> Result<S::Ok, S::Error>
116            where
117                S: serde::Serializer,
118            {
119                let display = $display(source);
120                serde_with::DisplayFromStr::serialize_as(&display, serializer)
121            }
122        }
123
124        #[cfg(feature = "serde")]
125        #[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
126        impl<'de> serde_with::DeserializeAs<'de, [u8; Self::LENGTH]> for $base {
127            fn deserialize_as<D>(deserializer: D) -> Result<[u8; Self::LENGTH], D::Error>
128            where
129                D: serde::Deserializer<'de>,
130            {
131                let array: $fromstr = serde_with::DisplayFromStr::deserialize_as(deserializer)?;
132                Ok(array.0)
133            }
134        }
135
136        #[cfg(test)]
137        mod $test_module {
138            use super::$display;
139            use super::$fromstr;
140            use test_strategy::proptest;
141
142            #[cfg(target_arch = "wasm32")]
143            use wasm_bindgen_test::wasm_bindgen_test as test;
144
145            #[proptest]
146            fn roundtrip_display_fromstr(array: $fromstr) {
147                let s = $display(&array.0).to_string();
148                let a = s.parse::<$fromstr>().unwrap();
149                assert_eq!(array, a);
150            }
151
152            // Fuzz the `FromStr` impl to ensure it never panics on
153            // arbitrary input. The strategy is restricted to the base64
154            // alphabet so that decode often succeeds, which exercises the
155            // length-validation path rather than bailing out early on
156            // invalid characters.
157            #[proptest]
158            fn fromstr_does_not_panic(#[strategy("[A-Za-z0-9+/=]{0,128}")] s: String) {
159                let _ = s.parse::<$fromstr>();
160            }
161
162            #[test]
163            fn short_decode_errors() {
164                "AAAA".parse::<$fromstr>().unwrap_err();
165            }
166        }
167    };
168}
169
170impl_base64_helper!(Base64Array32, Base64Display32, Base64FromStr32, test32, 32);
171impl_base64_helper!(Base64Array33, Base64Display33, Base64FromStr33, test33, 33);
172impl_base64_helper!(Base64Array34, Base64Display34, Base64FromStr34, test34, 34);
173impl_base64_helper!(Base64Array48, Base64Display48, Base64FromStr48, test48, 48);
174impl_base64_helper!(Base64Array64, Base64Display64, Base64FromStr64, test64, 64);
175impl_base64_helper!(Base64Array96, Base64Display96, Base64FromStr96, test96, 96);
176impl_base64_helper!(
177    Base64Array1952,
178    Base64Display1952,
179    Base64FromStr1952,
180    test1952,
181    1952
182);
183impl_base64_helper!(
184    Base64Array3309,
185    Base64Display3309,
186    Base64FromStr3309,
187    test3309,
188    3309
189);