Private ID Android SDK supports user registration with identity proofing, and user face login with FIDO Passkey, using Cryptonets homomorphic tokenization (HT) for privacy and security.
Features:
- Biometric face registration and authentication compliant with IEEE 2410-2021 Standard for Biometric Privacy, and exempt from GDPR, CCPA, BIPA, and HIPPA privacy law obligations.
- Face registration and 1:n face login in 200ms constant time
- Biometric age estimation with full privacy, on-device in 20ms
- Unlimited users (unlimited gallery size)
- Fair, accurate and unbiased
- Operates online or offline, using local cache for hyper-scalability
Builds
- Verified Identity
- Identity Assurance
- Authentication Assurance
- Federation Assurance
- Face Login
- Face Unlock
- Biometric Access Control
- Account Recovery
- Face CAPTCHA
- Android Studio
- Minimum API level: 24
- ndkVersion = "26.1.10909125"
-
Download library: Download the
cryptonets-android-sdk.aarfile from the Release section. -
Open project: Launch Android Studio and open your project.
-
Create library directory: Navigate to:
Project→app→right-click→New→Directory, and name the new directorylibs. -
Copy library file: Copy the downloaded
cryptonets-android-sdk.aarfile into thelibsdirectory. -
Update Build Configuration
- Open your app’s
build.gradleorbuild.gradle.kts - Add the following implementation according to your script type:
Groovy
implementation files('libs/cryptonets-android-sdk.aar')Kotlin
implementation(files("$projectDir/libs/cryptonets-android-sdk.aar")) - Open your app’s
-
Sync project
- Click the
Sync Nowbutton on the toolbar to sync your project.
- Click the
Use the PrivateIdentitySDK.getInstantIdentitySession() singleton to get the session object whenever you need it, and use the session object to call any method.
A function that returns the current SDK version.
Returns:
String: value for the current version.
Example:
val session = PrivateIdentitySDK.getInstantIdentitySession()
val version = session.getVersion()A method that creates the session for SDK work. It saves the session pointer inside the SDK and can be used for other methods. Please use it before making any other calls. NB: Don't call any function from the UI thread during the session initialization.
fun initialize(privateIdentityConfig: PrivateIdentityConfig): PrivateIdentitySessionParameters:
privateIdentityConfig: PrivateIdentityConfig: session initialization parameters.
Returns:
PrivateIdentitySessionsession wrapper for calling other functions.
Example:
val config = PrivateIdentityConfig(sessionToken = "", baseUrl = "", debugLevel = DebugLevel.LEVEL_3)
try {
val privateIdentitySession = PrivateIdentitySDK.initialize(config)
} catch (e: Exception) {
e.printStackTrace()
}A method that deinitializes the session created before. You can call this function when you no longer need SDK in your work, so it frees memory and closes the session.
fun deInitializeSession()Example:
PrivateIdentitySDK.deInitializeSession()A function that detects if there is a valid face on the input image.
fun validate(bitmap: Bitmap, baseUserConfig: ValidateConfig): StringParameters:
bitmap: Bitmap: input image for validation. Make sure the bitmap doesn't rotate other than 0 degrees.baseUserConfig: ValidateConfig: user's config for changing settings.
The ValidateConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.
Returns:
String: aJSONrepresenting the face status.
Example:
fun validImage(bitmap: Bitmap) {
viewModelScope.launch(Dispatchers.Default) {
// _uiState.emit("Validating image")
val privateIdentitySession = PrivateIdentitySDK.getInstantIdentitySession()
val result = privateIdentitySession.validate(
bitmap = bitmap, ValidateConfig()
)
// _uiState.emit("Result ${result}")
}
}Perform a new enrollment (register a new user) using the enroll function. The function will collect 5 consecutive, valid faces to be able to enroll. Using configuration, we must pass the same mfToken (Multiframe token) on success. If the mfToken value changes, we will have an invalid enrollment image and start again from the beginning. Note: 5 consecutive faces are needed. When enrollment is successful after 5 consecutive valid faces, enroll returns the enrollment result.
fun enroll(bitmap: Bitmap, enrollConfig: EnrollConfig): StringParameters:
bitmap: Bitmap: input image for enrolment. Make sure the bitmap doesn't rotate other than 0 degrees.enrollConfig: EnrollConfig: user's config for changing settings.
The EnrollConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.mfToken: you will get it after first enrollment.
Returns:
String: aJSONrepresenting the face status.
Example:
val enrollConfig = EnrollConfig(mfToken = "You will get token once you give valid that have face first image/frame ")
val resultJson = privateIdentitySession.enroll(bitmap = bitmap, enrollConfig = enrollConfig)
Note: Please check ExampleEnroll.kt in the main branch.
Perform predict (authenticate a user) after enrolling the user. This method returns a GUID/PUID if the prediction is successful; otherwise, face validation status and anti-spoof status code from the JSON response. You can get code descriptions at the end of the documentation. However, if the user is not enrolled in the system, this call will return a status of -1 and the message "User not enrolled."
fun predict(bitmap: Bitmap, predictConfig: PredictConfig): StringParameters:
bitmap: Bitmap: input image for enrolment.predictConfig: PredictConfig: user's config for changing settings.
The PredictConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.
Returns:
String: aJSONdata that either GUID/PUID or status code, face validating status, anti spoof status.
Example:
fun predictFace() {
viewModelScope.launch(Dispatchers.IO) {
val result = privateIdentitySession.predict(bitmap = bitmap, PredictConfig())
if (result.toPOJO().guid != null) {
Log.d(TAG,"success")
} else {
//check
Log.d(TAG,"fail")
}
}
}fun compareDocumentAndFace(userConfig: CompareFaceAndMugShortConfig, selfieBitmap: Bitmap, cropIdDocument: Bitmap): StringParameters:
cropIdDocument: Bitmap: user's document image.selfieBitmap: Bitmap: user's face image.userConfig: CompareFaceAndMugShortConfig: user's config for changing settings.
The DocumentAndFaceConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.blurThreshold-15.0: the threshold for marking input mugshot face as blurry. Smaller values are less restrictive, and 0.0 means no blurriness check.
Returns:
String: aJSONrepresenting the face status.
Example:
fun compareTwoImage(userImage:Bitmap, cropIdImage:Bitmap){
viewModelScope.launch(Dispatchers.IO) {
privateIdentitySession.compareDocumentAndFace(
userConfig = CompareFaceAndMugShortConfig(), userImage, cropIdImage)
}
}A sample JSON result:
{
"call_status": {
"return_status": 0,
"operation_tag": "compare_mugshot_and_face",
"return_message": "",
"mf_token": "",
"operation_id": 17,
"operation_type_id": 12
},
"face_compare": {
"result": 0,
"a_face_validation_status": 0,
"b_face_validation_status": 0,
"distance_min": 0.964277208,
"distance_mean": 0.964277208,
"distance_max": 0.964277208,
"conf_score": 56.8121185,
"face_thresholds": [],
"document_data": {
"document_conf_level": 0,
"cropped_document_image": {
"info": {
"width": 112,
"height": 112,
"channels": 4,
"depths": 0,
"color": 4
},
"data": ""
},
"document_validation_status": 0,
"status_message": "",
"mrz_text": []
},
"cropped_face_image": {
"info": {
"width": 112,
"height": 112,
"channels": 4,
"depths": 0,
"color": 4
},
"data": ""
}
}
}fun compareFaces(compareFacesConfig: CompareFacesConfig, faceOne: Bitmap, faceTwo: Bitmap) : StringParameters:
faceOne: Bitmap: user's first image.faceTwo: Bitmap: user's second image.compareFacesConfig: CompareFacesConfig: user's config for changing settings.
The CompareFacesConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.faceMatchingThreshold-1.24: Threshold for matching faces.
Returns:
String: aJSONrepresenting the face status.
Example:
fun compareTwoImage(){
viewModelScope.launch(Dispatchers.IO) {
val bitmapTwo = BitmapFactory.decodeResource(context.resources, R.drawable.ellon_image)
val bitmapOne = BitmapFactory.decodeResource(context.resources, R.drawable.test_user_image)
privateIdentitySession.compareFaces(
compareFacesConfig= CompareFacesConfig(skipAntispoof = true),bitmapOne,bitmapTwo)
}
}A sample JSON result:
{
"call_status": {
"return_status": 0,
"operation_tag": "compare_files",
"return_message": "",
"mf_token": "",
"operation_id": 11,
"operation_type_id": 6
},
"face_compare": {
"result": 1,
"a_face_validation_status": 0,
"b_face_validation_status": 0,
"distance_min": 0.881899476,
"distance_mean": 0.881899476,
"distance_max": 0.881899476,
"conf_score": 0.711803317,
"face_thresholds": [
0.3,
1.24,
0.65
]
}
}This function allows you to scan data from the front side of the document (government ID or driver's license). This method accepts a valid image of the front side of the ID document with a mugshot and returns a cropped document and mugshot images as well as a resulting JSON document.
fun frontDocumentScan(bitmap: Bitmap, idDocumentFrontScanConfig: IdDocumentFrontScanConfig): ScanDocumentsFrontParameters:
bitmap: Bitmap: input image for scanning document.idDocumentFrontScanConfig: IdDocumentFrontScanConfig: user's config for changing settings.
The IdDocumentFrontScanConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.thresholdDocX-0.2: the minimal allowed distance (as the ratio of input image width) between the detected document edge and the left/right sides of the input image.thresholdDocY-0.2: the minimal allowed distance (as the ratio of input image height) between the detected document edge and the top/bottom sides of the input image.documentAutoRotation-true: If the value is 'true,' the function will rotate the input image several times for better detection results.blurThreshold-15.0: the threshold for marking input mugshot face as blurry. Smaller values are less restrictive, and 0.0 means no blurriness check.
Returns:
ScanDocumentsFront: an object that contains JSON result, recognized document image, and mugshot image (face image of the front document).
Example:
fun scanDocumentsFront(bitmap: Bitmap) {
val result = privateIdentitySession.frontDocumentScan(
bitmap = bitmap, IdDocumentFrontScanConfig(
skipAntispoof = true, thresholdDocY = 0.0, thresholdDocX = 0.0))
updateUi(result)
}This function allows you to scan data from the back side of the document (government ID or driver's license). This method accepts a valid image of the back side of the ID document with a PTD417 barcode. It returns a cropped document and barcode images, as well as a resulting JSON document that contains barcode parsing results, if any. Note: high input image resolution is important for better barcode parsing results.
fun backDocumentScan(bitmap: Bitmap, documentConfig: IdDocumentBackScanConfig): ScanDocumentsBackIf you want to scan the barcode, use the documentScanBarcodeOnly parameter equal to true for faster processing.
Parameters:
image: UIImage: input image for scanning document.config: DocumentBackScanConfig: user's config for changing settings.
The DocumentBackScanConfig has default values:
skipAntispoof-true: anti-spoof is not enabled by default.documentScanBarcodeOnly-true: if you need to scan the whole document, you should use thefalsevalue here.thresholdDocX-0.2: the minimal allowed distance (as the ratio of input image width) between the detected document edge and the left/right sides of the input image.thresholdDocY-0.2: the minimal allowed distance (as the ratio of input image height) between the detected document edge and top/bottom sides of the input image.
Returns:
ScanDocumentsBack: an object that contains aJSONresult, recognized document image (if any), and barcode image.
Example:
fun scanDocumentsBack(bitmap: Bitmap) {
val result = privateIdentitySession.backDocumentScan(
bitmap = bitmap, IdDocumentBackScanConfig(
skipAntispoof = true, thresholdDocY = 0.0, thresholdDocX = 0.0))
updateUi(result)
}- -100 Internal Error
- -1 No Face Found
- 0 Valid Face
- 1 Image Spoof (Not Used)
- 2 Video Spoof (Not Used)
- 3 Too Close
- 4 Too Close
- 5 Too far to right (Close to right edge of image)
- 6 Too far to left (Close to left edge of image)
- 7 Too far up (Close to top edge of image)
- 8 Too far down (Close to bottom edge of image)
- 9 Too Blurry
- 10 Glasses Detected
- 11 Facemask Detected
- 12 Chin too far left
- 13 Chin too far right
- 14 Chin too far up
- 15 Chin too far down
- 16 Image too dim
- 17 Image too bright
- 18 Face low confidence value
- 19 Invalid face background (Not used)
- 20 Eyes blink
- 21 Mouth Open
- 22 Face tilted right
- 23 Face rotated left
- -100 Invalid Image
- -5 Greyscale Image
- -4 Invalid Face
- -2 Mobile phone detected
- -1 No Face Detected
- 0 Real
- 1 Spoof
val INVALID_IMAGE = -100
val SYSTEM_ERROR = -2
val MOVE_CLOSE/INVALID_DOCUMENT = -1
val SUCCESS =0
val DOCUMENT_IS_BLURRY = 2
val UNABLE_TO_PARSE_DOCUMENT = 3
val TOO_FAR = 4
val TOO_FAR_LEFT =5
val TOO_FAR_RIGHT = 6
val TOO_FAR_UP = 7
val TOO_FAR_DOWN = 8
val MUGSHOT_IS_BLURRY_OR_FINGER_BLOCKING_THE_DOCUMENT = 9
val DOCUMENT_FOUND_IS_NOT_VALID_FRONT_DOCUMENT = 18