Skip to main content

Signature verification

To improve the communication security between the Agora Notification Callback Server ( server and your server, Agora uses signatures for identity verification. The following steps show how to verify a signature:

  1. When you configure the Agora NCS, Agora generates a secret. You need to obtain the secret from Agora technical support and save it for signature verification when activating the NCS.
  2. When sending a message notification callback to your server, the Agora NCS server generates two signature values by using a secret and the HMAC/SHA1 and HMAC/SHA256 algorithms, and then adds the signature values to the Agora-Signature and Agora-Signature-V2 fields of the HTTPS request header.
  3. After receiving the notification callback, you can verify either Agora-Signature or Agora-Signature-V2. To verify Agora-Signature, use the secret, the raw request body, and the HMAC/SHA1 algorithm; to verify Agora-Signature-V2, use the secret, the raw request body, and the HMAC/SHA2 algorithm.

You can refer to the following signature verification code samples:

Python

HMAC/SHA256


_9
#!/usr/bin/env python2
_9
# !-*- coding: utf-8 -*-
_9
import hashlib
_9
import hmac
_9
# Gets the raw request body of the message notification and calculate the signature. The request_body in the following code is a binary byte array before deserialization and not a dictionary after deserialization.
_9
request_body = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
_9
secret = 'secret'
_9
signature2 = hmac.new(secret, request_body, hashlib.sha256).hexdigest()
_9
print(signature2) # 6d3320c60b11101395b7fc8f9068748808a0aa1bfa064438e39d1bc2c7d74d99</code></pre>

HMAC/SHA1


_9
#!/usr/bin/env python2
_9
# !-*- coding: utf-8 -*-
_9
import hashlib
_9
import hmac
_9
# Gets the raw request body of the message notification and calculate the signature. The request_body in the following code is a binary byte array before deserialization and not a dictionary after deserialization.
_9
request_body = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
_9
secret = 'secret'
_9
signature = hmac.new(secret, request_body, hashlib.sha1).hexdigest()
_9
print(signature) # 033c62f40f687675f17f0f41f91a40c71c0f134c</code></pre>

Node.js

HMAC/SHA256


_7
const crypto = require('crypto')
_7
// Gets the raw request body of the message notification and calculate the signature. The requestBody in the following code is a binary byte array before deserialization and not an object after deserialization.
_7
const requestBody = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
_7
const secret = 'secret'
_7
const signature2 = crypto.createHmac('sha256', secret).update(requestBody, 'utf8').digest('hex')
_7
console.log(signature2) // 6d3320c60b11101395b7fc8f9068748808a0aa1bfa064438e39d1bc2c7d74d99
_7
</code></pre>

HMAC/SHA1


_6
const crypto = require('crypto')
_6
// Gets the raw request body of the message notification and calculate the signature. The requestBody in the following code is a binary byte array before deserialization and not an object after deserialization.
_6
const requestBody = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'
_6
const secret = 'secret'
_6
const signature = crypto.createHmac('sha1', secret).update(requestBody, 'utf8').digest('hex')
_6
console.log(signature) // 033c62f40f687675f17f0f41f91a40c71c0f134c

Java

HMAC/SHA256


_38
import javax.crypto.Mac;
_38
import javax.crypto.SecretKey;
_38
import javax.crypto.spec.SecretKeySpec;
_38
public class HmacSha {
_38
// Converts an encrypted byte array into a hex string
_38
public static String bytesToHex(byte[] bytes) {
_38
StringBuffer sb = new StringBuffer();
_38
for (int i = 0; i &lt; bytes.length; i++) {
_38
String hex = Integer.toHexString(bytes[i] &amp; 0xFF);
_38
if (hex.length() &lt; 2) {
_38
sb.append(0);
_38
}
_38
sb.append(hex);
_38
}
_38
return sb.toString();
_38
}
_38
// Gets the encrypted hex string using the HMAC/SHA256 algorithm
_38
public static String hmacSha256(String message, String secret) {
_38
try {
_38
SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(
_38
"utf-8"), "HmacSHA256");
_38
Mac mac = Mac.getInstance("HmacSHA256");
_38
mac.init(signingKey);
_38
byte[] rawHmac = mac.doFinal(message.getBytes("utf-8"));
_38
return bytesToHex(rawHmac);
_38
} catch (Exception e) {
_38
throw new RuntimeException(e);
_38
}
_38
}
_38
public static void main(String[] args) {
_38
// Gets the raw request body of the message notification and calculate the
_38
// signature. The request_body in the following code is a binary byte array
_38
// before deserialization and not an object after deserialization.
_38
String request_body = "{\"eventMs\":1560408533119,\"eventType\":10,\"noticeId\":\"4eb720f0-8da7-11e9-a43e-53f411c2761f\",\"notifyMs\":1560408533119,\"payload\":{\"a\":\"1\",\"b\":2},\"productId\":1}";
_38
String secret = "secret";
_38
System.out.println(hmacSha256(request_body, secret)); // 033c62f40f687675f17f0f41f91a40c71c0f134c
_38
}
_38
}

HMAC/SHA1


_38
import javax.crypto.Mac;
_38
import javax.crypto.SecretKey;
_38
import javax.crypto.spec.SecretKeySpec;
_38
public class HmacSha {
_38
// Converts an encrypted byte array into a hex string
_38
public static String bytesToHex(byte[] bytes) {
_38
StringBuffer sb = new StringBuffer();
_38
for (int i = 0; i &lt; bytes.length; i++) {
_38
String hex = Integer.toHexString(bytes[i] &amp; 0xFF);
_38
if (hex.length() &lt; 2) {
_38
sb.append(0);
_38
}
_38
sb.append(hex);
_38
}
_38
return sb.toString();
_38
}
_38
// Gets the encrypted hex string using the HMAC/SHA1 algorithm
_38
public static String hmacSha1(String message, String secret) {
_38
try {
_38
SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(
_38
"utf-8"), "HmacSHA1");
_38
Mac mac = Mac.getInstance("HmacSHA1");
_38
mac.init(signingKey);
_38
byte[] rawHmac = mac.doFinal(message.getBytes("utf-8"));
_38
return bytesToHex(rawHmac);
_38
} catch (Exception e) {
_38
throw new RuntimeException(e);
_38
}
_38
}
_38
public static void main(String[] args) {
_38
// Gets the raw request body of the message notification and calculate the
_38
// signature. The request_body in the following code is a binary byte array
_38
// before deserialization and not an object after deserialization.
_38
String request_body = "{\"eventMs\":1560408533119,\"eventType\":10,\"noticeId\":\"4eb720f0-8da7-11e9-a43e-53f411c2761f\",\"notifyMs\":1560408533119,\"payload\":{\"a\":\"1\",\"b\":2},\"productId\":1}";
_38
String secret = "secret";
_38
System.out.println(hmacSha1(request_body, secret)); // 033c62f40f687675f17f0f41f91a40c71c0f134c
_38
}
_38
}

PHP

HMAC/SHA256


_21
&lt;?php
_21
function assertEqual($expect, $actual)
_21
{
_21
if ($expect != $actual) {
_21
echo("\n assert failed");
_21
echo("\n expect:\n " . $expect);
_21
echo("\n actual:\n " . $actual);
_21
echo("\n");
_21
} else {
_21
echo("assert ok\n");
_21
echo("\n");
_21
}
_21
}
_21
// Gets the raw request body of the message notification and calculate the signature. The requestBody in the following code is a binary byte array before deserialization and not an object after deserialization.
_21
$request_body = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}';
_21
$secret = 'secret';
_21
// The value of Agora-Signature-V2 in the request header
_21
$sha256 = '6d3320c60b11101395b7fc8f9068748808a0aa1bfa064438e39d1bc2c7d74d99';
_21
$res2 = (hash_hmac('sha256', $request_body, $secret));
_21
assertEqual($res2, $sha256);
_21
?>

HMAC/SHA1


_21
&lt;?php
_21
function assertEqual($expect, $actual)
_21
{
_21
if ($expect != $actual) {
_21
echo("\n assert failed");
_21
echo("\n expect:\n " . $expect);
_21
echo("\n actual:\n " . $actual);
_21
echo("\n");
_21
} else {
_21
echo("assert ok\n");
_21
echo("\n");
_21
}
_21
}
_21
// Gets the raw request body of the message notification and calculate the signature. The requestBody in the following code is a binary byte array before deserialization and not an object after deserialization.
_21
$request_body = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}';
_21
$secret = 'secret';
_21
// The value of Agora-Signature in the request header
_21
$sha1 = '033c62f40f687675f17f0f41f91a40c71c0f134c';
_21
$res1 = (hash_hmac('sha1', $request_body, $secret));
_21
assertEqual($res1, $sha1);
_21
?>