* feat: selfrica circuit and tests * chore: remove unused code * feat: test for ofac,date and olderthan * fix: public signal constant * feat: add contract tests * feat: helper function to gen TEE input * feat: gen circuit inputs with signature * feat: seralized base64 * fix: DateIsLessFullYear componenet * feat: register circuit for selfrica * feat: selfrica disclose circuit and test * fix: common module error * feat: add more test and fix constant * fix: commitment calculation * feat: selfrica contracts * test: selfrica register using unified circuit * feat: register persona and selfrica circuit * feat: selfrica circuit and tests * chore: remove unused code * feat: test for ofac,date and olderthan * fix: public signal constant * feat: add contract tests * feat: helper function to gen TEE input * feat: gen circuit inputs with signature * feat: seralized base64 * fix: DateIsLessFullYear componenet * feat: register circuit for selfrica * feat: selfrica disclose circuit and test * fix: common module error * feat: add more test and fix constant * fix: commitment calculation * feat: selfrica contracts * test: selfrica register using unified circuit * feat: register persona and selfrica circuit * refactor: contract size reduction for IdentityVerificationHubImplV2 export function logic to external libs, reduce compiler runs to 200, update deploy scripts to link new libs * feat: disclose circuit for persona * feat: update persona ofac trees * feat; register circuit for selfper * feat: disclose test for selfper * chore: refactor * chore : remove unused circuits * chore: rename selfper to kyc * chore: update comments * feat: constrain s to be 251 bit * feat: add range check on majority ASCII and comments * feat: range check on neg_r_inv * chore: remove is pk zero constrain * merge dev * feat: add registerPubkey function to Selfrica with GCPJWT Verification * test: add testing for GCPJWT verification on Selfrica * fix: script that calls register_selfrica circuits (ptau:14 -> ptau:15) * fix: get remaining Selfrica tests working with proper import paths * refactor: store pubkeys as string also add some comment code for registerPubkey function * refactor: remove registerPubkeyCommitment function some tests now skipped as awaiting changes to how pubkeys are stored (string instead of uint256) * feat: use hex decoding for the pubkey commitment * test: adjust tests for pubkey being string again * fix: remove old references to registerPubkey * docs: add full natspec for IdentityRegistrySelfricaImplV1 * docs: update files in rest of the repo for Selfrica attestation type * test: fix broken tests * fix: builds and move to kyc from selfrica * fix: constrain r_inv, Rx, s, T * feat: eddsa * feat: add onlyTEE check to registerPubkeyCommitment onlyOwner is able to change onlyTEE * refactor: update gcpRootCAPubkeyHash to be changeable by owner * feat: add events for update functions * style: move functions to be near other similar functions * fix: kyc happy flow * fix: all contract tests passing | fix: timestamp conversion with Date(), migrate to V2 for endToEnd test, scope formatting, fix register aadhaar issue by using block.timestamp instead of Date.now(), fix changed getter function name, enable MockGCPJWTVerifier with updated file paths, add missing LeanIMT import, fix user identifier format * audit: bind key offset-value offset and ensure image_digest only occurs once in the payload * fix: constrain bracket * chore: update comment * audit: hardcode attestation id * audit: make sure R and pubkey are on the curve * audit: ensure pubkey is within bounds * fix: all contract tests passing * feat: change max length to 99 from 74 * audit: don't check sha256 padding * audit: check the last window as well * audit: single occurance for eat_nonce and image_digest * audit: check if the certs are expired * audit: add the timestamp check to the contract * audit: make sure the person is less than 255 years of age * audit fixes * chore: yarn.lock * fix: build fixes * fix: aadhaar timestamp * lint * fix: types * format --------- Co-authored-by: vishal <vishalkoolkarni0045@gmail.com> Co-authored-by: Evi Nova <tranquil_flow@protonmail.com>
@selfxyz/core
SDK for verifying passport proofs from Self.
Installation
You can install with this command:
npm install @selfxyz/core
# or
yarn add @selfxyz/core
Initialization
Initialize the verifier with your scope, endpoint, and configuration:
import { SelfBackendVerifier } from '@selfxyz/core';
const selfBackendVerifier = new SelfBackendVerifier(
scope, // Your application's unique scope
endpoint, // Your verification endpoint URL
mockPassport, // Whether to use testnet (true) or mainnet (false)
allowedIds, // Map of allowed attestation IDs
configStorage, // Configuration storage implementation
userIdentifierType // Type of user identifier ('hex' or 'uuid')
);
Configuration Storage
The SDK requires a configuration storage implementation. You can use the provided implementations:
import { DefaultConfigStore, InMemoryConfigStore } from '@selfxyz/core';
// For simple use cases with a single config
const configStore = new DefaultConfigStore({
minimumAge: 18,
excludedCountries: ['IRN', 'PRK', 'RUS', 'SYR'],
ofac: true,
});
// For dynamic config management
const configStore = new InMemoryConfigStore(async (userIdentifier, userDefinedData) => {
// Return config ID based on user and data
return 'config-id-' + userIdentifier;
});
Verification
Verify a proof with the required parameters:
const result = await selfBackendVerifier.verify(
attestationId, // The attestation ID (e.g., 1 for passport)
proof, // The cryptographic proof
publicSignals, // Array of public signals from the proof
userContextData // Hex string containing user context data
);
Verification Result
The verify method returns a detailed verification result:
export interface VerificationResult {
attestationId: AttestationId;
isValidDetails: {
isValid: boolean; // Cryptographic validity of the proof
isMinimumAgeValid: boolean; // Age verification result
isOfacValid: boolean; // OFAC check results
};
forbiddenCountriesList: string[]; // List of forbidden countries from proof
discloseOutput: GenericDiscloseOutput; // Revealed data from the passport
userData: {
userIdentifier: string; // User identifier
userDefinedData: string; // User-defined data
};
}
The GenericDiscloseOutput contains the revealed passport data:
export type GenericDiscloseOutput = {
nullifier: string; // Cryptographic nullifier to prevent reuse
forbiddenCountriesListPacked: string[]; // Packed forbidden countries list
issuingState: string; // Passport issuing country
name: string; // User's name
idNumber: string; // Passport number
nationality: string; // User's nationality
dateOfBirth: string; // Date of birth
gender: string; // Gender
expiryDate: string; // Passport expiry date
minimumAge: string; // Age verification result
ofac: boolean[]; // OFAC check results [passport_no, name_dob, name_yob]
};
API Implementation Example
Here's an example of implementing an API endpoint that uses the SDK:
import { NextApiRequest, NextApiResponse } from 'next';
import { SelfBackendVerifier, DefaultConfigStore } from '@selfxyz/core';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
try {
const { attestationId, proof, publicSignals, userContextData } = req.body;
if (!attestationId || !proof || !publicSignals || !userContextData) {
return res.status(400).json({
message: 'attestationId, proof, publicSignals, and userContextData are required',
});
}
// Create configuration storage
const configStore = new DefaultConfigStore({
minimumAge: 18,
excludedCountries: ['IRN', 'PRK', 'RUS', 'SYR'],
ofac: true,
});
// Initialize the verifier
const selfBackendVerifier = new SelfBackendVerifier(
'my-application-scope',
'https://my-api.com/api/verify',
false, // Use mainnet
new Map([[1, true]]), // Allow passport attestation
configStore,
'uuid' // User identifier type
);
// Verify the proof
const result = await selfBackendVerifier.verify(
attestationId,
proof,
publicSignals,
userContextData
);
if (result.isValidDetails.isValid) {
// Return successful verification response
return res.status(200).json({
status: 'success',
result: true,
userData: result.userData,
discloseOutput: result.discloseOutput,
});
} else {
// Return failed verification response
return res.status(400).json({
status: 'error',
result: false,
message: 'Verification failed',
details: result.isValidDetails,
});
}
} catch (error) {
console.error('Error verifying proof:', error);
return res.status(500).json({
status: 'error',
result: false,
message: error instanceof Error ? error.message : 'Unknown error',
});
}
} else {
return res.status(405).json({ message: 'Method not allowed' });
}
}
Working with Country Codes
The SDK provides country code utilities for working with ISO 3-letter country codes:
import { countries, countryCodes } from '@selfxyz/core';
// Examples of usage
const iranCode = countries.IRAN; // "IRN"
const northKoreaCode = countries.NORTH_KOREA; // "PRK"
// Get country name from code
const iranName = countryCodes.IRN; // "Iran (Islamic Republic of)"
// Use in configuration
const configStore = new DefaultConfigStore({
excludedCountries: [countries.IRAN, countries.NORTH_KOREA, countries.SYRIA],
ofac: true,
});
Integration with SelfQRcode
This backend SDK is designed to work with the @selfxyz/qrcode package. When configuring your QR code, set the verification endpoint to point to your API that uses this SDK:
import { SelfAppBuilder } from '@selfxyz/qrcode';
const selfApp = new SelfAppBuilder({
appName: 'My Application',
scope: 'my-application-scope',
endpoint: 'https://my-api.com/api/verify', // Your API using SelfBackendVerifier
logoBase64: myLogoBase64,
userId,
disclosures: {
name: true,
nationality: true,
date_of_birth: true,
passport_number: true,
minimumAge: 20,
excludedCountries: ['IRN', 'PRK'],
ofac: true,
},
}).build();
Available Types and Exports
The SDK exports the following types and utilities:
import {
SelfBackendVerifier,
DefaultConfigStore,
InMemoryConfigStore,
countries,
countryCodes,
AttestationId,
VerificationResult,
VerificationConfig,
IConfigStorage,
} from '@selfxyz/core';
Types
AttestationId: Type for attestation identifiers (e.g., 1 for passport)VerificationResult: Result structure returned by the verifierVerificationConfig: Configuration for verification rulesIConfigStorage: Interface for configuration storage implementations
Utilities
countries: Object mapping country names to 3-letter ISO codescountryCodes: Object mapping 3-letter ISO codes to full country namesDefaultConfigStore: Simple configuration storage with a single configInMemoryConfigStore: In-memory configuration storage for dynamic configs
Example
For a more advanced implementation example, see the playground.