generate scope from dns (#495)

* generate scope from dns

* switch between api and staging api according to document type

* add poland passport to mockdatascreen

* yarn nice

* bump sdk version

* bump app version

* Feat/update sdk (#496)

* export castFromScope

* export proof conversion

* publish new package

* update package

* update package

* add hashEndpointWithScope to export member

---------

Co-authored-by: nicoshark <i.am.nicoshark@gmail.com>
This commit is contained in:
turnoffthiscomputer
2025-03-31 14:20:13 -04:00
committed by GitHub
parent effafe9ab0
commit fafc765af7
20 changed files with 3761 additions and 5046 deletions

View File

@@ -6,6 +6,7 @@ export type EndpointType = 'https' | 'celo' | 'staging_celo' | 'staging_https';
import { v4 } from 'uuid';
import { REDIRECT_URL } from "../constants/constants";
import { Country3LetterCode } from "../constants/countries";
import { formatEndpoint } from "./scope";
export interface SelfApp {
appName: string;
logoBase64: string;
@@ -48,6 +49,20 @@ export class SelfAppBuilder {
if (!config.endpoint) {
throw new Error('endpoint is required');
}
// Check if scope and endpoint contain only ASCII characters
if (!/^[\x00-\x7F]*$/.test(config.scope)) {
throw new Error("Scope must contain only ASCII characters (0-127)");
}
if (!/^[\x00-\x7F]*$/.test(config.endpoint)) {
throw new Error("Endpoint must contain only ASCII characters (0-127)");
}
if (config.scope.length > 31) {
throw new Error("Scope must be less than 31 characters");
}
const formattedEndpoint = formatEndpoint(config.endpoint);
if (formattedEndpoint.length > 496) {
throw new Error(`Endpoint must be less than 496 characters, current endpoint: ${formattedEndpoint}, length: ${formattedEndpoint.length}`);
}
if (!config.userId) {
throw new Error('userId is required');
}

View File

@@ -24,7 +24,6 @@ import { hash, packBytesAndPoseidon } from '../hash';
import { formatMrz } from '../passports/format';
import { castFromUUID, stringToAsciiBigIntArray } from './uuid';
import { getCurrentDateYYMMDD } from '../date';
import { castFromScope } from './uuid';
import { formatCountriesList } from './formatInputs';
import { generateMerkleProof, generateSMTProof } from '../trees';
import { parseCertificateSimple } from '../certificate_parsing/parseCertificateSimple';
@@ -234,7 +233,7 @@ export function generateCircuitInputsVCandDisclose(
siblings: formatInput(siblings),
selector_dg1: formatInput(selector_dg1),
selector_older_than: formatInput(selector_older_than),
scope: formatInput(castFromScope(scope)),
scope: formatInput(scope),
current_date: formatInput(getCurrentDateYYMMDD()),
majority: formatInput(majority_ascii),
user_identifier: formatInput(castFromUUID(user_identifier)),

63
common/src/utils/scope.ts Normal file
View File

@@ -0,0 +1,63 @@
import { poseidon2 } from "poseidon-lite";
import { flexiblePoseidon } from "./hash";
export function formatEndpoint(endpoint: string): string {
if (!endpoint) return '';
return endpoint
.replace(/^https?:\/\//, '')
.split('/')[0];
}
export function hashEndpointWithScope(endpoint: string, scope: string): string {
const formattedEndpoint = formatEndpoint(endpoint);
const endpointChunks: string[] = [];
let remaining = formattedEndpoint;
while (remaining.length > 0) {
const chunk = remaining.slice(0, 31);
endpointChunks.push(chunk);
remaining = remaining.slice(31);
}
if (endpointChunks.length > 16) {
throw new Error("Endpoint must be less than 496 characters");
}
const chunkedEndpointBigInts = endpointChunks.map(stringToBigInt);
const endpointHash = flexiblePoseidon(chunkedEndpointBigInts);
const scopeBigInt = stringToBigInt(scope);
return poseidon2([endpointHash, scopeBigInt]).toString();
}
export function stringToBigInt(str: string): bigint {
// Validate input contains only ASCII characters
if (!/^[\x00-\x7F]*$/.test(str)) {
throw new Error("Input must contain only ASCII characters (0-127)");
}
let result = 0n;
for (let i = 0; i < str.length; i++) {
result = (result << 8n) | BigInt(str.charCodeAt(i));
}
// Check size limit
const MAX_VALUE = (1n << 248n) - 1n;
if (result > MAX_VALUE) {
console.log(`str: ${str}, str.length: ${str.length}`);
throw new Error("Resulting BigInt exceeds maximum size of 31 bytes");
}
return result;
}
export function bigIntToString(bigInt: bigint): string {
if (bigInt === 0n) return '';
let result = '';
let tempBigInt = bigInt;
while (tempBigInt > 0n) {
const charCode = Number(tempBigInt & 0xFFn);
result = String.fromCharCode(charCode) + result;
tempBigInt = tempBigInt >> 8n;
}
return result;
}