You can include the Authorization header in the HTTP request to carry signature information to indicate that the request has been authorized.

SDK implementation

OSS SDKs automatically implements signatures in your requests. You do not need to manually calculate your signature when you use OSS SDKs. For more information about the signature implementations in specific programming languages, see the OSS SDK code. The following table describes the sample code used to implement signatures in various SDKs.
SDK Signature implementation
Java SDK OSSRequestSigner.java
Python SDK auth.py
.NET SDK OssRequestSigner.cs
PHP SDK OssClient.php
C SDK oss_auth.c
JavaScript SDK client.js
Go SDK auth.go
Ruby SDK util.rb
iOS SDK OSSModel.m
Android SDK OSSUtils.java

Calculation of the Authorization header

Authorization = "OSS " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
            VERB + "\n"
            + Content-MD5 + "\n" 
            + Content-Type + "\n" 
            + Date + "\n" 
            + CanonicalizedOSSHeaders
            + CanonicalizedResource))

Detail analysis:

  • AccessKeySecret specifies the key required for a signature.
  • VERB specifies the HTTP request method such as PUT, GET, POST, HEAD, and DELETE.
  • \n specifies a line break.
  • Content-MD5 specifies the MD5 value of the request. The MD5 value is obtained by calculating the message content (excluding the header) and then encoding the resulting 128-bit number in Base64. This header can be used to check the validity of a message. It provides a checking mechanism for whether the message content is consistent with the sent content, such as "eB5eJF1ptWaXm4bijSPyxw==". This header may be left empty. For more information, visit RFC 2616 Content-MD5.
  • Content-Type specifies the type of the request content, such as application/octet-stream. This header may be left empty.
  • Date specifies the operation time in GMT format, such as Sun, 22 Nov 2015 08:16:38 GMT.
  • CanonicalizedOSSHeaders specifies an assembly of HTTP headers that are sorted in alphabetical order and whose prefixes are x-oss-.
  • CanonicalizedResource specifies the OSS resources you want to access.
Note The values of Date and CanonicalizedResource cannot be left empty. If the difference between the value of Date in the request and the current time of the OSS server is greater than 15 minutes, the OSS server denies the request and returns an HTTP 403 error.

Construct CanonicalizedOSSHeaders

All the HTTP headers whose prefixes are x-oss- are called CanonicalizedOSSHeaders. You can construct CanonicalizedOSSHeaders as follows:

  1. Convert the names of all HTTP request headers whose prefixes are x-oss- into lowercase letters. For example, convert X-OSS-Meta-Name: TaoBao into x-oss-meta-name: TaoBao.
  2. If the request is sent by using the AccessKey ID and AccessKey secret obtained by STS, you must add the obtained security-token value to the signature string in x-oss-security-token:security-token format.
  3. Sort all the obtained HTTP request headers in alphabetical order.
  4. Delete any spaces on either end of the delimiter between the header and content of each request. For example, convert x-oss-meta-name: TaoBao into x-oss-meta-name:TaoBao.
  5. Separate the header and content of each request with the \n delimiter to form the final CanonicalizedOSSHeaders.
Note
  • CanonicalizedOSSHeaders can be left empty, and the \n delimiter at the end can be removed.
  • To construct only one CanonicalizedOSSHeaders, you must add the \n delimiter to the end of the header. Example: x-oss-meta-a\n.
  • To construct multiple CanonicalizedOSSHeaders, you must add the \n delimiter to the end of each header. Example: x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n.

Construct CanonicalizedResource

The target OSS resource specified in the request sent by the user is called a CanonicalizedResource. You can construct a CanonicalizedResource as follows:

  1. Set CanonicalizedResource to a null character string "".
  2. Specify the OSS resource you want to access in the following format: /BucketName/ObjectName. If ObjectName does not exist, CanonicalizedResource is /BucketName/. If BucketName does not exist either, CanonicalizedResource is a forward slash (/).
  3. If the requested resource includes subresources (SubResource), sort all subresources in alphabetical order and separate the subresources with the ampersand (&) delimiter to generate a subresource string. Add a question mark (?) and the subresource string to the end of the CanonicalizedResource string. In this case, CanonicalizedResource is /BucketName/ObjectName?acl&uploadId=UploadId.
Note
  • The subresources supported by OSS currently include: acl, uploads, location, cors, logging, website, referer, lifecycle, delete, append, tagging, objectMeta, uploadId, partNumber, security-token, position, img, style, styleName, replication, replicationProgress, replicationLocation, cname, bucketInfo, comp, qos, live, status, vod, startTime, endTime, symlink, x-oss-process, response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, and response-content-encoding.
  • Three types of subresources are available:
    • Resource identifiers such as acl, append, uploadId, and symlink subresources. For more information, see Bucket operations and Object operations.
    • Subresources that specify the response header fields, such as response-*** subresources. For more information, see the Request parameters section in GetObject.
    • Object processing methods such as x-oss-process. For more information, see Image Processing.

Rules to calculate a signature header

  • A signature string must be in UTF-8 format. A signature string that contains Chinese characters must be encoded in UTF-8. The encoded signature string is used together with AccessKeySecret to calculate the final signature.
  • The HMAC-SHA1 method defined in RFC 2104 is used to calculate the final signature. In this method, the Key is AccessKeySecret.
  • Content-Type and Content-MD5 are not required in a request. If the request requires signature verification, null values must be replaced with a line break (\n).
  • Among non-HTTP headers, only the headers starting with x-oss- require signature strings. Other non-HTTP headers are ignored by OSS. For example, the x-oss-magic header in the following example must include a signature string.
    Note Headers starting with x-oss- must comply with the following specifications before signature verification:
    • The header name is converted to lowercase letters.
    • The headers are sorted in alphabetical order.
    • No space exists before or after the colon (:) that separates the header name and value.
    • Each header is followed by a line break (\n). If no header is used, set CanonicalizedOSSHeaders to null.

Examples

Request Signature string calculation formula Signature string
PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: foo@bar.com X-OSS-Magic: abracadabra Signature = base64(hmac-sha1(AccessKeySecret,VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource)) "PUT\n eB5eJF1ptWaXm4bijSPyxw==\n text/html\n Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nels

If AccessKeyId is "44CF959******252F707" and AccessKeySecret is "OtxrzxIsfpFjA7Sw******8Bw21TLhquhboDYROV", you can use the following method to calculate the signature in Python:

import base64
import hmac
import sha
h = hmac.new("OtxrzxIsfpFjA7Sw******8Bw21TLhquhboDYROV",
             "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha)
Signature = base64.b64encode(h.digest())
print("Signature: %s" % Signature)

The signature calculation result is 26NBxoKd******Dv6inkoDft/yA=. Based on the formula Authorization = "OSS" + AccessKeyId + ":" + Signature, the value of Authorization is OSS 44CF95900***BF252F707:26NBxoKd******Dv6inkoDft/yA=. The value is added with the Authorization header to form the message to be sent:

PUT /nelson HTTP/1.0
Authorization:OSS 44CF95900***BF252F707:26NBxoKd******Dv6inkoDft/yA=
Content-Md5: eB5eJF1ptWaXm4bijSPyxw==
Content-Type: text/html
Date: Thu, 17 Nov 2005 18:49:58 GMT
Host: oss-example.oss-cn-hangzhou.aliyuncs.com
X-OSS-Meta-Author: foo@bar.com
X-OSS-Magic: abracadabra

Detail analysis:

  • If the entered AccessKey ID does not exist or is not activated, 403 Forbidden is returned. Error code: InvalidAccessKeyId.
  • If the value of the Authorization header in the request is in an invalid format, 400 Bad Request is returned. Error code: InvalidArgument.
  • All OSS requests must use the GMT time format provided in HTTP 1.1. The format is as follows:
    date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982).
    Note In this format, day is in 2-digit form. Therefore, "Jun 2", "2 Jun 1982", and "2-Jun-1982" are all invalid formats.
  • If no date is entered or the date is in the invalid format during signature verification, 403 Forbidden is returned. Error code: AccessDenied.
  • The request must be entered within 15 minutes after the current time of the OSS server. Otherwise, 403 Forbidden is returned. Error code: RequestTimeTooSkewed.
  • If the AccessKey ID is activated but OSS determines that the signature of the user request is incorrect, 403 Forbidden is returned. The correct signature string for verification and encryption is returned to the user in the response message. You can check whether the signature string is correct based on the response of OSS.
    Sample responses:
    <? xml version="1.0" ? >
    <Error>
     <Code>
         SignatureDoesNotMatch
     </Code>
     <Message>
         The request signature we calculated does not match the signature you provided. Check your key and signing method.
     </Message>
     <StringToSignBytes>
         47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c
     </StringToSignBytes>
     <RequestId>
         1E446260FF9B****
     </RequestId>
     <HostId>
         oss-cn-hangzhou.aliyuncs. ***
     </HostId>
     <SignatureProvided>
         y5H7yzPsA/tP4+0tH1HHvPEwUv8=
     </SignatureProvided>
     <StringToSign>
         GET
    Wed, 11 May 2011 07:59:25 GMT
    /oss-example? acl
     </StringToSign>
     <OSSAccessKeyId>
         AKIAIVAKMSMOY7VO****
     </OSSAccessKeyId>
    </Error>

Calculate the Content-MD5 value

The message content "123456789" is used as an example. The following section provides a detailed description about the correct and incorrect methods to calculate the Content-MD5 value of the string.

  • Correct method
    1. Calculate the MD5-encrypted 128-bit binary array.
    2. Encode the binary array (instead of the 32-bit string) in Base64.
    The following code provides an example on how to calculate the Content-MD5 value in Python:
    >>> import base64,hashlib
    >>> hash = hashlib.md5()
    >>> hash.update("0123456789")
    >>> base64.b64encode(hash.digest())
    'eB5eJF1ptWaXm4bijSPyxw=='

    Call the hash.digest() function to obtain a 128-bit binary array.

    >>> hash.digest()
    'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7'
  • Incorrect method
    Note A common incorrect method is to directly encode the 32-bit string in Base64.
    # Call the hash.hexdigest() function to obtain a visible 32-bit string.
    >>> hash.hexdigest()
    '781e5e245d69b566979b86e28d23f2c7'
    # Result of encoding the MD5 value in Base64:
    >>> base64.b64encode(hash.hexdigest())
    'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='