Developer Guides

Setting up and docking a DP service

Integrating the Orange Pass typically only requires calling the browser extension, verifying, and saving the attestation data returned by the extension.

Frontend

Main Steps

To perform verification with Orange Pass, follow these steps:

  1. Install the Orange Pass Chrome extension.

  2. Call the methods provided by the Orange Pass extension to initiate proof.

  3. Orange Pass opens the corresponding third-party page and executes the proof process.

  4. The extension obtains the proof result and returns it to the page.

  5. The page sends the proof result to its backend, which verifies whether the relevant data in the proof meets the requirements and updates the relevant status.

  6. The frontend updates the frontend page based on the status updated by the backend.

Installing the Orange Pass Chrome Extension

To perform verification, users must first ensure that the extension is installed. You can determine whether the extension is installed by checking if the window.orangePass object is injected into the page. If the extension is not installed, guide the user to install it.

Calling Methods Provided by the Orange Pass Extension to Initiate Verification

The injected window.orangePass object contains methods to initiate verification. The relevant type definitions are as follows:

// Verification result
interface VerifyResult {
  recipient: string;
  verifier_address: string;
  verifier_signature: string;
  data_hash: string;
  schema_id: string;
  task_id: string;
  user_hash: string;
}

// window.orangePass type definition 
interface OrangePass {
  start: (schemaId: string, recipient: string, proxyFirst?: boolean) => Promise<VerifyResult>;
}

The parameter definitions for the start method are as follows:

Parameter
Definition

schemaId

The schema ID of the content to verify

recipient

Ethereum address, indicating ownership of the proof

proxyFirst

Whether to use proxy mode; optional; defaults to true

The specific usage is as follows

const startOrangePass = async () => {
  if (!window.orangePass) {
    // If the extension is not installed, guide to install it
    return;
  }

  // Execute proof and obtain the proof result
  const result = await window.orangePass.start(
    '***',
    '0x***',
    true,
  );
}

Orange Pass Opens the Corresponding Third-Party Page to Execute the Proof Process

When the window.orangePass.start method is called, the proof request is sent to the Orange Pass extension. The extension will use the provided schemaId parameter to retrieve the specific schema configuration, which records all the data required for the proof.

The core configuration parameters of the schema are as follows:

Parameter
Definition
Example

pageUrl

The page that needs to be opened for verification

apiUrl

The API endpoint that needs to be used for verification

responseMatches

Conditions that need to be met in the API response

""balance":\s*"(?.+?)""

responseRedactions

Fields that need to be exposed in the API response

"$.data.balance"

The core process is as follows

  1. Retrieve the corresponding schema configuration using the schemaId, obtaining data such as pageUrl and apiUrl.

  2. Open the third-party page at pageUrl.

  3. Listen for requests to the apiUrl endpoint, using zero-knowledge proof technology to prove that the data returned by the apiUrl endpoint meets the requirements.

  4. After verifying that the data returned by the apiUrl endpoint meets the requirements (e.g., Binance balance greater than 10 USDT), generate the proof.

How to obtain the schemaId?

Check all verifiable items on the Orange Pass official website and copy their schemaId. The Orange Pass official website is still under development.

The Extension Obtains the Proof Result and Returns It to the Page

After obtaining the proof result, the extension will return the result to the page:

  1. If the proof meets the requirements, the third-party verification page will automatically close, and the browser window will redirect to the page that initiated the verification.

  2. If the proof does not meet the requirements or if there are other errors, the third-party verification page will not close automatically. It will display the error message on the third-party verification page while also throwing an error to the initiating verification page, which developers can catch and handle accordingly.

The Page Sends the Proof Result to Its Backend, Which Validates Whether the Proof Data Meets the Requirements and Updates the Relevant Status

Once a proof is successfully obtained, the page needs to send the proof to its backend, which will validate its validity (signature verification). For instructions on how the backend performs verification, refer to the relevant backend Markdown. The verification data sent to the backend is as follows::

interface VerifyResult {
  recipient: string;
  verifier_address: string;
  verifier_signature: string;
  data_hash: string;
  schema_id: string;
  task_id: string;
  user_hash: string;
}

After the verification passes (signature verification), it can be proved that the user indeed meets the requirements corresponding to this schema_id. The core relevant field descriptions are as follows:

Parameter
Function

schema_id

The schema ID of the content to verify, e.g., Binance balance greater than 10 USDT

verifier_signature

The signature of the result, indicating that it passed the Orange Pass verification

recipient

Ethereum address, indicating ownership of the proof, preventing others from using the proof

user_hash

Hash value of the user ID who performed the verification in the third-party application; for instance, if verifying related to Binance, it would be the hash of the Binance ID to prevent generating the proof repeatedly with the same account

The logic following the proof verification is handled by the DApp-related backend itself. For example, after verifying the Binance balance greater than 10 USDT, the backend can change the relevant verification status to true.

The Frontend Updates Its Page Based on the Status Updated by the Backend

After sending the proof to the backend and receiving full verification, the frontend can request the latest data from the backend to update the frontend page. For instance, if the user's Binance balance is greater than 10 USDT, the UI should also be updated to reflect the status of the completed certification.

Backend

The frontend will receive the Attestation data returned by Orange Notary, which can be submitted to the backend service requiring verification. The backend service is responsible for validating the Attestation's authenticity, ensuring that the signature address of the Attestation is the official address of Orange Notary's production environment.

APIs

Notary (MPC Mode)

Name
Path
Method

Get Signing Address

/notary/signingAddress

POST

Generate Attestation

/notary/genAttestation

POST

Get Supported Schemas

/notary/schemas

POST

  1. Get Signing Address

Return the signing address for the notary

Path : /notary/signingAddress Method : POST Parameter :

Response :

{
    "code": "<signer address>",
}
  1. Generate Attestation

Return the attestation based on schema data Path : /notary/genAttestation Method : POST Parameter :

{
    "schema_id": "<schema id for the attestation>",
    "data": "<encrypted data for the attestation>",
    "reciepint": "<recipient address for the attestation>",
}

Response :

{
    "data": {
        "recipient": "<reciepient address>",
        "verifier_address": "<verifier address for the attestation>",
        "verifier_signature": "<verifier signature for the attestation>",
        "data_hash": "<data hash for the attestation>",
        "schema_id": "<schema id for the attestation>",
        "task_id": "<task id , random and  unique  for each attestation>",
        "user_hash": "<user identifier hash for the attestation>",
    }
}
  1. Get Supported Schemas

Return the supported schemas for the notary Path : /notary/schemas Method : POST Parameter :

{
    "conditions":{
        "wheres":[    // remove this if you want to return all schemas
            {
                "field_name":"schema_id",
                "field_op":"eq",
                "field_value":"<value>"
            }
        ],
        "orders":[
            {
                "field_name":"schema_id",
                "order":"desc"
            }
            ]
        }
    }

Response :

{
    "data":[
        {
           "ID":<seq no>,
           "SchemaName":"<name for the schema>",
           "NSchema":"<schema configuration>" ,
           "SchemaID":"<schema id>",
           "Category":"<category of the schema>",
           "Owner":"<owner of the schema>",
           "CreatedTime":"<created time>",
        }
    ]
}

Proxy (Proxy Mode)

Name
Path
Method

Get Signing Address

/proxy/signingAddress

POST

Generate Attestation

/proxy/genAttestation

POST

  1. Get Signing Address

Return the signing address for the notary

Path : /proxy/signingAddress Method : POST Parameter :

Response :

{
    "code": "<signer address>",
}
  1. Generate Attestation

Return the attestation based on schema data Path : /proxy/genAttestation Method : POST Parameter :

{
    "schema_id": "<schema id for the attestation>",
    "data": "<encrypted data for the attestation>",
    "reciepint": "<recipient address for the attestation>",
}

Response :

{
    "data": {
        "recipient": "<reciepient address>",
        "verifier_address": "<verifier address for the attestation>",
        "verifier_signature": "<verifier signature for the attestation>",
        "data_hash": "<data hash for the attestation>",
        "schema_id": "<schema id for the attestation>",
        "task_id": "<task id , random and  unique  for each attestation>",
        "user_hash": "<user identifier hash for the attestation>",
    }
}

1. Golang example

  1. Calculate the hash of the attestation

type Attestation struct {
	Recipient       string `json:"recipient"`
	VerifierAddress string `json:"verifier_address"`
	DataHash        string `json:"data_hash"`
	SchemaID        string `json:"schema_id"`
	TaskID          string `json:"task_id"`
	UHash           string `json:"user_hash"`
}

func GetAttestationHash(attestation *Attestation) ([]byte, error) {
	taskBytes, err := hexutil.Decode(attestation.TaskID)
	if err != nil {
		return nil, err
	}
	uhashBytes, err := hexutil.Decode(attestation.UHash)
	if err != nil {
		return nil, err
	}
	siBytes, err := hexutil.Decode(attestation.SchemaID)
	if err != nil {
		return nil, err
	}
	dhBytes, err := hexutil.Decode(attestation.DataHash)
	if err != nil {
		return nil, err
	}

	atHash := crypto.Keccak256Hash(
		taskBytes,
		uhashBytes,
		siBytes,
		common.LeftPadBytes(common.HexToAddress(attestation.Recipient).Bytes(), 32),
		dhBytes,
		common.LeftPadBytes(common.HexToAddress(attestation.VerifierAddress).Bytes(), 32),
	).Bytes()

	return atHash, nil
}

//verify the signature for message
func ETHVerifyNotarySig(from, sigHex string, msg []byte) bool {
	fromAddr := ethcomm.HexToAddress(from)

	sig := hexutil.MustDecode(sigHex)
	if len(sig) < 64 {
		return false
	}
	// https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L442
	if sig[64] != 27 && sig[64] != 28 {
		return false
	}
	sig[64] -= 27

	pubKey, err := crypto.SigToPub(msg, sig)
	if err != nil {
		return false
	}

	recoveredAddr := crypto.PubkeyToAddress(*pubKey)
	return strings.EqualFold(fromAddr.Hex(), recoveredAddr.Hex())
}

2. Verify by smart contract

  1. We also provide a smart contract for attestation verification. For Binance Smart Chain testnet, the contract address can be found in the explorer.

the parameter format should be:

["<task_id>","<user_hash>","<schema_id>","<recipient>","<data_hash>","<verifier_address>","<verifier_signature>"]

Last updated

Was this helpful?