{"action":"opened","issue":{"url":"https://api.github.com/repos/cloudflare/cfssl/issues/220","labels_url":"https://api.github.com/repos/cloudflare/cfssl/issues/220/labels{/name}","comments_url":"https://api.github.com/repos/cloudflare/cfssl/issues/220/comments","events_url":"https://api.github.com/repos/cloudflare/cfssl/issues/220/events","html_url":"https://github.com/cloudflare/cfssl/issues/220","id":79235156,"number":220,"title":"Add asymmetric auth provider","user":{"login":"grittygrease","id":5125095,"avatar_url":"https://avatars.githubusercontent.com/u/5125095?v=3","gravatar_id":"","url":"https://api.github.com/users/grittygrease","html_url":"https://github.com/grittygrease","followers_url":"https://api.github.com/users/grittygrease/followers","following_url":"https://api.github.com/users/grittygrease/following{/other_user}","gists_url":"https://api.github.com/users/grittygrease/gists{/gist_id}","starred_url":"https://api.github.com/users/grittygrease/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/grittygrease/subscriptions","organizations_url":"https://api.github.com/users/grittygrease/orgs","repos_url":"https://api.github.com/users/grittygrease/repos","events_url":"https://api.github.com/users/grittygrease/events{/privacy}","received_events_url":"https://api.github.com/users/grittygrease/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-05-22T01:35:48Z","updated_at":"2015-05-22T01:35:48Z","closed_at":null,"body":"The HMAC authentication provider works great but it would be nice to have some sort of asymmetric authentication.\r\n\r\nThere are several ways to do this, but the requirements are simple. The client should sign the full request and include a signature performed with a private key known only to them. To verify the request, the server uses the corresponding public key. I will describe three scenarios here:\r\n\r\n1) one key per label\r\nThis is the simplest model and most closely resembles the HMAC authenticator.\r\n\r\nOn the client side, the authenticator config would consist of one private key and a signing algorithm.\r\nfor example:\r\n\"auth_keys\": {\r\n\t\"myauth\": {\r\n\t\t\"type\":\"rsa_oaep_sign\",\r\n\t\t\"privatekey\":\"<pem RSA private key>\"\r\n\t}\r\n},\r\n\r\n(alternatively <pem RSA private key> could be a URI for accessing a public key such as file:///key.pem or pkcs11://object=my-key;objecttype=private;pinfile=/etc/ssh/token_pin)\r\n\r\nWhen constructing the request to the server, the JSON message is serialized as in the standard auth case and the auth token is the request signed with the private key.\r\n\r\nOn the server side, the configuration holds the associated public keys for the requests.\r\n\"auth_keys\": {\r\n\t\"myauth\": {\r\n\t\t\"type\":\"rsa_oaep_verify\",\r\n\t\t\"key\":\"<pem RSA public key>\"\r\n\t}\r\n},\r\nAnd validates the signature with that certificate before accepting the request.\r\n\r\n2) Certificate-based\r\nIn this case, there is not a 1-1 relationship with authentication keys and authentication providers. Instead, the client can include a certificate in the message and sign the message with the corresponding private key. The server can validate the certificate through any means it wishes (certificate pinning, PKI, etc.)\r\n\r\nOn the client side, the authenticator config would consist of one private key, a signing algorithm and a certificate.\r\nfor example:\r\n\"auth_keys\": {\r\n\t\"myauth\": {\r\n\t\t\"type\":\"rsa_oaep_sign\",\r\n\t\t\"privatekey\":\"<pem RSA private key/URI>\"\r\n\t\t\"certificate\":\"<pem RSA certificate>\"\r\n\t}\r\n},\r\n\r\nWhen constructing the request to the server, the certificate would be added to the JSON message as an additional parameter so as to be included in the signed part of the message. The augmented JSON message is serialized as in the standard auth case and the auth token is the request signed with the private key.\r\n\r\nOn the server side, the configuration holds the associated public keys for the requests.\r\nThis is just an example:\r\n\"auth_keys\": {\r\n\t\"myauth\": {\r\n\t\t\"type\":\"rsa_oaep_verify_service\",\r\n\t\t\"service\":\"database_lookup\"\r\n\t}\r\n},\r\nIn this case, the service would first check the signature of the request using the certificate's public key, then use some sort of validation service to validate the public key.\r\n\r\nValidation service\r\nThis could be as simple as\r\n- validating that the client's IP matches a SAN in the certificate, or \r\n- validating that the certificate was signed by a trusted certificate authority \r\n\r\nof it could be handled by an external service.\r\n\r\nFor example, consider a model where many clients (such as web servers) were previously issued client certificates and these client certificates are associated with the identities of their owners in a database. This database associates each identity with a set of valid hostnames.\r\n\r\nA service could be set up that returns a hostname given a certificate. That hostname could be used to restrict the list of valid hostnames for a given request.\r\n\r\n"}}