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;
336const MAX_EXT_ISS_LEN: u8 = 165;
337const MAX_ISS_LEN_B64: u8 = 4 * (1 + MAX_EXT_ISS_LEN / 3);
338
339pub fn hash_ascii_str_to_field(s: &str, max_size: u8) -> Result<Fr, SignatureError> {
341 let str_padded = str_to_padded_char_codes(s, max_size)?;
342 hash_to_field(&str_padded, 8, PACK_WIDTH)
343}
344
345fn str_to_padded_char_codes(s: &str, max_len: u8) -> Result<Vec<U256>, SignatureError> {
346 let arr: Vec<U256> = s.bytes().map(U256::from).collect();
347 pad_with_zeroes(arr, max_len)
348}
349
350fn pad_with_zeroes(in_arr: Vec<U256>, out_count: u8) -> Result<Vec<U256>, SignatureError> {
351 if in_arr.len() > out_count as usize {
352 return Err(SignatureError::from_source("in_arr too long"));
353 }
354 let mut padded = in_arr;
355 padded.resize(out_count as usize, U256::ZERO);
356 Ok(padded)
357}
358
359fn hash_to_field<T: ToBits>(
364 input: &[T],
365 in_width: u16,
366 pack_width: u8,
367) -> Result<Fr, SignatureError> {
368 let packed = convert_base(input, in_width, pack_width)?;
369
370 POSEIDON.hash(&packed).map_err(SignatureError::from_source)
371}
372
373fn convert_base<T: ToBits>(
375 in_arr: &[T],
376 in_width: u16,
377 out_width: u8,
378) -> Result<Vec<Fr>, SignatureError> {
379 if out_width == 0 {
380 return Err(SignatureError::from_source("invalid input"));
381 }
382 let bits = big_int_array_to_bits(in_arr, in_width as usize)?;
383 let mut packed: Vec<Fr> = bits
384 .rchunks(out_width as usize)
385 .map(|chunk| {
386 Fr::from_be_bytes_mod_order(U256::from_radix_be(chunk, 2).unwrap().to_be().digits())
387 })
388 .collect();
389 packed.reverse();
390 match packed.len() != (in_arr.len() * in_width as usize).div_ceil(out_width as usize) {
391 true => Err(SignatureError::from_source("invalid input")),
392 false => Ok(packed),
393 }
394}
395
396fn big_int_array_to_bits<T: ToBits>(
398 integers: &[T],
399 intended_size: usize,
400) -> Result<Vec<u8>, SignatureError> {
401 use itertools::Itertools;
402 use std::cmp::Ordering::Equal;
403 use std::cmp::Ordering::Greater;
404 use std::cmp::Ordering::Less;
405
406 integers
407 .iter()
408 .map(|integer| {
409 let bits = integer.to_bits();
410 match bits.len().cmp(&intended_size) {
411 Less => {
412 let extra_bits = intended_size - bits.len();
413 let mut padded = vec![0; extra_bits];
414 padded.extend(bits);
415 Ok(padded)
416 }
417 Equal => Ok(bits),
418 Greater => Err(SignatureError::from_source("invalid input")),
419 }
420 })
421 .flatten_ok()
422 .collect()
423}
424
425trait ToBits {
426 fn to_bits(&self) -> Vec<u8>;
427}
428
429impl ToBits for U256 {
430 fn to_bits(&self) -> Vec<u8> {
431 self.to_radix_be(2)
432 }
433}
434
435impl ToBits for U2048 {
436 fn to_bits(&self) -> Vec<u8> {
437 self.to_radix_be(2)
438 }
439}
440
441pub fn calculate_all_inputs_hash(
443 inputs: &ZkLoginInputs,
444 signature: &SimpleSignature,
445 modulus: &[u8],
446 max_epoch: u64,
447) -> Result<Fr, SignatureError> {
448 if inputs.header_base64.len() > MAX_HEADER_LEN as usize {
449 return Err(SignatureError::from_source("header too long"));
450 }
451
452 let (first, second) = public_key_to_frs(signature);
453
454 let address_seed = bn254_to_fr(&inputs.address_seed);
455 let max_epoch_f = Fr::from_be_bytes_mod_order(U256::from(max_epoch).to_be().digits());
456 let index_mod_4_f = Fr::from_be_bytes_mod_order(
457 U256::from(inputs.iss_base64_details.index_mod_4)
458 .to_be()
459 .digits(),
460 );
461
462 let iss_base64_f = hash_ascii_str_to_field(&inputs.iss_base64_details.value, MAX_ISS_LEN_B64)?;
463 let header_f = hash_ascii_str_to_field(&inputs.header_base64, MAX_HEADER_LEN)?;
464 let modulus_f = hash_to_field(&[U2048::from_be_slice(modulus).unwrap()], 2048, PACK_WIDTH)?;
465
466 POSEIDON
467 .hash(&[
468 first,
469 second,
470 address_seed,
471 max_epoch_f,
472 iss_base64_f,
473 index_mod_4_f,
474 header_f,
475 modulus_f,
476 ])
477 .map_err(SignatureError::from_source)
478}
479
480#[allow(unused)]
482fn gen_address_seed(
483 salt: &str,
484 name: &str, value: &str, aud: &str, ) -> Result<String, SignatureError> {
488 let salt_hash = POSEIDON
489 .hash(&[bn254_to_fr(
490 &Bn254FieldElement::from_str(salt).map_err(SignatureError::from_source)?,
491 )])
492 .map_err(SignatureError::from_source)?;
493 gen_address_seed_with_salt_hash(salt_hash, name, value, aud)
494}
495
496const MAX_KEY_CLAIM_NAME_LENGTH: u8 = 32;
497const MAX_KEY_CLAIM_VALUE_LENGTH: u8 = 115;
498const MAX_AUD_VALUE_LENGTH: u8 = 145;
499
500pub(crate) fn gen_address_seed_with_salt_hash(
502 salt_hash: Fr,
503 name: &str, value: &str, aud: &str, ) -> Result<String, SignatureError> {
507 Ok(POSEIDON
508 .hash(&[
509 hash_ascii_str_to_field(name, MAX_KEY_CLAIM_NAME_LENGTH)?,
510 hash_ascii_str_to_field(value, MAX_KEY_CLAIM_VALUE_LENGTH)?,
511 hash_ascii_str_to_field(aud, MAX_AUD_VALUE_LENGTH)?,
512 salt_hash,
513 ])
514 .map_err(SignatureError::from_source)?
515 .to_string())
516}
517
518#[cfg(test)]
519mod test {
520 use super::*;
521 use sui_sdk_types::Ed25519Signature;
522
523 #[cfg(test)]
524 #[cfg(target_arch = "wasm32")]
525 use wasm_bindgen_test::wasm_bindgen_test as test;
526
527 #[test]
528 fn test_verify_zklogin_google() {
529 let user_salt = "206703048842351542647799591018316385612";
530
531 let pubkey = Ed25519PublicKey::new([
532 185, 198, 238, 22, 48, 239, 62, 113, 17, 68, 166, 72, 219, 6, 187, 178, 40, 79, 114,
533 116, 207, 190, 229, 63, 252, 238, 80, 60, 193, 164, 146, 0,
534 ]);
535 let signature = SimpleSignature::Ed25519 {
536 signature: Ed25519Signature::new([0; 64]),
537 public_key: pubkey,
538 };
539
540 let address_seed = gen_address_seed(
542 user_salt,
543 "sub",
544 "106294049240999307923",
545 "25769832374-famecqrhe2gkebt5fvqms2263046lj96.apps.googleusercontent.com",
546 )
547 .unwrap();
548
549 let inputs = serde_json::json!({
550 "proof_points": {
551 "a": [
552 "8247215875293406890829839156897863742504615191361518281091302475904551111016",
553 "6872980335748205979379321982220498484242209225765686471076081944034292159666",
554 "1"
555 ],
556 "b": [
557 [
558 "21419680064642047510915171723230639588631899775315750803416713283740137406807",
559 "21566716915562037737681888858382287035712341650647439119820808127161946325890"
560 ],
561 [
562 "17867714710686394159919998503724240212517838710399045289784307078087926404555",
563 "21812769875502013113255155836896615164559280911997219958031852239645061854221"
564 ],
565 ["1","0"]
566 ],
567 "c": [
568 "7530826803702928198368421787278524256623871560746240215547076095911132653214",
569 "16244547936249959771862454850485726883972969173921727256151991751860694123976",
570 "1"
571 ]
572 },
573 "iss_base64_details": {
574 "value": "yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC",
575 "index_mod_4": 1
576 },
577 "header_base64": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZmNzI1NDEwMWY1NmU0MWNmMzVjOTkyNmRlODRhMmQ1NTJiNGM2ZjEiLCJ0eXAiOiJKV1QifQ",
578 "address_seed": address_seed
579 });
580
581 let zklogin_inputs: ZkLoginInputs = serde_json::from_value(inputs).unwrap();
582
583 let jwk = Jwk {
584 kty: "RSA".to_string(),
585 e: "AQAB".to_string(),
586 n: "oUriU8GqbRw-avcMn95DGW1cpZR1IoM6L7krfrWvLSSCcSX6Ig117o25Yk7QWBiJpaPV0FbP7Y5-DmThZ3SaF0AXW-3BsKPEXfFfeKVc6vBqk3t5mKlNEowjdvNTSzoOXO5UIHwsXaxiJlbMRalaFEUm-2CKgmXl1ss_yGh1OHkfnBiGsfQUndKoHiZuDzBMGw8Sf67am_Ok-4FShK0NuR3-q33aB_3Z7obC71dejSLWFOEcKUVCaw6DGVuLog3x506h1QQ1r0FXKOQxnmqrRgpoHqGSouuG35oZve1vgCU4vLZ6EAgBAbC0KL35I7_0wUDSMpiAvf7iZxzJVbspkQ".to_string(),
587 alg: "RS256".to_string(),
588 };
589
590 VerifyingKey::new_mainnet()
591 .verify_zklogin(&jwk, &zklogin_inputs, &signature, 10)
592 .unwrap();
593 }
594
595 #[test]
596 fn test_public_key_to_frs() {
597 let pubkey = Ed25519PublicKey::new([
598 185, 198, 238, 22, 48, 239, 62, 113, 17, 68, 166, 72, 219, 6, 187, 178, 40, 79, 114,
599 116, 207, 190, 229, 63, 252, 238, 80, 60, 193, 164, 146, 0,
600 ]);
601 let signature = SimpleSignature::Ed25519 {
602 signature: Ed25519Signature::new([0; 64]),
603 public_key: pubkey,
604 };
605 let (actual_0, actual_1) = public_key_to_frs(&signature);
606 let expect_0 = Fr::from(ark_ff::BigInt([
607 1244302228903607218,
608 13386648721483054705,
609 0,
610 0,
611 ]));
612
613 let expect_1 = Fr::from(ark_ff::BigInt([
614 18225592963892023808,
615 2904666130704426303,
616 0,
617 0,
618 ]));
619 assert_eq!(actual_0, expect_0);
620 assert_eq!(actual_1, expect_1);
621 }
622
623 #[test]
624 fn test_hash_ascii_str_to_field() {
625 let actual = hash_ascii_str_to_field("sub", 32).unwrap();
626 let expect = Fr::from(ark_ff::BigInt([
627 9420274050661827129,
628 9736100402995345242,
629 10431892319505233812,
630 1450152190758097105,
631 ]));
632 assert_eq!(actual, expect);
633
634 let actual = hash_ascii_str_to_field("106294049240999307923", 115).unwrap();
635 let expect = Fr::from(ark_ff::BigInt([
636 1616959301818912987,
637 17318965991705091209,
638 15303466056770245354,
639 1596136658728187659,
640 ]));
641 assert_eq!(actual, expect);
642
643 let actual = hash_ascii_str_to_field(
644 "25769832374-famecqrhe2gkebt5fvqms2263046lj96.apps.googleusercontent.com",
645 145,
646 )
647 .unwrap();
648 let expect = Fr::from(ark_ff::BigInt([
649 5030944271044826582,
650 8577618269522081956,
651 6962871209781429610,
652 2149811477348923117,
653 ]));
654 assert_eq!(actual, expect);
655
656 let actual =
657 hash_ascii_str_to_field("yJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLC", 224)
658 .unwrap();
659 let expect = Fr::from(ark_ff::BigInt([
660 6021918591354572765,
661 14069258108381575504,
662 1736509627917450843,
663 2767185135515367512,
664 ]));
665 assert_eq!(actual, expect);
666
667 let actual = hash_ascii_str_to_field(
668 "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZmNzI1NDEwMWY1NmU0MWNmMzVjOTkyNmRlODRhMmQ1NTJiNGM2ZjEiLCJ0eXAiOiJKV1QifQ",
669 248,
670 ).unwrap();
671 let expect = Fr::from(ark_ff::BigInt([
672 4239129243150064016,
673 15469804315138207306,
674 17534492051703966556,
675 2100329545252322607,
676 ]));
677 assert_eq!(actual, expect);
678 }
679}