1use std::str::FromStr;
2
3use crate::SignatureError;
4use ark_bn254::Fq;
5use ark_bn254::Fq2;
6use ark_bn254::Fr;
7use ark_bn254::G1Affine;
8use ark_bn254::G1Projective;
9use ark_bn254::G2Affine;
10use ark_bn254::G2Projective;
11use ark_ff::PrimeField;
12use ark_groth16::PreparedVerifyingKey;
13use ark_groth16::Proof;
14use sui_sdk_types::Bn254FieldElement;
15use sui_sdk_types::CircomG1;
16use sui_sdk_types::CircomG2;
17use sui_sdk_types::Ed25519PublicKey;
18use sui_sdk_types::Jwk;
19use sui_sdk_types::Secp256k1PublicKey;
20use sui_sdk_types::Secp256r1PublicKey;
21use sui_sdk_types::SimpleSignature;
22use sui_sdk_types::ZkLoginInputs;
23use sui_sdk_types::ZkLoginProof;
24
25use super::POSEIDON;
26
27#[derive(Clone, Debug)]
28pub struct VerifyingKey {
29 inner: PreparedVerifyingKey<ark_bn254::Bn254>,
30}
31
32const fn str_to_bn254(s: &str) -> Bn254FieldElement {
33 match Bn254FieldElement::from_str_radix_10(s) {
34 Ok(e) => e,
35 Err(_) => panic!("unable to convert bn254"),
36 }
37}
38
39const fn build_circom_g1([e0, e1, e2]: [&str; 3]) -> CircomG1 {
40 CircomG1([str_to_bn254(e0), str_to_bn254(e1), str_to_bn254(e2)])
41}
42
43const fn build_circom_g2([[e00, e01], [e10, e11], [e20, e21]]: [[&str; 2]; 3]) -> CircomG2 {
44 CircomG2([
45 [str_to_bn254(e00), str_to_bn254(e01)],
46 [str_to_bn254(e10), str_to_bn254(e11)],
47 [str_to_bn254(e20), str_to_bn254(e21)],
48 ])
49}
50
51fn circom_to_arkworks_g1(g1: &CircomG1) -> Result<G1Affine, SignatureError> {
52 let CircomG1([f0, f1, f2]) = g1;
53
54 let g1: G1Affine =
55 G1Projective::new_unchecked(bn254_to_fq(f0), bn254_to_fq(f1), bn254_to_fq(f2)).into();
56
57 if !g1.is_on_curve() || !g1.is_in_correct_subgroup_assuming_on_curve() {
58 return Err(SignatureError::from_source("invalid G1 input"));
59 }
60
61 Ok(g1)
62}
63
64fn circom_to_arkworks_g2(g2: &CircomG2) -> Result<G2Affine, SignatureError> {
65 let CircomG2([[f00, f01], [f10, f11], [f20, f21]]) = g2;
66
67 let g2: G2Affine = G2Projective::new_unchecked(
68 Fq2::new(bn254_to_fq(f00), bn254_to_fq(f01)),
69 Fq2::new(bn254_to_fq(f10), bn254_to_fq(f11)),
70 Fq2::new(bn254_to_fq(f20), bn254_to_fq(f21)),
71 )
72 .into();
73
74 if !g2.is_on_curve() || !g2.is_in_correct_subgroup_assuming_on_curve() {
75 return Err(SignatureError::from_source("invalid G2 input"));
76 }
77
78 Ok(g2)
79}
80
81fn bn254_to_fq(f: &Bn254FieldElement) -> Fq {
82 Fq::from_be_bytes_mod_order(f.padded())
83}
84
85fn bn254_to_fr(f: &Bn254FieldElement) -> Fr {
86 Fr::from_be_bytes_mod_order(f.padded())
87}
88
89fn mainnet_verifying_key() -> VerifyingKey {
90 const CIRCOM_ALPHA_G1: CircomG1 = build_circom_g1([
91 "21529901943976716921335152104180790524318946701278905588288070441048877064089",
92 "7775817982019986089115946956794180159548389285968353014325286374017358010641",
93 "1",
94 ]);
95
96 const CIRCOM_BETA_G2: CircomG2 = build_circom_g2([
97 [
98 "6600437987682835329040464538375790690815756241121776438004683031791078085074",
99 "16207344858883952201936462217289725998755030546200154201671892670464461194903",
100 ],
101 [
102 "17943105074568074607580970189766801116106680981075272363121544016828311544390",
103 "18339640667362802607939727433487930605412455701857832124655129852540230493587",
104 ],
105 ["1", "0"],
106 ]);
107
108 const CIRCOM_GAMMA_G2: CircomG2 = build_circom_g2([
109 [
110 "10857046999023057135944570762232829481370756359578518086990519993285655852781",
111 "11559732032986387107991004021392285783925812861821192530917403151452391805634",
112 ],
113 [
114 "8495653923123431417604973247489272438418190587263600148770280649306958101930",
115 "4082367875863433681332203403145435568316851327593401208105741076214120093531",
116 ],
117 ["1", "0"],
118 ]);
119
120 const CIRCOM_DELTA_G2: CircomG2 = build_circom_g2([
121 [
122 "19260309516619721648285279557078789954438346514188902804737557357941293711874",
123 "2480422554560175324649200374556411861037961022026590718777465211464278308900",
124 ],
125 [
126 "14489104692423540990601374549557603533921811847080812036788172274404299703364",
127 "12564378633583954025611992187142343628816140907276948128970903673042690269191",
128 ],
129 ["1", "0"],
130 ]);
131
132 const CIRCOM_GAMMA_ABC_G1: [CircomG1; 2] = [
133 build_circom_g1([
134 "1607694606386445293170795095076356565829000940041894770459712091642365695804",
135 "18066827569413962196795937356879694709963206118612267170825707780758040578649",
136 "1",
137 ]),
138 build_circom_g1([
139 "20653794344898475822834426774542692225449366952113790098812854265588083247207",
140 "3296759704176575765409730962060698204792513807296274014163938591826372646699",
141 "1",
142 ]),
143 ];
144
145 let vk = ark_groth16::VerifyingKey {
146 alpha_g1: circom_to_arkworks_g1(&CIRCOM_ALPHA_G1).unwrap(),
147 beta_g2: circom_to_arkworks_g2(&CIRCOM_BETA_G2).unwrap(),
148 gamma_g2: circom_to_arkworks_g2(&CIRCOM_GAMMA_G2).unwrap(),
149 delta_g2: circom_to_arkworks_g2(&CIRCOM_DELTA_G2).unwrap(),
150 gamma_abc_g1: CIRCOM_GAMMA_ABC_G1
151 .iter()
152 .map(circom_to_arkworks_g1)
153 .collect::<Result<_, _>>()
154 .unwrap(),
155 };
156
157 VerifyingKey {
158 inner: PreparedVerifyingKey::from(vk),
159 }
160}
161
162fn dev_verifying_key() -> VerifyingKey {
164 const CIRCOM_ALPHA_G1: CircomG1 = build_circom_g1([
165 "20491192805390485299153009773594534940189261866228447918068658471970481763042",
166 "9383485363053290200918347156157836566562967994039712273449902621266178545958",
167 "1",
168 ]);
169
170 const CIRCOM_BETA_G2: CircomG2 = build_circom_g2([
171 [
172 "6375614351688725206403948262868962793625744043794305715222011528459656738731",
173 "4252822878758300859123897981450591353533073413197771768651442665752259397132",
174 ],
175 [
176 "10505242626370262277552901082094356697409835680220590971873171140371331206856",
177 "21847035105528745403288232691147584728191162732299865338377159692350059136679",
178 ],
179 ["1", "0"],
180 ]);
181
182 const CIRCOM_GAMMA_G2: CircomG2 = build_circom_g2([
183 [
184 "10857046999023057135944570762232829481370756359578518086990519993285655852781",
185 "11559732032986387107991004021392285783925812861821192530917403151452391805634",
186 ],
187 [
188 "8495653923123431417604973247489272438418190587263600148770280649306958101930",
189 "4082367875863433681332203403145435568316851327593401208105741076214120093531",
190 ],
191 ["1", "0"],
192 ]);
193
194 const CIRCOM_DELTA_G2: CircomG2 = build_circom_g2([
195 [
196 "10857046999023057135944570762232829481370756359578518086990519993285655852781",
197 "11559732032986387107991004021392285783925812861821192530917403151452391805634",
198 ],
199 [
200 "8495653923123431417604973247489272438418190587263600148770280649306958101930",
201 "4082367875863433681332203403145435568316851327593401208105741076214120093531",
202 ],
203 ["1", "0"],
204 ]);
205
206 const CIRCOM_GAMMA_ABC_G1: [CircomG1; 2] = [
207 build_circom_g1([
208 "20701306374481714853949730154526815782802808896228594855451770849676897643964",
209 "2766989084754673216772682210231588284954002353414778477810174100808747060165",
210 "1",
211 ]),
212 build_circom_g1([
213 "501195541410525737371980194958674422793469475773065719916327137354779402600",
214 "13527631693157515024233848630878973193664410306029731429350155106228769355415",
215 "1",
216 ]),
217 ];
218
219 let vk = ark_groth16::VerifyingKey {
220 alpha_g1: circom_to_arkworks_g1(&CIRCOM_ALPHA_G1).unwrap(),
221 beta_g2: circom_to_arkworks_g2(&CIRCOM_BETA_G2).unwrap(),
222 gamma_g2: circom_to_arkworks_g2(&CIRCOM_GAMMA_G2).unwrap(),
223 delta_g2: circom_to_arkworks_g2(&CIRCOM_DELTA_G2).unwrap(),
224 gamma_abc_g1: CIRCOM_GAMMA_ABC_G1
225 .iter()
226 .map(circom_to_arkworks_g1)
227 .collect::<Result<_, _>>()
228 .unwrap(),
229 };
230
231 VerifyingKey::new(PreparedVerifyingKey::from(vk))
232}
233
234impl VerifyingKey {
235 fn new(inner: PreparedVerifyingKey<ark_bn254::Bn254>) -> Self {
236 Self { inner }
237 }
238
239 pub fn new_mainnet() -> Self {
240 mainnet_verifying_key()
241 }
242
243 pub fn new_dev() -> Self {
244 dev_verifying_key()
245 }
246
247 pub fn verify_zklogin(
248 &self,
249 jwk: &Jwk,
250 inputs: &ZkLoginInputs,
251 signature: &SimpleSignature,
252 max_epoch: u64,
253 ) -> Result<(), SignatureError> {
254 use base64ct::Base64UrlUnpadded;
255 use base64ct::Encoding;
256 let modulus = Base64UrlUnpadded::decode_vec(&jwk.n)
258 .map_err(|e| SignatureError::from_source(e.to_string()))?;
259
260 let proof = zklogin_proof_to_arkworks(&inputs.proof_points).unwrap();
261 let input_hash = calculate_all_inputs_hash(inputs, signature, &modulus, max_epoch).unwrap();
262
263 self.verify_proof(&proof, &[input_hash])
264 }
265
266 fn verify_proof(
267 &self,
268 proof: &Proof<ark_bn254::Bn254>,
269 public_inputs: &[ark_bn254::Fr],
270 ) -> Result<(), SignatureError> {
271 use ark_snark::SNARK;
272
273 if ark_groth16::Groth16::<ark_bn254::Bn254>::verify_with_processed_vk(
274 &self.inner,
275 public_inputs,
276 proof,
277 )
278 .map_err(|e| SignatureError::from_source(e.to_string()))?
279 {
280 Ok(())
281 } else {
282 Err(SignatureError::from_source("Groth16 proof verify failed"))
283 }
284 }
285}
286
287fn zklogin_proof_to_arkworks(
288 proof: &ZkLoginProof,
289) -> Result<Proof<ark_bn254::Bn254>, SignatureError> {
290 Ok(Proof {
291 a: circom_to_arkworks_g1(&proof.a)?,
292 b: circom_to_arkworks_g2(&proof.b)?,
293 c: circom_to_arkworks_g1(&proof.c)?,
294 })
295}
296
297pub fn public_key_to_frs(signature: &SimpleSignature) -> (Fr, Fr) {
300 let mut buf = [0u8; 34];
303
304 buf[0] = signature.scheme().to_u8();
305
306 let buf = match signature {
307 SimpleSignature::Ed25519 { public_key, .. } => {
308 buf[1..Ed25519PublicKey::LENGTH + 1].copy_from_slice(public_key.inner());
309 &buf[..Ed25519PublicKey::LENGTH + 1]
310 }
311 SimpleSignature::Secp256k1 { public_key, .. } => {
312 buf[1..Secp256k1PublicKey::LENGTH + 1].copy_from_slice(public_key.inner());
313 &buf[..Secp256k1PublicKey::LENGTH + 1]
314 }
315 SimpleSignature::Secp256r1 { public_key, .. } => {
316 buf[1..Secp256r1PublicKey::LENGTH + 1].copy_from_slice(public_key.inner());
317 &buf[..Secp256r1PublicKey::LENGTH + 1]
318 }
319 };
320
321 let (first_half, second_half) = buf.split_at(buf.len() - 16);
325
326 let eph_public_key_0 = Fr::from_be_bytes_mod_order(first_half);
327 let eph_public_key_1 = Fr::from_be_bytes_mod_order(second_half);
328 (eph_public_key_0, eph_public_key_1)
329}
330
331pub(crate) type U256 = bnum::BUintD8<32>;
332pub(crate) type U2048 = bnum::BUintD8<256>;
333
334const MAX_HEADER_LEN: u8 = 248;
335const PACK_WIDTH: u8 = 248;
336#[allow(unused)]
337const ISS: &str = "iss";
338#[allow(unused)]
339const BASE64_URL_CHARSET: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
340const MAX_EXT_ISS_LEN: u8 = 165;
341const MAX_ISS_LEN_B64: u8 = 4 * (1 + MAX_EXT_ISS_LEN / 3);
342
343pub fn hash_ascii_str_to_field(s: &str, max_size: u8) -> Result<Fr, SignatureError> {
345 let str_padded = str_to_padded_char_codes(s, max_size)?;
346 hash_to_field(&str_padded, 8, PACK_WIDTH)
347}
348
349fn str_to_padded_char_codes(s: &str, max_len: u8) -> Result<Vec<U256>, SignatureError> {
350 let arr: Vec<U256> = s.bytes().map(U256::from).collect();
351 pad_with_zeroes(arr, max_len)
352}
353
354fn pad_with_zeroes(in_arr: Vec<U256>, out_count: u8) -> Result<Vec<U256>, SignatureError> {
355 if in_arr.len() > out_count as usize {
356 return Err(SignatureError::from_source("in_arr too long"));
357 }
358 let mut padded = in_arr;
359 padded.resize(out_count as usize, U256::ZERO);
360 Ok(padded)
361}
362
363fn hash_to_field<T: ToBits>(
368 input: &[T],
369 in_width: u16,
370 pack_width: u8,
371) -> Result<Fr, SignatureError> {
372 let packed = convert_base(input, in_width, pack_width)?;
373
374 POSEIDON.hash(&packed).map_err(SignatureError::from_source)
375}
376
377fn convert_base<T: ToBits>(
379 in_arr: &[T],
380 in_width: u16,
381 out_width: u8,
382) -> Result<Vec<Fr>, SignatureError> {
383 if out_width == 0 {
384 return Err(SignatureError::from_source("invalid input"));
385 }
386 let bits = big_int_array_to_bits(in_arr, in_width as usize)?;
387 let mut packed: Vec<Fr> = bits
388 .rchunks(out_width as usize)
389 .map(|chunk| {
390 Fr::from_be_bytes_mod_order(U256::from_radix_be(chunk, 2).unwrap().to_be().digits())
391 })
392 .collect();
393 packed.reverse();
394 match packed.len() != (in_arr.len() * in_width as usize).div_ceil(out_width as usize) {
395 true => Err(SignatureError::from_source("invalid input")),
396 false => Ok(packed),
397 }
398}
399
400fn big_int_array_to_bits<T: ToBits>(
402 integers: &[T],
403 intended_size: usize,
404) -> Result<Vec<u8>, SignatureError> {
405 use itertools::Itertools;
406 use std::cmp::Ordering::Equal;
407 use std::cmp::Ordering::Greater;
408 use std::cmp::Ordering::Less;
409
410 integers
411 .iter()
412 .map(|integer| {
413 let bits = integer.to_bits();
414 match bits.len().cmp(&intended_size) {
415 Less => {
416 let extra_bits = intended_size - bits.len();
417 let mut padded = vec![0; extra_bits];
418 padded.extend(bits);
419 Ok(padded)
420 }
421 Equal => Ok(bits),
422 Greater => Err(SignatureError::from_source("invalid input")),
423 }
424 })
425 .flatten_ok()
426 .collect()
427}
428
429trait ToBits {
430 fn to_bits(&self) -> Vec<u8>;
431}
432
433impl ToBits for U256 {
434 fn to_bits(&self) -> Vec<u8> {
435 self.to_radix_be(2)
436 }
437}
438
439impl ToBits for U2048 {
440 fn to_bits(&self) -> Vec<u8> {
441 self.to_radix_be(2)
442 }
443}
444
445pub fn calculate_all_inputs_hash(
447 inputs: &ZkLoginInputs,
448 signature: &SimpleSignature,
449 modulus: &[u8],
450 max_epoch: u64,
451) -> Result<Fr, SignatureError> {
452 if inputs.header_base64.len() > MAX_HEADER_LEN as usize {
453 return Err(SignatureError::from_source("header too long"));
454 }
455
456 let (first, second) = public_key_to_frs(signature);
457
458 let address_seed = bn254_to_fr(&inputs.address_seed);
459 let max_epoch_f = Fr::from_be_bytes_mod_order(U256::from(max_epoch).to_be().digits());
460 let index_mod_4_f = Fr::from_be_bytes_mod_order(
461 U256::from(inputs.iss_base64_details.index_mod_4)
462 .to_be()
463 .digits(),
464 );
465
466 let iss_base64_f = hash_ascii_str_to_field(&inputs.iss_base64_details.value, MAX_ISS_LEN_B64)?;
467 let header_f = hash_ascii_str_to_field(&inputs.header_base64, MAX_HEADER_LEN)?;
468 let modulus_f = hash_to_field(&[U2048::from_be_slice(modulus).unwrap()], 2048, PACK_WIDTH)?;
469
470 POSEIDON
471 .hash(&[
472 first,
473 second,
474 address_seed,
475 max_epoch_f,
476 iss_base64_f,
477 index_mod_4_f,
478 header_f,
479 modulus_f,
480 ])
481 .map_err(SignatureError::from_source)
482}
483
484#[allow(unused)]
486fn gen_address_seed(
487 salt: &str,
488 name: &str, value: &str, aud: &str, ) -> Result<String, SignatureError> {
492 let salt_hash = POSEIDON
493 .hash(&[bn254_to_fr(
494 &Bn254FieldElement::from_str(salt).map_err(SignatureError::from_source)?,
495 )])
496 .map_err(SignatureError::from_source)?;
497 gen_address_seed_with_salt_hash(salt_hash, name, value, aud)
498}
499
500const MAX_KEY_CLAIM_NAME_LENGTH: u8 = 32;
501const MAX_KEY_CLAIM_VALUE_LENGTH: u8 = 115;
502const MAX_AUD_VALUE_LENGTH: u8 = 145;
503
504pub(crate) fn gen_address_seed_with_salt_hash(
506 salt_hash: Fr,
507 name: &str, value: &str, aud: &str, ) -> Result<String, SignatureError> {
511 Ok(POSEIDON
512 .hash(&[
513 hash_ascii_str_to_field(name, MAX_KEY_CLAIM_NAME_LENGTH)?,
514 hash_ascii_str_to_field(value, MAX_KEY_CLAIM_VALUE_LENGTH)?,
515 hash_ascii_str_to_field(aud, MAX_AUD_VALUE_LENGTH)?,
516 salt_hash,
517 ])
518 .map_err(SignatureError::from_source)?
519 .to_string())
520}
521
522#[cfg(test)]
523mod test {
524 use super::*;
525 use sui_sdk_types::Ed25519Signature;
526
527 #[cfg(test)]
528 #[cfg(target_arch = "wasm32")]
529 use wasm_bindgen_test::wasm_bindgen_test as test;
530
531 #[test]
532 fn test_verify_zklogin_google() {
533 let user_salt = "206703048842351542647799591018316385612";
534
535 let pubkey = Ed25519PublicKey::new([
536 185, 198, 238, 22, 48, 239, 62, 113, 17, 68, 166, 72, 219, 6, 187, 178, 40, 79, 114,
537 116, 207, 190, 229, 63, 252, 238, 80, 60, 193, 164, 146, 0,
538 ]);
539 let signature = SimpleSignature::Ed25519 {
540 signature: Ed25519Signature::new([0; 64]),
541 public_key: pubkey,
542 };
543
544 let address_seed = gen_address_seed(
546 user_salt,
547 "sub",
548 "106294049240999307923",
549 "25769832374-famecqrhe2gkebt5fvqms2263046lj96.apps.googleusercontent.com",
550 )
551 .unwrap();
552
553 let inputs = serde_json::json!({
554 "proof_points": {
555 "a": [
556 "8247215875293406890829839156897863742504615191361518281091302475904551111016",
557 "6872980335748205979379321982220498484242209225765686471076081944034292159666",
558 "1"
559 ],
560 "b": [
561 [
562 "21419680064642047510915171723230639588631899775315750803416713283740137406807",
563 "21566716915562037737681888858382287035712341650647439119820808127161946325890"
564 ],
565 [
566 "17867714710686394159919998503724240212517838710399045289784307078087926404555",
567 "21812769875502013113255155836896615164559280911997219958031852239645061854221"
568 ],
569 ["1","0"]
570 ],
571 "c": [
572 "7530826803702928198368421787278524256623871560746240215547076095911132653214",
573 "16244547936249959771862454850485726883972969173921727256151991751860694123976",
574 "1"
575 ]
576 },
577 "iss_base64_details": {
578 "value": "yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC",
579 "index_mod_4": 1
580 },
581 "header_base64": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZmNzI1NDEwMWY1NmU0MWNmMzVjOTkyNmRlODRhMmQ1NTJiNGM2ZjEiLCJ0eXAiOiJKV1QifQ",
582 "address_seed": address_seed
583 });
584
585 let zklogin_inputs: ZkLoginInputs = serde_json::from_value(inputs).unwrap();
586
587 let jwk = Jwk {
588 kty: "RSA".to_string(),
589 e: "AQAB".to_string(),
590 n: "oUriU8GqbRw-avcMn95DGW1cpZR1IoM6L7krfrWvLSSCcSX6Ig117o25Yk7QWBiJpaPV0FbP7Y5-DmThZ3SaF0AXW-3BsKPEXfFfeKVc6vBqk3t5mKlNEowjdvNTSzoOXO5UIHwsXaxiJlbMRalaFEUm-2CKgmXl1ss_yGh1OHkfnBiGsfQUndKoHiZuDzBMGw8Sf67am_Ok-4FShK0NuR3-q33aB_3Z7obC71dejSLWFOEcKUVCaw6DGVuLog3x506h1QQ1r0FXKOQxnmqrRgpoHqGSouuG35oZve1vgCU4vLZ6EAgBAbC0KL35I7_0wUDSMpiAvf7iZxzJVbspkQ".to_string(),
591 alg: "RS256".to_string(),
592 };
593
594 VerifyingKey::new_mainnet()
595 .verify_zklogin(&jwk, &zklogin_inputs, &signature, 10)
596 .unwrap();
597 }
598
599 #[test]
600 fn test_public_key_to_frs() {
601 let pubkey = Ed25519PublicKey::new([
602 185, 198, 238, 22, 48, 239, 62, 113, 17, 68, 166, 72, 219, 6, 187, 178, 40, 79, 114,
603 116, 207, 190, 229, 63, 252, 238, 80, 60, 193, 164, 146, 0,
604 ]);
605 let signature = SimpleSignature::Ed25519 {
606 signature: Ed25519Signature::new([0; 64]),
607 public_key: pubkey,
608 };
609 let (actual_0, actual_1) = public_key_to_frs(&signature);
610 let expect_0 = Fr::from(ark_ff::BigInt([
611 1244302228903607218,
612 13386648721483054705,
613 0,
614 0,
615 ]));
616
617 let expect_1 = Fr::from(ark_ff::BigInt([
618 18225592963892023808,
619 2904666130704426303,
620 0,
621 0,
622 ]));
623 assert_eq!(actual_0, expect_0);
624 assert_eq!(actual_1, expect_1);
625 }
626
627 #[test]
628 fn test_hash_ascii_str_to_field() {
629 let actual = hash_ascii_str_to_field("sub", 32).unwrap();
630 let expect = Fr::from(ark_ff::BigInt([
631 9420274050661827129,
632 9736100402995345242,
633 10431892319505233812,
634 1450152190758097105,
635 ]));
636 assert_eq!(actual, expect);
637
638 let actual = hash_ascii_str_to_field("106294049240999307923", 115).unwrap();
639 let expect = Fr::from(ark_ff::BigInt([
640 1616959301818912987,
641 17318965991705091209,
642 15303466056770245354,
643 1596136658728187659,
644 ]));
645 assert_eq!(actual, expect);
646
647 let actual = hash_ascii_str_to_field(
648 "25769832374-famecqrhe2gkebt5fvqms2263046lj96.apps.googleusercontent.com",
649 145,
650 )
651 .unwrap();
652 let expect = Fr::from(ark_ff::BigInt([
653 5030944271044826582,
654 8577618269522081956,
655 6962871209781429610,
656 2149811477348923117,
657 ]));
658 assert_eq!(actual, expect);
659
660 let actual =
661 hash_ascii_str_to_field("yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC", 224)
662 .unwrap();
663 let expect = Fr::from(ark_ff::BigInt([
664 6021918591354572765,
665 14069258108381575504,
666 1736509627917450843,
667 2767185135515367512,
668 ]));
669 assert_eq!(actual, expect);
670
671 let actual = hash_ascii_str_to_field(
672 "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZmNzI1NDEwMWY1NmU0MWNmMzVjOTkyNmRlODRhMmQ1NTJiNGM2ZjEiLCJ0eXAiOiJKV1QifQ",
673 248,
674 ).unwrap();
675 let expect = Fr::from(ark_ff::BigInt([
676 4239129243150064016,
677 15469804315138207306,
678 17534492051703966556,
679 2100329545252322607,
680 ]));
681 assert_eq!(actual, expect);
682 }
683}