Guide for Signers

Signers in GSMA's Open Verifiable Calling project are also called originating parties (OPs). They are typically UCaaS providers or traditional carriers and operators positioned in a route immediately after the internal VOIP systems of the accountable party (the enterprise whose brand is associated with the call). Signers are responsible for generating a SIP INVITE (or receiving an incomplete INVITE) for each call, and then adding to that INVITE an Identity header that contains the STIR-compliant VVP passport.

Before any calls can be signed, VVP requires enterprises to organize evidence that proves important things about their identity, brand, telephone number, and intentions. See Credential Types. Enterprises that want signed traffic configure most of this evidence ahead of time, but finish assembling their dossier at the moment the signer agrees to produce signed traffic for them. Once this permanent dossier exists, it is referenced repeatedly, without modification, as calls occur in realtime. Dossiers last as long as the enterprise wants to keep signed traffic configured that way; unlike X509 certificates, dossiers do not require periodic reissuance as keys rotate.

A signer fits into the overall SIP call flow exactly as STIR imagines (see steps 3 and 4):

What is different in our project is that the passport contains richer, more robust, and more permanent evidence than with other STIR passport types — proof of the legal identity of the caller, right to use TN, brand attributes, delegation to the originating service provider, relationship to call center, settlement, AI involvement, and so forth. See The Evidence Advantage. The verifier is able to achieve higher levels of assurance about more facts, and to justify their decisions to auditors anywhere in the world, now and at any future time, without central governance.

Approaches to signing

There are 3 ways you can implement signing behavior in this project:

  • with SIP redirects (just requires simple SBC config)

  • by calling RESTful APIs (requires a small amount of coding to integrate)

  • by implementing verification from scratch (doable with a significant investment)

In the first two approaches, signers call services that do the heavy lifting. In the Open Verifiable Calling project, these services are provided to experimenters by Provenant. In the final approach, signers collect and analyze the open VVP data themselves, and thus have full flexibility.

Easiest way to sign: use SIP redirect server

In this approach, the signer's SBC receives or generates a SIP INVITE that is not yet protected by VVP, and passes it to a SIP redirect server at sip-sign.voice.sandbox.provenant.net. This server uses the originating TN to look up the associated, preconfigured dossier. It then generates a signed Identity header (= STIR PASSporT; a JWT in compact format) matching (and hyperlinking to) that dossier. It returns an updated SIP INVITE containing this header. The response begins with a SIP status line that has a SIP response code that tells the SBC what kind of handling for the call is appropriate, based on the state of the evidence.

Prerequisites

Requesting an INVITE protected by VVP

Your SBC should forward to the signing endpoint every SIP INVITE that it wants to protect with the VVP mechanism.No special headers or parameters are required — just the INVITE as it would normally be generated. This INVITE will naturally contain the From and To headers (inputs for the PASSporT that will reference the dossier and hold a signature).

Sample TCP SIP signing request

What your SBC sends to this endpoint might look like this:

INVITE sip:[email protected]:5060 SIP/2.0
Via: SIP/2.0/TCP 192.168.122.197:5060;branch=z9hG4bK2437132
From: +XXXXXXXXXXX <sip:[email protected]:5060>;tag=12345
To: +YYYYYYYYYYY <sip:[email protected]:5060>
Call-ID: e403c07d-86cb-43c7-bf46-78c3a1d49d25
CSeq: 1 INVITE
Contact: sip:[email protected]:5060
Max-Forwards: 70
Content-Type: application/sdp
Content-Length: 0

Sample TCP SIP signing response

The response from the SIP redirect server is normally an upgraded SIP INVITE that now contains an Identity header. This new INVITE is what should be passed to downstream nodes in the route. For example:

SIP/2.0 306 branded 0x00204800
CSeq: 1 INVITE
Call-ID: e403c07d-86cb-43c7-bf46-78c3a1d49d25
From: "+" <sip:[email protected]:5060>;tag=12345
To: "+YYYYYYYYYYY" <sip:[email protected]:5060>
Via: SIP/2.0/TCP 192.168.122.197:5060;branch=z9hG4bK2437132;received=192.168.20.23;rport=46137
Contact: <sip:[email protected]:5060>
Identity: eyJhbGciOiJFZERTQSIsInR5cCI6InBhc3Nwb3J0IiwicHB0IjoidnZwIiwia2lkIjoiaHR0cDovL3dpdG5lc3MxLmRldi5wcm92ZW5hbnQubmV0OjU2MzEvb29iaS9FSVo1MGdaLXJIanNtdHljQWQ4VGtpRnJfU01RSmd0X1ZkN2xxb0s0UUZnNi93aXRuZXNzIn0.eyJvcmlnIjp7InRuIjpbIjQ0MjA3OTQ2MDgyMyJdfSwiZGVzdCI6eyJ0biI6WyIxMjEyMzMzMTIzNCJdfSwiaWF0IjoxNzU3NjA1NDI4LCJjYXJkIjpudWxsLCJjYWxsX3JlYXNvbiI6bnVsbCwiZ29hbCI6bnVsbCwiZXZkIjoiaHR0cHM6Ly9vcmlnaW4uZGV2LnByb3ZlbmFudC5uZXQvdjEvYWdlbnQvcHVibGljL0VHVGxRd1pUZTktLUlRQjhtamJzT0QyVjJ5b3ZON09KcWI1VEJZOTV3SWY1L2Rvc3NpZXIuY2VzciIsIm9yaWdJZCI6IiIsImV4cCI6MTc1NzYwNTcyOCwicmVxdWVzdF9pZCI6IiJ9.ZorPngtPKtA8T0NeIrHROq987hVvRR4sZhaIt-bMuJdk5cKvb-Kx57MiwXYX5qpEscUdlW8X7WyrJOJvWYjcDg;ppt=vvp
Request_id: 49066ecb-84e0-4723-8186-de9223431d1c
Content-Length: 0

Sample structure inside the Identity header

If you pass such an Identity header to a JWT parser (e.g., on https://jwt.io), you'll see that in addition to a signature, it contains substructure like this:

Header

{
  "alg": "EdDSA",
  "typ": "passport",
  "ppt": "vvp",
  "kid": "http://witness1.provenant.net:5631/oobi/EIZ50gZ-rHjsmtycAd8TkiFr_SMQJgt_Vd7lqoK4QFg6/witness"
}

Payload

{
  "orig": {
    "tn": [
      "XXXXXXXXXXX"
    ]
  },
  "dest": {
    "tn": [
      "YYYYYYYYYYY"
    ]
  },
  "iat": 1757605428,
  "card": null,
  "call_reason": "debt collection"
  "evd": "https://acme.com/dossiers/EGTlQwZTe9--IQB8mjbsOD2V2yovN7OJqb5TBY95wIf5.cesr",
  "origId": "",
  "exp": 1757605728,
  "request_id": "49066ecb-84e0-4723-8186-de9223431d1c"
}

In this data structure, the kid header allows verifiers to look up the key state of the signer, and the evd claim references the permanent dossier of evidence.

Possible outcomes

These samples show a typical interaction where evidence is complete and in optimal state, and branding information is included. Of course, the SIP redirect server at sip-sign.voice.sandbox.provenant.net also communicates errors exactly as the SIP spec expects — with 4xx and 5xx response codes. It will also advise callers if evidence doesn't intend to prove brand, or if it has a more complex state. It does this by signalling 5 different ways that downstream verifiers might react to the evidence. See SIP Response Codes for more details.

More control, slightly more effort: use RESTful web service

In this approach, your SBC calls an HTTPS signing endpoint, https://voice.sandbox.provenant.net/v1/signer/voice/sign, instead of a SIP redirect server. The benefit is that you can get richer data and can perform arbitrary customizations in your routing logic. The tradeoff is that you have to call an HTTPS API from SIP infrastructure. Performance at scale is optimized and can approach that of raw SIP, but to use the API, you must satisfy the API's cybersecurity requirements. Instead of using an API key or an OAuth token, you must sign your HTTP requests according to rules of RFC 9421. This RFC is elegant and very secure, but it is also relatively new, so the technique may be unfamiliar. (Implementation is not difficult — 20 to 40 lines of code in most common programming languages. Provenant has reference implementations that it can share upon request.) Perhaps more important, this also requires your infrastructure to create, register, and manage the lifecycle of an Ed25519 keypair, and it requires your code to depend on a cryptographic library like libsodium.

Sample POST

A request to the web verification endpoint is a POST. It must define the Content-Digest, Signature, and Signature-Input headers, and its body must be JSON that includes the orig and dest TNs, an optional request_id for tracing, and an optional call_reason. A sample request might look like this:

POST /v1/signer/voice/sign HTTP/1.1
Accept: application/json
origin-date: 2025-09-10T15:44:02.625712445-04:00
content-digest: sha-256=:aFeN5cBYC-fgfXYuD8wSzLf5gPnzElIRmlGgUY97sDc:
signature:indexed="?0";provenant-au="0BDKj3dIJjEylI3ZirsUM9waSuK7CpOlq_iHB2AkJuAd_V-0cn9Kc2reGe7wl6hyYjmyfPOGu7_R77-FbVN4Ue8E"
signature-input: provenant-au=("@method" "@path" "origin-date" "content-digest"); "created"="1757533442626";"keyid"="BB5o8EzplEwMlqZMJaiFhveqND1X0ECqhgyyu4S5VOmd";"alg"="ed25519";
Content-Type: application/json
Content-Length: 81
Host: sign.sip.callverify.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.12.0
 
{"orig":"+442079460823","dest":"+12123331234","request_id":"49066ecb-84e0-4723-8186-de9223431d1c","call_reason":"debt collection"}

If you'd like the OpenAPI (Swagger) definitions for this API, use ssh-keygen to create an Ed25519 keypair. Then contact Provenant with your public key and the IP address you'll be calling from. Your key will be registered and you'll receive docs to explore further.

Maximum control, significant investment: implement from scratch

The VVP specification and the related KERI, ACDC, CESR, and Dossier specifications that it depends on are all open, published to the world by standards organizations. In addition, there are reference implementations of major components of a VVP stack under permissive open source licenses on github (see 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13). The communities behind these resources conduct meetings that are open to the public, and may be able to offer simple orientation to what they've published. Participants in the Open Verifiable Calling project would likely be welcomed as peers with enthusiasm.

However, these resources represent many person-years of investment in a specialized problem domain. Therefore, those pursuing this approach should expect a significant learning curve. After they've mastered the basics, there is still work to be done, gluing the components together, adapting them to the special needs of VVP use cases, testing them rigorously, and deploying for high availability, scale, cybersecurity, and similar goals.

Last updated