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