Sign Requests

Last Updated on : 2022-12-21 07:49:53download

When you call an API operation of the cloud development, you must provide a signature to verify your identity. This topic describes how to generate a signature in a call.

This topic is no longer maintained. For the latest version of sign method, see Sign Request.

Tuya provides sample code for signature construction:

  1. Java development: Java develop code sample
  2. GoLand development: GoLand develop code sample
  3. Nodejs development: Nodejs develop code sample

Signature algorithm

Tuya Smart uses HMAC-SHA256 to create a message digest.

  • You can verify the encryption result of sign in the cloud API requests, for the detail please refer to Verify Signature Result.
  • To improve service security, Tuya has updated the signature algorithm. New projects created after June 30, 2021 can only be verified with the new algorithm. Projects created before June 30, 2021 can still be verified with the algorithm described in Sign Requests (Old Version). However, to ensure data security, we recommend that you update to a new signature algorithm.

Signature algorithm for token management operations

  • Scope of application: operations that are used to get or refresh tokens.

  • Signature algorithm:

    sign = HMAC-SHA256(client_id + t + nonce + stringToSign, secret).toUpperCase()
    
  • Procedure to sign a request:

    1. nonce is the UUID generated by the API caller, which prevents repetition by combining with the timestamp. It is an optional field. stringToSign is the signature string.
    2. Concatenate the value of client_id, the 13-digit standard timestamp (t) of the specified request, nonce, and stringToSign to create a string.
    3. Create a hash digest value based on the string and the value of secret. Encode the hash digest value into a new string.
    4. Capitalize all letters of the new string.

Signature algorithm for service management operations

  • Scope of application: operations that are used to manage services rather than tokens.

  • Signature algorithm:

    str = client_id + access_token + t + nonce + stringToSign 
    sign = HMAC-SHA256(str, secret).toUpperCase()
    
  • Procedure to sign a request:

    1. nonce is the UUID generated by the API caller, which prevents repetition by combining with the timestamp. It is an optional field. stringToSign is the signature string.

    2. Concatenate the value of client_id, access_token, the 13-digit standard timestamp (t) of the specified request, nonce, and stringToSign to create a string.

    3. Create a hash digest value based on the string and the value of secret. Encode the hash digest value into a new string.

    4. Capitalize all letters of the new string.

stringToSign signature string

  • Components

    String stringToSign= 
    HTTPMethod + "\n" + 
    Content-SHA256 + "\n" +
    Headers + "\n" +
    Url
    
  • Signature string fields

    1. HTTPMethod: All letters of each method name are capitalized. Example: POST and PUT.

    2. Content-SHA256: the SHA256 value of the body. SHA256 is calculated only when the body is not a form. Calculation:

      String content-SHA256 = SHA256(bodyStream.getbytes("UTF-8")); //`bodyStream` is a byte array.
      

      Note: When the body is empty, encryption will also be performed, and the encryption result is e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.

    3. Headers:

      Headers refers to the concatenated string of the Key and Value of the Header involved in the signature calculation.

      The keys of the headers in the signature are concatenated with colons (:) as the value of Signature-Headers.

      Header example:

      client_id:xxx
      Signature-Headers : Key1:Key2
      Key1:xxx
      Key2:xxx
      key3:xxx (it will not be included in the signature calculation)
      nonce:xxx
      ·····
      

      Headers calculation (Only the keys in Signature-Headers are calculated):

      String Headers =
      HeaderKey1 + ":" + HeaderValue1 + "\n" +
      HeaderKey2 + ":" + HeaderValue2 + "\n" +
      ...
      HeaderKeyN + ":" + HeaderValueN + "\n"
      
      
    4. URL: the Form parameter in Path + Query + Body. The following sample code shows how to calculate the URL:

      Sort the keys according to the dictionary, and follow the method below to concatenate Query + Form. If the Query or Form parameters are empty, the URL is the set value of Path and a connector ? is not required.

      String url =
      Path +
      "?" +
      Key1 + "=" + Value1 +
      "&" + Key2 + "=" + Value2 +
      "&" + Key3 + 
      ...
      "&" + KeyN + "=" + ValueN 
      

Signature examples

Parameters

The operation to get the user list is used as an example. The schema parameter is apps. No body parameter is required.

Note: For more information about the request header, see Request parameters.

Parameter Parameter value
URL /v2.0/apps/schema/users
method GET
client_id 1KAD46OrT9HafiKdsXeg
secret 4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC
t 1588925778000
access_token 3f4eda2bdec17232f67c0b188af3eec1
sign_method HMAC-SHA256
Note:In the signature digest algorithm, the request header is required.
nonce 5138cc3a9033d69856923fd07b491173
Signature-Headers area_id:call_id
area_id (Customized) 29a33e8796834b1efa6
call_id (Customized) 8afdb70ab2ed11eb85290242ac130003
page_no 1
page_size 50

Signature algorithm for token management operations

  1. Concatenate a string-to-sign.

    stringToSign=GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    	
    /v1.0/token?grant_type=1
    
  2. Concatenate a string-to-sign.

    1KAD46OrT9HafiKdsXeg15889257780005138cc3a9033d69856923fd07b491173GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    
    /v1.0/token?grant_type=1
    
  3. Create a hash digest value based on the string and the value of secret. Encode the hash digest value into a new string.

    • Hash digest value:

      HMAC-SHA256(1KAD46OrT9HafiKdsXeg15889257780005138cc3a9033d69856923fd07b491173GET
      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
      area_id:29a33e8796834b1efa6
      call_id:8afdb70ab2ed11eb85290242ac130003
      
      /v1.0/token?grant_type=1,4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC)
      
    • New string:
      9e48a3e93b302eeecc803c7241985d0a34eb944f40fb573c7b5c2a82158af13e

  4. Capitalize all letters of the new string.
    9E48A3E93B302EEECC803C7241985D0A34EB944F40FB573C7B5C2A82158AF13E

Signature algorithm for service management operations

  1. Concatenate a string-to-sign.

    stringToSign=GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    	
    /v2.0/apps/schema/users?page_no=1&page_size=50
    
  2. Concatenate a string-to-sign.

    1KAD46OrT9HafiKdsXeg3f4eda2bdec17232f67c0b188af3eec115889257780005138cc3a9033d69856923fd07b491173GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    
    /v2.0/apps/schema/users?page_no=1&page_size=50
    
  3. Create a hash digest value based on the string and the value of secret. Encode the hash digest value into a new string.

    • Hash digest value:

      HMAC-SHA256(1KAD46OrT9HafiKdsXeg3f4eda2bdec17232f67c0b188af3eec115889257780005138cc3a9033d69856923fd07b491173GET
      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
      area_id:29a33e8796834b1efa6
      call_id:8afdb70ab2ed11eb85290242ac130003
      
      /v2.0/apps/schema/users?page_no=1&page_size=50,4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC)
      
    • New string:
      ae4481c692aa80b25f3a7e12c3a5fd9bbf6251539dd78e565a1a72a508a88784

  4. Capitalize all letters of the new string.
    AE4481C692AA80B25F3A7E12C3A5FD9BBF6251539DD78E565A1A72A508A88784

Implement the HMAC SHA256 authentication scheme

Java

Click to download Java example.

Go

Click to download Go example.

Node.js

Click to download Node.js example.

Javascript

/**
Run the code online with this jsfiddle. Dependent upon an open source js library calledhttp://code.google.com/p/crypto-js/.
**/

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/enc-base64.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/hmac-sha256.min.js"></script>

<script>
  var hash = CryptoJS.HmacSHA256("str", "secret");
  var hashInBase64 = hash.toString().toUpperCase();
  document.write(hashInBase64);
</script>

PHP

/**
PHP has built in methods for hash_hmac (PHP 5) and base64_encode (PHP 4, PHP 5) resulting in no outside dependencies. Say what you want about PHP but they have the cleanest code for this example.
**/

$s = strtoupper(hash_hmac("sha256", "str", 'secret'));
echo var_dump($s);

Java

/**
Dependent on Apache Commons Codec to encode in base64.
**/

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class ApiSecurityExample {
  public static void main(String[] args) {
    try {
     String secret = "secret";
     String str = "str";

     Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
     SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
     sha256_HMAC.init(secret_key);

      byte[] bytes = sha256_HMAC.doFinal(str.getBytes());
     String hash = new HexBinaryAdapter().marshal(bytes).toUpperCase();
     System.out.println(hash);
    }
    catch (Exception e){
     System.out.println("Error");
    }
   }
}

C#

using System;
using System.Security.Cryptography;

namespace Test
{
  public class MyHmac
  {
    public static string Encrypt(string str, string secret)
            {
                secret = secret ?? "";
                var encoding = new System.Text.UTF8Encoding();
                byte[] keyByte = encoding.GetBytes(secret);
                byte[] messageBytes = encoding.GetBytes(str);
                using (var hmacsha256 = new HMACSHA256(keyByte))
                {
                    byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                    StringBuilder builder = new StringBuilder();
                    for (int i = 0; i < hashmessage.Length; i++)
                    {
                        builder.Append(hashmessage[i].ToString("x2"));
                    }
                    return builder.ToString().ToUpper();
                }
            }
  }
}