Name: js-handler/node_modules/restify/node_modules/http-signature/http_signing.md
| 1: | # Abstract |
| 2: | |
| 3: | This document describes a way to add origin authentication, message integrity, |
| 4: | and replay resistance to HTTP REST requests. It is intended to be used over |
| 5: | the HTTPS protocol. |
| 6: | |
| 7: | # Copyright Notice |
| 8: | |
| 9: | Copyright (c) 2011 Joyent, Inc. and the persons identified as document authors. |
| 10: | All rights reserved. |
| 11: | |
| 12: | Code Components extracted from this document must include MIT License text. |
| 13: | |
| 14: | # Introduction |
| 15: | |
| 16: | This protocol is intended to provide a standard way for clients to sign HTTP |
| 17: | requests. RFC2617 (HTTP Authentication) defines Basic and Digest authentication |
| 18: | mechanisms, and RFC5246 (TLS 1.2) defines client-auth, both of which are widely |
| 19: | employed on the Internet today. However, it is common place that the burdens of |
| 20: | PKI prevent web service operators from deploying that methodoloy, and so many |
| 21: | fall back to Basic authentication, which has poor security characteristics. |
| 22: | |
| 23: | Additionally, OAuth provides a fully-specified alternative for authorization |
| 24: | of web service requests, but is not (always) ideal for machine to machine |
| 25: | communication, as the key acquisition steps (generally) imply a fixed |
| 26: | infrastructure that may not make sense to a service provider (e.g., symmetric |
| 27: | keys). |
| 28: | |
| 29: | Several web service providers have invented their own schemes for signing |
| 30: | HTTP requests, but to date, none have been placed in the public domain as a |
| 31: | standard. This document serves that purpose. There are no techniques in this |
| 32: | proposal that are novel beyond previous art, however, this aims to be a simple |
| 33: | mechanism for signing these requests. |
| 34: | |
| 35: | # Signature Authentication Scheme |
| 36: | |
| 37: | The "signature" authentication scheme is based on the model that the client must |
| 38: | authenticate itself with a digital signature produced by either a private |
| 39: | asymmetric key (e.g., RSA) or a shared symmetric key (e.g., HMAC). The scheme |
| 40: | is parameterized enough such that it is not bound to any particular key type or |
| 41: | signing algorithm. However, it does explicitly assume that clients can send an |
| 42: | HTTP `Date` header. |
| 43: | |
| 44: | ## Authorization Header |
| 45: | |
| 46: | The client is expected to send an Authorization header (as defined in RFC 2617) |
| 47: | with the following parameterization: |
| 48: | |
| 49: | credentials := "Signature" params |
| 50: | params := 1#(keyId | algorithm | [headers] | [ext] | signature) |
| 51: | digitalSignature := plain-string |
| 52: | |
| 53: | keyId := "keyId" "=" <"> plain-string <"> |
| 54: | algorithm := "algorithm" "=" <"> plain-string <"> |
| 55: | headers := "headers" "=" <"> 1#headers-value <"> |
| 56: | ext := "ext" "=" <"> plain-string <"> |
| 57: | signature := "signature" "=" <"> plain-string <"> |
| 58: | |
| 59: | headers-value := plain-string |
| 60: | plain-string = 1*( %x20-21 / %x23-5B / %x5D-7E ) |
| 61: | |
| 62: | ### Signature Parameters |
| 63: | |
| 64: | #### keyId |
| 65: | |
| 66: | REQUIRED. The `keyId` field is an opaque string that the server can use to look |
| 67: | up the component they need to validate the signature. It could be an SSH key |
| 68: | fingerprint, an LDAP DN, etc. Management of keys and assignment of `keyId` is |
| 69: | out of scope for this document. |
| 70: | |
| 71: | #### algorithm |
| 72: | |
| 73: | REQUIRED. The `algorithm` parameter is used if the client and server agree on a |
| 74: | non-standard digital signature algorithm. The full list of supported signature |
| 75: | mechanisms is listed below. |
| 76: | |
| 77: | #### headers |
| 78: | |
| 79: | OPTIONAL. The `headers` parameter is used to specify the list of HTTP headers |
| 80: | used to sign the request. If specified, it should be a quoted list of HTTP |
| 81: | header names, separated by a single space character. By default, only one |
| 82: | HTTP header is signed, which is the `Date` header. Note that the list MUST be |
| 83: | specified in the order the values are concatenated together during signing. To |
| 84: | include the HTTP request line in the signature calculation, use the special |
| 85: | `request-line` value. While this is overloading the definition of `headers` in |
| 86: | HTTP linguism, the request-line is defined in RFC 2616, and as the outlier from |
| 87: | headers in useful signature calculation, it is deemed simpler to simply use |
| 88: | `request-line` than to add a separate parameter for it. |
| 89: | |
| 90: | #### extensions |
| 91: | |
| 92: | OPTIONAL. The `extensions` parameter is used to include additional information |
| 93: | which is covered by the request. The content and format of the string is out of |
| 94: | scope for this document, and expected to be specified by implementors. |
| 95: | |
| 96: | #### signature |
| 97: | |
| 98: | REQUIRED. The `signature` parameter is a `Base64` encoded digital signature |
| 99: | generated by the client. The client uses the `algorithm` and `headers` request |
| 100: | parameters to form a canonicalized `signing string`. This `signing string` is |
| 101: | then signed with the key associated with `keyId` and the algorithm |
| 102: | corresponding to `algorithm`. The `signature` parameter is then set to the |
| 103: | `Base64` encoding of the signature. |
| 104: | |
| 105: | ### Signing String Composition |
| 106: | |
| 107: | In order to generate the string that is signed with a key, the client MUST take |
| 108: | the values of each HTTP header specified by `headers` in the order they appear. |
| 109: | |
| 110: | 1. If the header name is not `request-line` then append the lowercased header |
| 111: | name followed with an ASCII colon `:` and an ASCII space ` `. |
| 112: | 2. If the header name is `request-line` then appened the HTTP request line, |
| 113: | otherwise append the header value. |
| 114: | 3. If value is not the last value then append an ASCII newline `\n`. The string |
| 115: | MUST NOT include a trailing ASCII newline. |
| 116: | |
| 117: | # Example Requests |
| 118: | |
| 119: | All requests refer to the following request (body ommitted): |
| 120: | |
| 121: | POST /foo HTTP/1.1 |
| 122: | Host: example.org |
| 123: | Date: Tue, 07 Jun 2011 20:51:35 GMT |
| 124: | Content-Type: application/json |
| 125: | Content-MD5: h0auK8hnYJKmHTLhKtMTkQ== |
| 126: | Content-Length: 123 |
| 127: | |
| 128: | The "rsa-key-1" keyId refers to a private key known to the client and a public |
| 129: | key known to the server. The "hmac-key-1" keyId refers to key known to the |
| 130: | client and server. |
| 131: | |
| 132: | ## Default parameterization |
| 133: | |
| 134: | The authorization header and signature would be generated as: |
| 135: | |
| 136: | Authorization: Signature keyId="rsa-key-1",algorithm="rsa-sha256",signature="Base64(RSA-SHA256(signing string))" |
| 137: | |
| 138: | The client would compose the signing string as: |
| 139: | |
| 140: | date: Tue, 07 Jun 2011 20:51:35 GMT |
| 141: | |
| 142: | ## Header List |
| 143: | |
| 144: | The authorization header and signature would be generated as: |
| 145: | |
| 146: | Authorization: Signature keyId="rsa-key-1",algorithm="rsa-sha256",headers="request-line date content-type content-md5",signature="Base64(RSA-SHA256(signing string))" |
| 147: | |
| 148: | The client would compose the signing string as (`+ "\n"` inserted for |
| 149: | readability): |
| 150: | |
| 151: | POST /foo HTTP/1.1 + "\n" |
| 152: | date: Tue, 07 Jun 2011 20:51:35 GMT + "\n" |
| 153: | content-type: application/json + "\n" |
| 154: | content-md5: h0auK8hnYJKmHTLhKtMTkQ== |
| 155: | |
| 156: | ## Algorithm |
| 157: | |
| 158: | The authorization header and signature would be generated as: |
| 159: | |
| 160: | Authorization: Signature keyId="hmac-key-1",algorithm="hmac-sha1",signature="Base64(HMAC-SHA1(signing string))" |
| 161: | |
| 162: | The client would compose the signing string as: |
| 163: | |
| 164: | date: Tue, 07 Jun 2011 20:51:35 GMT |
| 165: | |
| 166: | # Signing Algorithms |
| 167: | |
| 168: | Currently supported algorithm names are: |
| 169: | |
| 170: | * rsa-sha1 |
| 171: | * rsa-sha256 |
| 172: | * rsa-sha512 |
| 173: | * dsa-sha1 |
| 174: | * hmac-sha1 |
| 175: | * hmac-sha256 |
| 176: | * hmac-sha512 |
| 177: | |
| 178: | # Security Considerations |
| 179: | |
| 180: | ## Default Parameters |
| 181: | |
| 182: | Note the default parameterization of the `Signature` scheme is only safe if all |
| 183: | requests are carried over a secure transport (i.e., TLS). Sending the default |
| 184: | scheme over a non-secure transport will leave the request vulnerable to |
| 185: | spoofing, tampering, replay/repudiaton, and integrity violations (if using the |
| 186: | STRIDE threat-modeling methodology). |
| 187: | |
| 188: | ## Insecure Transports |
| 189: | |
| 190: | If sending the request over plain HTTP, service providers SHOULD require clients |
| 191: | to sign ALL HTTP headers, and the `request-line`. Additionally, service |
| 192: | providers SHOULD require `Content-MD5` calculations to be performed to ensure |
| 193: | against any tampering from clients. |
| 194: | |
| 195: | ## Nonces |
| 196: | |
| 197: | Nonces are out of scope for this document simply because many service providers |
| 198: | fail to implement them correctly, or do not adopt security specfiications |
| 199: | because of the infrastructure complexity. Given the `header` parameterization, |
| 200: | a service provider is fully enabled to add nonce semantics into this scheme by |
| 201: | using something like an `x-request-nonce` header, and ensuring it is signed |
| 202: | with the `Date` header. |
| 203: | |
| 204: | ## Clock Skew |
| 205: | |
| 206: | As the default scheme is to sign the `Date` header, service providers SHOULD |
| 207: | protect against logged replay attacks by enforcing a clock skew. The server |
| 208: | SHOULD be synchronized with NTP, and the recommendation in this specification |
| 209: | is to allow 300s of clock skew (in either direction). |
| 210: | |
| 211: | ## Required Headers to Sign |
| 212: | |
| 213: | It is out of scope for this document to dictate what headers a service provider |
| 214: | will want to enforce, but service providers SHOULD at minimum include the |
| 215: | `Date` header. |
| 216: | |
| 217: | # References |
| 218: | |
| 219: | ## Normative References |
| 220: | |
| 221: | * [RFC2616] Hypertext Transfer Protocol -- HTTP/1.1 |
| 222: | * [RFC2617] HTTP Authentication: Basic and Digest Access Authentication |
| 223: | * [RFC5246] The Transport Layer Security (TLS) Protocol Version 1.2 |
| 224: | |
| 225: | ## Informative References |
| 226: | |
| 227: | Name: Mark Cavage (editor) |
| 228: | Company: Joyent, Inc. |
| 229: | Email: [email protected] |
| 230: | URI: http://www.joyent.com |
| 231: | |
| 232: | # Appendix A - Test Values |
| 233: | |
| 234: | The following test data uses the RSA (2048b) keys, which we will refer |
| 235: | to as `keyId=Test` in the following samples: |
| 236: | |
| 237: | -----BEGIN PUBLIC KEY----- |
| 238: | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3 |
| 239: | 6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6 |
| 240: | Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw |
| 241: | oYi+1hqp1fIekaxsyQIDAQAB |
| 242: | -----END PUBLIC KEY----- |
| 243: | |
| 244: | -----BEGIN RSA PRIVATE KEY----- |
| 245: | MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF |
| 246: | NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F |
| 247: | UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB |
| 248: | AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA |
| 249: | QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK |
| 250: | kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg |
| 251: | f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u |
| 252: | 412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc |
| 253: | mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7 |
| 254: | kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA |
| 255: | gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW |
| 256: | G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI |
| 257: | 7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA== |
| 258: | -----END RSA PRIVATE KEY----- |
| 259: | |
| 260: | And all examples use this request: |
| 261: | |
| 262: | POST /foo?param=value&pet=dog HTTP/1.1 |
| 263: | Host: example.com |
| 264: | Date: Thu, 05 Jan 2012 21:31:40 GMT |
| 265: | Content-Type: application/json |
| 266: | Content-MD5: Sd/dVLAcvNLSq16eXua5uQ== |
| 267: | Content-Length: 18 |
| 268: | |
| 269: | {"hello": "world"} |
| 270: | |
| 271: | ### Default |
| 272: | |
| 273: | The string to sign would be: |
| 274: | |
| 275: | date: Thu, 05 Jan 2012 21:31:40 GMT |
| 276: | |
| 277: | The Authorization header would be: |
| 278: | |
| 279: | Authorization: Signature keyId="Test",algorithm="rsa-sha256",signature="JldXnt8W9t643M2Sce10gqCh/+E7QIYLiI+bSjnFBGCti7s+mPPvOjVb72sbd1FjeOUwPTDpKbrQQORrm+xBYfAwCxF3LBSSzORvyJ5nRFCFxfJ3nlQD6Kdxhw8wrVZX5nSem4A/W3C8qH5uhFTRwF4ruRjh+ENHWuovPgO/HGQ=" |
| 280: | |
| 281: | ### All Headers |
| 282: | |
| 283: | Parameterized to include all headers, the string to sign would be (`+ "\n"` |
| 284: | inserted for readability): |
| 285: | |
| 286: | POST /foo?param=value&pet=dog HTTP/1.1 + "\n" |
| 287: | host: example.com + "\n" |
| 288: | date: Thu, 05 Jan 2012 21:31:40 GMT + "\n" |
| 289: | content-type: application/json + "\n" |
| 290: | content-md5: Sd/dVLAcvNLSq16eXua5uQ== + "\n" |
| 291: | content-length: 18 |
| 292: | |
| 293: | The Authorization header would be: |
| 294: | |
| 295: | Authorization: Signature keyId="Test",algorithm="rsa-sha256",headers="request-line host date content-type content-md5 content-length",signature="Gm7W/r+e90REDpWytALMrft4MqZxCmslOTOvwJX17ViEBA5E65QqvWI0vIH3l/vSsGiaMVmuUgzYsJLYMLcm5dGrv1+a+0fCoUdVKPZWHyImQEqpLkopVwqEH67LVECFBqFTAKlQgBn676zrfXQbb+b/VebAsNUtvQMe6cTjnDY=" |
