Developer API reference

Implement public key registration and lookup for seamless end-to-end encryption in your application


Overview

Implementing end-to-end encryption without sacrificing the features and convenience users have come to expect may require a little more effort, but it is possible, and your users will thank you. With AuthMA, your messaging client can lookup public keys from email addresses, phone numbers, and more -- without user hassle, and without fear of a MiTM.

Our keyserver uses a JSON API that is simple to integrate into your web, mobile, or desktop apps. In fact, the key Registration and Lookup features on this website are simple examples of how to build a web app that interfaces with the API. Feel free to view the the source code and adapt it to your needs!

Example: PHP for performing a public key lookup request


Keyserver
Our JSON keyserver is openly accessible from the following address:
ec2-107-20-62-180.compute-1.amazonaws.com
2003

The hostname and port of the keyserver may change in the future. Therefore, we recommend that your client applications obtain the most current hostname and port from the config file located at config.xml.


Public key lookup
  1. A public key lookup is begun by sending a JSON dictionary object to the keyserver:

    Key Type Description
    cmd string "lookup"
    contact_method string Must be one of "contact_email", "contact_mobile_phone", "contact_facebook_id", "contact_pseudoname". At this time, only "contact_email" is supported by the keyserver.
    contact_address string This is the email address, phone number, facebook ID or pseudoname (depending on contact_method).

    Example:

    {"cmd":"lookup","contact_method":"contact_email","contact_address":"joeshmoe@gmail.com"}
  2. If no public key has been registered to that address, or the lookup fails for any other reason, the keyserver will return a JSON dictionary object with the "err" key set. A successful response includes a base64 encoded JSON identity card, signature, and any community ratings if available.

    Example:

    {"card_enc":"eyJhdHRlc3RtZW50X3VybCI6Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9TzJ6YnhNNEVlaEUiLCJwdWJsaWNfa2V5IjoiTUlJQklEQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FRMEFNSUlCQ0FLQ0FRRUF5TmZNREptM095WExDWWJ3K1AzUDBKSG9SMDNZXG43Z3haSlVZaEt3SGtpL2RnNXJCL2hPNUgxcWxtRnVTS0QycjBlTWZscDhscnVwWXNnQ2RkTUpaTDY2ZlRvVUVtOW9DckRNZWtcbjNnTjgxU1FqVkFVUzdUZG1pZnpIWmU4WVdydXd0OFF3MjI5WEVkTFNhbUtHd0ZKU3hid0lQSGc4eFE5V2c0RDRQY0ZWK0h4cFxuUnczUDJkZW1OTkZVbkpMV2l6Q3NGc21FdUFwR1BITjRxMi9lL2lMSXNKSVErYmhrQmlzMHlyUVRVVzNpMU5qRjdoUlJObHpUXG4wRm9talNPWGpMMTN4Q25mWFNHU0kwajNlOURTSXU1bGdITnhvUE4vd2pETVY2NE1Jc0JqeVpQaFpkQmlTYmxJNllXZEtuMm9cbjM5QjFvTkRxMm1SaENsWWdGczc4Tzk0TUhRSUJFUT09XG4iLCJjb250YWN0X2FkZHJlc3MiOiJzYmhlaW5yaWNAZ21haWwuY29tIiwiY29udGFjdF9tZXRob2QiOiJjb250YWN0X2VtYWlsIiwiZmlyc3RuYW1lIjoiU3R1YXJ0In0=","card_sig":"FnFWcekItsnL0xKpRpHxMDyANmGrqq4NJ287KmBHsmGI0cclW7gqLkGTpaoqzIGiocfZywMjekH8N603rqBDFRWOTWb6tdYxkjUuPEbImpIjA8Ew0TCrZyY+ds6ChyTrnrTRQUOpOd02nhapZexvuBB3YIdUl9WW/ee5NyDFVfgW1/P+Kl4Rks2llQYzDCq5yOi0c9RUgp6a8zkGk8dBAu4bVfq6AIbm2CBTJDjKHohRX6Rn3goLM+DkQGUC9cp9o3E+bIrc67M1L0hxqeRP90FGbf2vf1I/XdvYxxaEuzYs8Wl3yT1IsILgquleEu7jFbQw+POW59OCjd9sTYamMA==","ratings":[]}
  3. The client application then decodes the "card_enc" field to obtain a JSON dictionary for the identity card. The public key is given in ASN.1 DER encoding in base64. This is the same as PEM format without the BEGIN/END amendments.

    Example:

    {"attestment_url":"https://www.youtube.com/watch?v=O2zbxM4EehE","public_key":"MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAyNfMDJm3OyXLCYbw+P3P0JHoR03Y\n7gxZJUYhKwHki/dg5rB/hO5H1qlmFuSKD2r0eMflp8lrupYsgCddMJZL66fToUEm9oCrDMek\n3gN81SQjVAUS7TdmifzHZe8YWruwt8Qw229XEdLSamKGwFJSxbwIPHg8xQ9Wg4D4PcFV+Hxp\nRw3P2demNNFUnJLWizCsFsmEuApGPHN4q2/e/iLIsJIQ+bhkBis0yrQTUW3i1NjF7hRRNlzT\n0FomjSOXjL13xCnfXSGSI0j3e9DSIu5lgHNxoPN/wjDMV64MIsBjyZPhZdBiSblI6YWdKn2o\n39B1oNDq2mRhClYgFs78O94MHQIBEQ==\n","contact_address":"stuart@gmail.com","contact_method":"contact_email","firstname":"Stuart"}
  4. Using the public key extracted from the identity card, the client application should verify that "card_sig" is a signature of the data "card_enc." This proves that the identity card was authored by the owner of the public key.

  5. The client application should now compute the MD5 hash of the public key and store the result as a hex string.

  6. The client application should show the media attestment to the user, and ask the user to verify its authenticity. The user should be reminded not only to verify that the identity of the person in the video is convincing, but also that the hex string communicated in the video is exactly equal to the computed MD5 hash!

  7. Finally, once the user has verified the authenticity of the media attestment, the client application should store the identity card for future reference. If the identity card is not stored locally, the client should sign the identity card with the user's own private key to prevent the cache entries from being modified by a third party.


Public key registration:
  1. Construct a JSON identity card containing the user's contact information, public key, and media attestment URL.

  2. Key Type Description
    contact_method string Must be one of "contact_email", "contact_mobile_phone", "contact_facebook_id", "contact_pseudoname". At this time, only "contact_email" is supported by the keyserver.
    contact_address string This is the email address, phone number, facebook ID or pseudoname (depending on contact_method).
    public_key string base64 encoded RSA public key
    youtube_id string The YouTube ID of media attestment.
    fullname string The user's display name, fullname, or pseudoname.

    Example (outdated):

    {"attestment_url":"https://www.youtube.com/watch?v=O2zbxM4EehE","public_key":"MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAyNfMDJm3OyXLCYbw+P3P0JHoR03Y\n7gxZJUYhKwHki/dg5rB/hO5H1qlmFuSKD2r0eMflp8lrupYsgCddMJZL66fToUEm9oCrDMek\n3gN81SQjVAUS7TdmifzHZe8YWruwt8Qw229XEdLSamKGwFJSxbwIPHg8xQ9Wg4D4PcFV+Hxp\nRw3P2demNNFUnJLWizCsFsmEuApGPHN4q2/e/iLIsJIQ+bhkBis0yrQTUW3i1NjF7hRRNlzT\n0FomjSOXjL13xCnfXSGSI0j3e9DSIu5lgHNxoPN/wjDMV64MIsBjyZPhZdBiSblI6YWdKn2o\n39B1oNDq2mRhClYgFs78O94MHQIBEQ==\n","contact_address":"stuart@gmail.com","contact_method":"contact_email","firstname":"Stuart"}
  3. Compute the signature of the base64 encoded identity card with the user's private RSA key. Signature scheme is RSASSA-PSS as defined in PKCS#1, using SHA-1 hash function.

  4. Construct a JSON registration request, which includes the JSON card and signature.

    Key Type Description
    cmd string "register"
    card string Contains the base64 encoded identity card.
    card_sig string Contains the base64 encoded user signature of the above card blob.

    Example:

    {"cmd":"register","card":"eyJhdHRlc3RtZW50X3VybCI6Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9TzJ6YnhNNEVlaEUiLCJwdWJsaWNfa2V5IjoiTUlJQklEQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FRMEFNSUlCQ0FLQ0FRRUF5TmZNREptM095WExDWWJ3K1AzUDBKSG9SMDNZXG43Z3haSlVZaEt3SGtpL2RnNXJCL2hPNUgxcWxtRnVTS0QycjBlTWZscDhscnVwWXNnQ2RkTUpaTDY2ZlRvVUVtOW9DckRNZWtcbjNnTjgxU1FqVkFVUzdUZG1pZnpIWmU4WVdydXd0OFF3MjI5WEVkTFNhbUtHd0ZKU3hid0lQSGc4eFE5V2c0RDRQY0ZWK0h4cFxuUnczUDJkZW1OTkZVbkpMV2l6Q3NGc21FdUFwR1BITjRxMi9lL2lMSXNKSVErYmhrQmlzMHlyUVRVVzNpMU5qRjdoUlJObHpUXG4wRm9talNPWGpMMTN4Q25mWFNHU0kwajNlOURTSXU1bGdITnhvUE4vd2pETVY2NE1Jc0JqeVpQaFpkQmlTYmxJNllXZEtuMm9cbjM5QjFvTkRxMm1SaENsWWdGczc4Tzk0TUhRSUJFUT09XG4iLCJjb250YWN0X2FkZHJlc3MiOiJzYmhlaW5yaWNAZ21haWwuY29tIiwiY29udGFjdF9tZXRob2QiOiJjb250YWN0X2VtYWlsIiwiZmlyc3RuYW1lIjoiU3R1YXJ0In0=","card_sig":"FnFWcekItsnL0xKpRpHxMDyANmGrqq4NJ287KmBHsmGI0cclW7gqLkGTpaoqzIGiocfZywMjekH8N603rqBDFRWOTWb6tdYxkjUuPEbImpIjA8Ew0TCrZyY+ds6ChyTrnrTRQUOpOd02nhapZexvuBB3YIdUl9WW/ee5NyDFVfgW1/P+Kl4Rks2llQYzDCq5yOi0c9RUgp6a8zkGk8dBAu4bVfq6AIbm2CBTJDjKHohRX6Rn3goLM+DkQGUC9cp9o3E+bIrc67M1L0hxqeRP90FGbf2vf1I/XdvYxxaEuzYs8Wl3yT1IsILgquleEu7jFbQw+POW59OCjd9sTYamMA=="}
  5. Send the JSON request to the keyserver.

  6. The keyserver will send a link to the user at their supplied contact address (eg, email). When the user clicks on this link, it will direct them to a CAPTCHA problem. On successful completion of the CAPTCHA, their registration attempt will be finalized by the keyserver.


Implementing user login

The client's private key should not be stored or retrieved on any third party servers, as this would violate the most fundamental principle of end-to-end encryption: the user's private key is not known by anyone else. It is also not a good idea to store the client's private key on the local filesystem, as this could be stolen, or might be inaccessible to the user from different machines. Therefore, the recommended way of storing a key is not at all: the user can remember a passphrase, and this passphrase can be used to derive a public-private keypair at login time by running it through a key expansion algorithm (e.g., PBKDF2) to generate a seed for a cryptographically secure random number generator that is used to generate an RSA keypair. Thus, if using a web client, there are necessarily two password fields that must be entered by the user: one to authenticate with the webservice provider, and the other password to be used locally by the client for encryption and decryption.


Implementing local search

In order to support content-based searching of encrypted messages, the client should maintain a search index of all decrypted messages (as well as outgoing messages prior to encryption). This search index should be encrypted with the user's private key. If the client is a web client, the search index should be stored in the cloud, so that the client can automatically re-download it when being used from a new machine.


Public keys held by organizations

In some cases, a contact address might be used by multiple people, such as a business address like support@company.com. Because this address is used by multiple people, it could not be registered with the keyserver for AMA-style authentication. However, the owners of this address may still wish to communicate with users via end-to-end encryption. This can be accomplished if the business encrypts their public key inside the contents of encrypted outgoing messages. Thus, in order to process such communications seamlessly, a client software should be prepared to extract public keys from incoming messages using an established protocol, as well as embed one's public key in outgoing encrypted messages.


Sanity checking

It is not a bad idea for a client application to periodically query the keyserver for the client's own public key, using an anonymizing proxy. This provides additional security and peace of mind by verifying that the keyserver is serving the proper key.