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