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:
- 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.
- 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
andAgora-Signature-V2
fields of the HTTPS requestheader
. - After receiving the notification callback, you can verify either
Agora-Signature
orAgora-Signature-V2
. To verifyAgora-Signature
, use the secret, the raw request body, and the HMAC/SHA1 algorithm; to verifyAgora-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 -*-_9import hashlib_9import 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._9request_body = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'_9secret = 'secret'_9signature2 = hmac.new(secret, request_body, hashlib.sha256).hexdigest()_9print(signature2) # 6d3320c60b11101395b7fc8f9068748808a0aa1bfa064438e39d1bc2c7d74d99</code></pre>
HMAC/SHA1
_9#!/usr/bin/env python2_9# !-*- coding: utf-8 -*-_9import hashlib_9import 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._9request_body = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}'_9secret = 'secret'_9signature = hmac.new(secret, request_body, hashlib.sha1).hexdigest()_9print(signature) # 033c62f40f687675f17f0f41f91a40c71c0f134c</code></pre>
Node.js
HMAC/SHA256
_7const 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._7const requestBody = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}' _7const secret = 'secret' _7const signature2 = crypto.createHmac('sha256', secret).update(requestBody, 'utf8').digest('hex')_7console.log(signature2) // 6d3320c60b11101395b7fc8f9068748808a0aa1bfa064438e39d1bc2c7d74d99_7</code></pre>
HMAC/SHA1
_6const 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._6const requestBody = '{"eventMs":1560408533119,"eventType":10,"noticeId":"4eb720f0-8da7-11e9-a43e-53f411c2761f","notifyMs":1560408533119,"payload":{"a":"1","b":2},"productId":1}' _6const secret = 'secret' _6const signature = crypto.createHmac('sha1', secret).update(requestBody, 'utf8').digest('hex') _6console.log(signature) // 033c62f40f687675f17f0f41f91a40c71c0f134c
Java
HMAC/SHA256
_38import javax.crypto.Mac;_38import javax.crypto.SecretKey;_38import javax.crypto.spec.SecretKeySpec;_38public 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 < bytes.length; i++) {_38 String hex = Integer.toHexString(bytes[i] & 0xFF);_38 if (hex.length() < 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
_38import javax.crypto.Mac;_38import javax.crypto.SecretKey;_38import javax.crypto.spec.SecretKeySpec;_38public 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 < bytes.length; i++) {_38 String hex = Integer.toHexString(bytes[i] & 0xFF);_38 if (hex.length() < 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<?php_21function 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));_21assertEqual($res2, $sha256);_21?>
HMAC/SHA1
_21<?php_21function 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));_21assertEqual($res1, $sha1);_21?>