Telegram Passport
Telegram Passport is a unified authorization method for services that require personal identification.
As a bot developer, you can use it to receive confidential user data in an end-to-end encrypted fashion.
There are several Know Your Customer (KYC) solutions that have already added support for Telegram Passport.
This guide is targeted at bot developers and presents our library support for Telegram Passport. Click the badges above for more documentation.
Quickstart
This guide teaches the basics of working with Telegram Passport. See the complete version of the code at Quickstart project. Code snippets on this page are in the context of that project.
Encryption Keys
You don't really need to generate any RSA key. Use our sample keys for this demo.
Send the public key to @BotFather using /setpublickey
command:
Copy this public key and send it to BotFather.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0VElWoQA2SK1csG2/sY/
wlssO1bjXRx+t+JlIgS6jLPCefyCAcZBv7ElcSPJQIPEXNwN2XdnTc2wEIjZ8bTg
BlBqXppj471bJeX8Mi2uAxAqOUDuvGuqth+mq7DMqol3MNH5P9FO6li7nZxI1FX3
9u2r/4H4PXRiWx13gsVQRL6Clq2jcXFHc9CvNaCQEJX95jgQFAybal216EwlnnVV
giT/TNsfFjW41XJZsHUny9k+dAfyPzqAk54cgrvjgAHJayDWjapq90Fm/+e/DVQ6
BHGkV0POQMkkBrvvhAIQu222j+03frm9b2yZrhX/qS01lyjW4VaQytGV0wlewV6B
FwIDAQAB
-----END PUBLIC KEY-----
Now Telegram client app can encrypt the data for your bot using this key.
Request Information
Bot waits for a text message from user. Once it receives a text message, it generates an authorization request link and sends that to the user.
Authorization Request
A passport authorization request means that the bot should ask the user to open a tg://resolve
URI in the browser
with specific parameters in its query string.
You can alternatively have a button in an HTML page on your website for that.
Type AuthorizationRequestParameters
helps you in creating such an URI.
AuthorizationRequestParameters authReq = new AuthorizationRequestParameters(
botId: 123456, // bot user ID
publicKey: "...", // public key in PEM format. same as the key above.
nonce: "unique nonce for this request",
scope: new PassportScope { // a PassportScope object
Data = [
new PassportScopeElementOne(EncryptedPassportElementType.Address),
new PassportScopeElementOne(EncryptedPassportElementType.PhoneNumber)
]
});
In SendAuthorizationRequestAsync
method, we ask for address
and phone_number
scopes.
Then, we generate the query string and ask user to open the link.
You might be wondering what is the magic in here?
Our webpage https://telegrambots.github.io/Telegram.Bot.Extensions.Passport/redirect.html
redirects the user to tg://resolve
URI, appending whatever query string was passed to it.
If a user is using an Android device, the URI will start with
tg:
instead of the defaulttg://
.
Passport Data
You, the user, should now be redirected to the Telegram Passport screen in your Telegram client app. Enter your password and log in.
Note that the app will ask you to register if this is the first time you are using Telegram Passport.
Fill in the address and phone number data. Click on the Authorize button at the end.
At this point, your Telegram client app encrypts the actual Telegram Passport data (e.g. address) using the AES algorithm, and then encrypts the info required for decryption using your bot's public RSA key. Finally, it sends the result of both encryptions to Telegram servers.
Data Decryption
Your bot now receives a new message update with the encrypted Passport data. The user is also notified in the chat:
Let's decrypt that gibberish to get the information. That's what DecryptPassportDataAsync
method does.
Step 1: Credentials
You can't just access the encrypted data in the message.PassportData.Data
array.
Required parameters for their decryption are in the message.PassportData.Credentials
object.
But that credentials object is encrypted using bot's public key!
We first take the bot's private key this time and decrypt the credentials.
Note: We are loading the RSA key from PEM format thanks to the method
RSA.ImportFromPem
(.NET 5+).
var decrypter = new Decrypter();
var credentials = decrypter.DecryptCredentials(message.PassportData.Credentials, GetRsaPrivateKey());
Step 2: Nonce
There is a nonce
property on the credentials (now decrypted) object.
In order to prevent certain attacks, ensure its value is exactly the same as the nonce you set in the authorization request.
Read more about nonce on Wikipedia.
Step 3: Residential Address
It's finally time to see the user's address.
We are looking for an encrypted element with type of address in message.PassportData.Data
array.
Also, decryption parameters for that are in Credentials.SecureData.Address.Data
.
Here is how the decryption magic happens:
var addressElement = message.PassportData.Data.Single(el => el.Type == PassportEnums.Scope.Address);
var address = decrypter.DecryptData<ResidentialAddress>(addressElement.Data, credentials.SecureData.Address.Data);
DecryptData
method does 3 tasks here:
- Decrypts the data into a JSON-serialized string
- Verifies that the data hashes match
- Converts from JSON to a .NET object
Step 4: Phone Number
Values for phone number and email address are not end-to-end encrypted in Telegram Passport and Telegram stores these values after being verified.
There is no need for decryption at this point.
Just find the element with the type of phone_number in the message.PassportData.Data
array.
Information Demo
At the end, bot sends some of the information received to the user for demo purposes.