full ios mint flow

- corrected passport reading flow to include eContent (signedAttributes)
- formatting proof from swift bindings to be verified in solidity
This commit is contained in:
0xturboblitz
2024-01-17 14:07:18 +01:00
parent 0889b2cc97
commit 7d02a479fe
8 changed files with 161 additions and 60 deletions

View File

@@ -57,7 +57,9 @@ import {
formatAndConcatenateDataHashes,
formatMrz,
splitToWords,
hexStringToSignedIntArray
hexStringToSignedIntArray,
formatProofIOS,
formatInputsIOS
} from '../common/src/utils/utils';
import { samplePassportData } from '../common/src/utils/passportDataStatic';
@@ -136,6 +138,7 @@ function App(): JSX.Element {
}, []);
useEffect(() => {
NativeModules.Prover.runInitAction()
if (SKIP_SCAN && passportData === null) {
setPassportData(samplePassportData as PassportData);
setStep('scanCompleted');
@@ -145,7 +148,8 @@ function App(): JSX.Element {
async function handleResponseIOS(response: any) {
const parsed = JSON.parse(response);
const eContentBase64 = parsed.eContentBase64;
const eContentBase64 = parsed.eContentBase64; // this is what we call concatenatedDataHashes in our world
const signedAttributes = parsed.signedAttributes; // this is what we call eContent in our world
const signatureAlgorithm = parsed.signatureAlgorithm;
const mrz = parsed.passportMRZ;
const dataGroupHashes = parsed.dataGroupHashes;
@@ -160,9 +164,12 @@ function App(): JSX.Element {
console.log('publicKey', publicKey)
const modulus = (publicKey as any).n.toString(10);
const eContentArray = Array.from(Buffer.from(eContentBase64, 'base64'));
const eContentArray = Array.from(Buffer.from(signedAttributes, 'base64'));
const signedEContentArray = eContentArray.map(byte => byte > 127 ? byte - 256 : byte);
const concatenatedDataHashesArray = Array.from(Buffer.from(eContentBase64, 'base64'));
const concatenatedDataHashesArraySigned = concatenatedDataHashesArray.map(byte => byte > 127 ? byte - 256 : byte);
const dgHashes = JSON.parse(dataGroupHashes);
console.log('dgHashes', dgHashes)
@@ -183,7 +190,7 @@ function App(): JSX.Element {
pubKey: {
modulus: modulus,
},
dataGroupHashes: dataGroupHashesArray as DataHash[],
dataGroupHashes: concatenatedDataHashesArraySigned,
eContent: signedEContentArray,
encryptedDigest: encryptedDigestArray,
};
@@ -307,10 +314,14 @@ function App(): JSX.Element {
// 2. Format all the data as inputs for the circuit
const formattedMrz = formatMrz(passportData.mrz);
const mrzHash = hash(formatMrz(passportData.mrz));
const concatenatedDataHashes = formatAndConcatenateDataHashes(
mrzHash,
passportData.dataGroupHashes as DataHash[],
);
const concatenatedDataHashes =
Array.isArray(passportData.dataGroupHashes[0])
? formatAndConcatenateDataHashes(
mrzHash,
passportData.dataGroupHashes as DataHash[],
)
: passportData.dataGroupHashes
const reveal_bitmap = Array.from({ length: 88 }, (_) => '0');
@@ -324,7 +335,7 @@ function App(): JSX.Element {
}
}
if (passportData.signatureAlgorithm !== "SHA256withRSA") {
if (!["SHA256withRSA", "sha256WithRSAEncryption"].includes(passportData.signatureAlgorithm)) {
console.log(`${passportData.signatureAlgorithm} not supported for proof right now.`);
setError(`${passportData.signatureAlgorithm} not supported for proof right now.`);
return;
@@ -333,7 +344,7 @@ function App(): JSX.Element {
const inputs = {
mrz: Array.from(formattedMrz).map(byte => String(byte)),
reveal_bitmap: reveal_bitmap.map(byte => String(byte)),
dataHashes: Array.from(concatenatedDataHashes.map(toUnsignedByte)).map(byte => String(byte)),
dataHashes: Array.from((concatenatedDataHashes as number[]).map(toUnsignedByte)).map(byte => String(byte)),
eContentBytes: Array.from(passportData.eContent.map(toUnsignedByte)).map(byte => String(byte)),
signature: splitToWords(
BigInt(bytesToBigDecimal(passportData.encryptedDigest)),
@@ -348,11 +359,21 @@ function App(): JSX.Element {
address,
}
// 3. Generate a proof of passport
const start = Date.now();
NativeModules.RNPassportReader.provePassport(inputs, (err: any, res: any) => {
const end = Date.now();
console.log('inputs', inputs)
const start = Date.now();
if (Platform.OS === 'android') {
await proveAndroid(inputs);
} else {
await proveIOS(inputs);
}
const end = Date.now();
console.log('Total proof time from frontend:', end - start);
setTotalTime(end - start);
};
async function proveAndroid(inputs: any) {
NativeModules.RNPassportReader.provePassport(inputs, (err: any, res: any) => {
if (err) {
console.error(err);
setError(
@@ -372,7 +393,6 @@ function App(): JSX.Element {
console.log('deserializedInputs', deserializedInputs);
setProofTime(parsedResponse.duration);
setTotalTime(end - start);
setProof({
proof: JSON.stringify(deserializedProof),
@@ -381,7 +401,41 @@ function App(): JSX.Element {
setGeneratingProof(false)
setStep('proofGenerated');
});
};
}
async function proveIOS(inputs: any) {
try {
console.log('running mopro init action')
await NativeModules.Prover.runInitAction()
console.log('running mopro prove action')
const response = await NativeModules.Prover.runProveAction({
...inputs,
address: [BigInt(address).toString()]
})
console.log('proof response:', response)
const parsedResponse = JSON.parse(response)
console.log('running mopro verify action')
const res = await NativeModules.Prover.runVerifyAction()
console.log('verify response:', res)
setProof({
proof: JSON.stringify(formatProofIOS(parsedResponse.proof)),
inputs: JSON.stringify(formatInputsIOS(parsedResponse.inputs)),
});
// setProofTime(response.duration);
setGeneratingProof(false)
setStep('proofGenerated');
} catch (err: any) {
console.log('err', err);
setError(
"err: " + err.toString(),
);
}
}
const handleMint = async () => {
setMinting(true)
@@ -651,37 +705,6 @@ function App(): JSX.Element {
</Button>
{testResult && <Text>{testResult}</Text>}
<Button
onPress={async () => {
const res = await NativeModules.Prover.runInitAction()
console.log('res', res)
}}
marginTop={10}
>
<ButtonText>runInitAction</ButtonText>
</Button>
<Button
onPress={async () => {
// careful, address here is in decimal
const inputsIOS = {"mrz":["97","91","95","31","88","80","60","70","82","65","68","85","80","79","78","84","60","60","65","76","80","72","79","78","83","69","60","72","85","71","85","69","83","60","65","76","66","69","82","84","60","60","60","60","60","60","60","60","60","50","52","72","66","56","49","56","51","50","52","70","82","65","48","52","48","50","49","49","49","77","51","49","49","49","49","49","53","60","60","60","60","60","60","60","60","60","60","60","60","60","60","48","50"],"reveal_bitmap":["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],"dataHashes":["48","130","1","37","2","1","0","48","11","6","9","96","134","72","1","101","3","4","2","1","48","130","1","17","48","37","2","1","1","4","32","176","223","31","133","108","84","158","102","70","11","165","175","196","12","201","130","25","131","46","125","156","194","28","23","55","133","157","164","135","136","220","78","48","37","2","1","2","4","32","190","82","180","235","222","33","79","50","152","136","142","35","116","224","6","242","156","141","128","248","10","61","98","86","248","45","207","210","90","232","175","38","48","37","2","1","3","4","32","0","194","104","108","237","246","97","230","116","198","69","110","26","87","17","89","110","199","108","250","36","21","39","87","110","102","250","213","174","131","171","174","48","37","2","1","11","4","32","136","155","87","144","111","15","152","127","85","25","154","81","20","58","51","75","193","116","234","0","60","30","29","30","183","141","72","247","255","203","100","124","48","37","2","1","12","4","32","41","234","106","78","31","11","114","137","237","17","92","71","134","47","62","78","189","233","201","214","53","4","47","189","201","133","6","121","34","131","64","142","48","37","2","1","13","4","32","91","222","210","193","62","222","104","82","36","41","138","253","70","15","148","208","156","45","105","171","241","195","185","43","217","162","146","201","222","89","238","38","48","37","2","1","14","4","32","76","123","216","13","51","227","72","245","59","193","238","166","103","49","23","164","171","188","194","197","156","187","249","28","198","95","69","15","182","56","54","38"],"eContentBytes":["49","102","48","21","6","9","42","134","72","134","247","13","1","9","3","49","8","6","6","103","129","8","1","1","1","48","28","6","9","42","134","72","134","247","13","1","9","5","49","15","23","13","49","57","49","50","49","54","49","55","50","50","51","56","90","48","47","6","9","42","134","72","134","247","13","1","9","4","49","34","4","32","32","85","108","174","127","112","178","182","8","43","134","123","192","211","131","66","184","240","212","181","240","180","106","195","24","117","54","129","19","10","250","53"],"signature":["7924608050410952186","18020331358710788578","8570093713362871693","158124167841380627","11368970785933558334","13741644704804016484","3255497432248429697","18325134696633464276","11159517223698754974","14221210644107127310","18395843719389189885","14516795783073238806","2008163829408627473","10489977208787195755","11349558951945231290","10261182129521943851","898517390497363184","7991226362010359134","16695870541274258886","3471091665352332245","9966265751297511656","15030994431171601215","10723494832064770597","14939163534927288303","13596611050508022203","12058746125656824488","7806259275107295093","9171418878976478189","16438005721800053020","315207309308375554","3950355816720285857","5415176625244763446"],"pubkey":["10501872816920780427","9734403015003984321","14411195268255541454","5140370262757446136","442944543003039303","2084906169692591819","13619051978156646232","11308439966240653768","11784026229075891869","3619707049269329199","14678094225574041482","13372281921787791985","5760458619375959191","1351001273751492154","9127780359628047919","5377643070972775368","14145972494784958946","295160036043261024","12244573192558293296","13273111070076476096","15787778596745267629","12026125372525341435","17186889501189543072","1678833675164196298","11525741336698300342","9004411014119053043","3653149686233893817","3525782291631180893","13397424121878903415","12208454420188007950","5024240771370648155","15842149209258762075"],"address":["897585614395172552642670145532424661022951192962"]}
const res = await NativeModules.Prover.runProveAction(inputsIOS)
console.log('res', res)
}}
marginTop={10}
>
<ButtonText>runProveAction</ButtonText>
</Button>
<Button
onPress={async () => {
const res = await NativeModules.Prover.runVerifyAction()
console.log('res', res)
}}
marginTop={10}
>
<ButtonText>runVerifyAction</ButtonText>
</Button>
</View>
</ScrollView>
</SafeAreaView>

View File

@@ -194,10 +194,16 @@ class PassportReader: NSObject{
do {
let sod = passport.getDataGroup(DataGroupId.SOD) as! SOD
ret["eContentBase64"] = try sod.getEncapsulatedContent().base64EncodedString()
// ret["concatenatedDataHashes"] = try sod.getEncapsulatedContent().base64EncodedString() // this is what we call concatenatedDataHashes, not the true eContent
ret["eContentBase64"] = try sod.getEncapsulatedContent().base64EncodedString() // this is what we call concatenatedDataHashes, not the true eContent
ret["signatureAlgorithm"] = try sod.getSignatureAlgorithm()
let messageDigestFromSignedAttributes = try sod.getMessageDigestFromSignedAttributes()
let signedAttributes = try sod.getSignedAttributes()
print("messageDigestFromSignedAttributes", messageDigestFromSignedAttributes)
ret["signedAttributes"] = signedAttributes.base64EncodedString()
// if let pubKey = convertOpaquePointerToSecKey(opaquePointer: sod.pubKey),
// let serializedPublicKey = serializePublicKey(pubKey) {
// ret["publicKeyBase64"] = serializedPublicKey

View File

@@ -34,7 +34,7 @@ target 'ProofOfPassport' do
flags = get_default_flags()
use_frameworks!
pod 'NFCPassportReader', git: 'https://github.com/0xturboblitz/NFCPassportReader.git', commit: '07b3662702834676b547718998fa377fe5f00776'
pod 'NFCPassportReader', git: 'https://github.com/0xturboblitz/NFCPassportReader.git', commit: 'd36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9'
pod 'MoproKit', :path => './MoproKit'
use_react_native!(

View File

@@ -403,7 +403,7 @@ DEPENDENCIES:
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- MoproKit (from `./MoproKit`)
- NFCPassportReader (from `https://github.com/0xturboblitz/NFCPassportReader.git`, commit `07b3662702834676b547718998fa377fe5f00776`)
- NFCPassportReader (from `https://github.com/0xturboblitz/NFCPassportReader.git`, commit `d36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9`)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
@@ -460,7 +460,7 @@ EXTERNAL SOURCES:
MoproKit:
:path: "./MoproKit"
NFCPassportReader:
:commit: 07b3662702834676b547718998fa377fe5f00776
:commit: d36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9
:git: https://github.com/0xturboblitz/NFCPassportReader.git
RCT-Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
@@ -533,7 +533,7 @@ EXTERNAL SOURCES:
CHECKOUT OPTIONS:
NFCPassportReader:
:commit: 07b3662702834676b547718998fa377fe5f00776
:commit: d36952eeaa2025ff1a9c9abbc244bd5ff53eb0f9
:git: https://github.com/0xturboblitz/NFCPassportReader.git
SPEC CHECKSUMS:
@@ -582,6 +582,6 @@ SPEC CHECKSUMS:
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 8796b55dba14d7004f980b54bcc9833ee45b28ce
PODFILE CHECKSUM: 52f9302a4d936d9bacb79ef5417142b1e96c5f0e
PODFILE CHECKSUM: d401e6efe0c933985349c8c115c7edca8fef3182
COCOAPODS: 1.14.3

View File

@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
00E356F31AD99517003FC87E /* ProofOfPassportTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ProofOfPassportTests.m */; };
057DFC5F2B56DC0D003D24A3 /* libmopro_ffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 057DFC5E2B56DC0D003D24A3 /* libmopro_ffi.a */; };
05BD9DCC2B548AA900823023 /* MoproKit in Resources */ = {isa = PBXBuildFile; fileRef = 05BD9DCB2B548AA900823023 /* MoproKit */; };
05BD9DCE2B554FA300823023 /* libmopro_ffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 05BD9DCD2B554FA300823023 /* libmopro_ffi.a */; };
05EDEDC62B52D25D00AA51AD /* Prover.m in Sources */ = {isa = PBXBuildFile; fileRef = 05EDEDC42B52D25D00AA51AD /* Prover.m */; };
@@ -37,6 +38,7 @@
00E356EE1AD99517003FC87E /* ProofOfPassportTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProofOfPassportTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* ProofOfPassportTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ProofOfPassportTests.m; sourceTree = "<group>"; };
057DFC5E2B56DC0D003D24A3 /* libmopro_ffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmopro_ffi.a; path = MoproKit/Libs/libmopro_ffi.a; sourceTree = "<group>"; };
05A0773D2B5333CE0037E489 /* MoproKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MoproKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
05BD9DCB2B548AA900823023 /* MoproKit */ = {isa = PBXFileReference; lastKnownFileType = folder; path = MoproKit; sourceTree = "<group>"; };
05BD9DCD2B554FA300823023 /* libmopro_ffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmopro_ffi.a; path = MoproKit/Libs/libmopro_ffi.a; sourceTree = "<group>"; };
@@ -78,6 +80,7 @@
files = (
0651723A94C70A2B31E3E4F8 /* Pods_ProofOfPassport.framework in Frameworks */,
05BD9DCE2B554FA300823023 /* libmopro_ffi.a in Frameworks */,
057DFC5F2B56DC0D003D24A3 /* libmopro_ffi.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -108,6 +111,7 @@
05EDEDC52B52D25D00AA51AD /* Prover.swift */,
905B700A2A72A5E900AFA232 /* masterList.pem */,
905B70082A729CD400AFA232 /* ProofOfPassport.entitlements */,
057DFC5E2B56DC0D003D24A3 /* libmopro_ffi.a */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
05BD9DCB2B548AA900823023 /* MoproKit */,
13B07FB01A68108700A75B9A /* AppDelegate.mm */,

View File

@@ -36,9 +36,11 @@ class Prover: NSObject {
// Log the time taken for initialization
print("Initializing arkzkey took \(timeTaken) seconds.")
resolve("Done")
} catch {
// Log any errors that occurred during initialization
print("An error occurred during initialization: \(error)")
reject("PROVER", "An error occurred during initialization", error)
}
}
}
@@ -47,8 +49,9 @@ class Prover: NSObject {
func runProveAction(_ inputs: [String: [String]], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
// Logic for prove (generate_proof2)
do {
// format of inputs, if you want to manage it manually:
// WORKING, SAMPLE DATA:
// let mrz: [String] = ["97","91","95","31","88","80","60","70","82","65","68","85","80","79","78","84","60","60","65","76","80","72","79","78","83","69","60","72","85","71","85","69","83","60","65","76","66","69","82","84","60","60","60","60","60","60","60","60","60","50","52","72","66","56","49","56","51","50","52","70","82","65","48","52","48","50","49","49","49","77","51","49","49","49","49","49","53","60","60","60","60","60","60","60","60","60","60","60","60","60","60","48","50"]
// let reveal_bitmap: [String] = ["0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"]
// let dataHashes: [String] = ["48","130","1","37","2","1","0","48","11","6","9","96","134","72","1","101","3","4","2","1","48","130","1","17","48","37","2","1","1","4","32","176","223","31","133","108","84","158","102","70","11","165","175","196","12","201","130","25","131","46","125","156","194","28","23","55","133","157","164","135","136","220","78","48","37","2","1","2","4","32","190","82","180","235","222","33","79","50","152","136","142","35","116","224","6","242","156","141","128","248","10","61","98","86","248","45","207","210","90","232","175","38","48","37","2","1","3","4","32","0","194","104","108","237","246","97","230","116","198","69","110","26","87","17","89","110","199","108","250","36","21","39","87","110","102","250","213","174","131","171","174","48","37","2","1","11","4","32","136","155","87","144","111","15","152","127","85","25","154","81","20","58","51","75","193","116","234","0","60","30","29","30","183","141","72","247","255","203","100","124","48","37","2","1","12","4","32","41","234","106","78","31","11","114","137","237","17","92","71","134","47","62","78","189","233","201","214","53","4","47","189","201","133","6","121","34","131","64","142","48","37","2","1","13","4","32","91","222","210","193","62","222","104","82","36","41","138","253","70","15","148","208","156","45","105","171","241","195","185","43","217","162","146","201","222","89","238","38","48","37","2","1","14","4","32","76","123","216","13","51","227","72","245","59","193","238","166","103","49","23","164","171","188","194","197","156","187","249","28","198","95","69","15","182","56","54","38"]
@@ -77,17 +80,37 @@ class Prover: NSObject {
// Record end time and compute duration
let end = CFAbsoluteTimeGetCurrent()
let timeTaken = end - start
print("Proof generation took \(timeTaken) seconds.")
// Store the generated proof and public inputs for later verification
print("generateProofResult", generateProofResult)
generatedProof = generateProofResult.proof
publicInputs = generateProofResult.inputs
print("Proof generation took \(timeTaken) seconds.")
resolve(generateProofResult)
// Convert Data to array of bytes
let proofBytes = [UInt8](generateProofResult.proof)
let inputsBytes = [UInt8](generateProofResult.inputs)
print("proofBytes", proofBytes)
print("inputsBytes", inputsBytes)
// Create a dictionary with byte arrays
let resultDict: [String: [UInt8]] = [
"proof": proofBytes,
"inputs": inputsBytes
]
// Serialize dictionary to JSON
let jsonData = try JSONSerialization.data(withJSONObject: resultDict, options: [])
let jsonString = String(data: jsonData, encoding: .utf8)!
resolve(jsonString)
} catch let error as MoproError {
print("MoproError: \(error)")
reject("PROVER", "An error occurred during proof generation", error)
} catch {
print("Unexpected error: \(error)")
reject("PROVER", "An error occurred during proof generation", error)
}
}
@@ -105,10 +128,13 @@ class Prover: NSObject {
assert(isValid, "Proof verification should succeed")
print("Proof verification succeeded.")
resolve(isValid)
} catch let error as MoproError {
print("MoproError: \(error)")
print("MoproError: \(error)")
reject("PROVER", "An error occurred during proof verification", error)
} catch {
print("Unexpected error: \(error)")
reject("PROVER", "An error occurred during proof verification", error)
}
}
}