署名メッセージ
SMS APIでは、SMSメッセージの送受信時に署名を使用できます。送信時には、メッセージと共に送信する署名を生成します。受信時には、受信ウェブフックに署名と、アプリケーションで署名を生成するために必要なすべてのフィールドが含まれ、2つの署名が一致することを検証します。
あなたはサインを使う:
- リクエストが信頼できるソースから発信されたものであることを検証する。
- メッセージが途中で改ざんされていないことを確認する。
- インターセプトとリプレーに対する防御
内容
この文書では、送信するメッセージへの署名と、受信するメッセージに正しい署名があるかどうかのVerifyの両方について、メッセージでの署名の使い方を説明します。
- 署名付きメッセージの送信.を使用する。 クライアントライブラリ で署名されたメッセージを生成し、送信する。
- 受信メッセージの署名検証 を使用して、受信するWebhookのメッセージの信頼性を確保します。
- 手動で署名を生成する 既存のライブラリを使用できない場合は、署名生成のための手動プロセスがここに含まれている。
メッセージ送信時に署名を使用する
署名付きメッセージを送信するには SIGNATURE_SECRET の代わりに API_SECRET メッセージの送信時に署名の秘密を見つけ、どの署名アルゴリズムを使うかを選択するには ダッシュボード.デフォルトのアルゴリズムはMD5ハッシュをサポートする。 MD5 HMAC, SHA1 HMAC, SHA-256 HMAC そして SHA-512 HMAC.
Vonageでは、次のいずれかを使用することを強くお勧めします。 クライアントライブラリ を使用して署名を生成または検証します。もし かなわない なぜかこうする。 缶 シグネチャを自分で生成して検証することもできますが、これは複雑で、エラーが発生する可能性があります。そのため 署名を手動で生成するセクション.
署名付きメッセージの送信プロセスは以下の通り:
- 署名入り リクエスト でSMSを送信する。
- チェック レスポンスコード リクエストを正しく送信したことを確認してください。
- メッセージが携帯電話に届きます。利用者の携帯電話から配信レシートが返送されます。
- (オプション) 署名入りの配送受領書と受信メッセージを要求した場合、各受信リクエストの署名を検証したいでしょう。
署名を正しく生成できなかった場合 ステータス は 14, invalid signature.詳細は トラブルシューティング の項を参照されたい。
デフォルトでは、メッセージ送信時の署名はオプションで、受信ウェブフックには含まれません。署名付き Webhook を有効にする、または送信されたメッセージにすべて署名するようにするには、次の連絡先までお問い合わせください。 サポート.
以下のコード例は、SMS APIを使って署名付きメッセージを送信する方法を示している。
Prerequisites
npm install @vonage/server-sdkCreate a file named send-signed-sms.js and add the following code:
const { Vonage } = require('@vonage/server-sdk');
const vonage = new Vonage({
apiKey: VONAGE_API_KEY,
apiSecret: VONAGE_API_SECRET,
// By passing in the signature, the SDK will sign the request for you
// Isn't that neat?!
signature: {
secret: SMS_SIGNATURE,
algorithm: 'md5hash',
},
});Write the code
Add the following to send-signed-sms.js:
const sendMessage = async () => {
try {
const result = await vonage.sms.send({
from: SMS_SENDER_ID,
to: SMS_TO_NUMBER,
text: 'A text message sent using the Vonage SMS API',
});
console.log('Message sent successfully.');
console.log(result);
} catch (error) {
console.error(`Message failed with error: ${error.message}`);
}
};
sendMessage();Run your code
Save this file to your machine and run it:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk-kotlin:2.1.1'Create a class named SendSignedSms and add the following code to the main method:
fun main() {
val client = Vonage {
apiKey(VONAGE_API_KEY)
signatureSecret(VONAGE_SIGNATURE_SECRET)
hashType(HashType.HMAC_SHA256)Write the code
Add the following to the main method of the SendSignedSms class:
val response = client.sms.sendText(
from = SMS_SENDER_ID,
to = SMS_TO_NUMBER,
message = "Hello from Vonage SMS API"
)
if (response.wasSuccessfullySent()) {
println("Message sent successfully.")
}
else {
println("Message failed with error: ${response[0].errorText}")Run your code
We can use the アプリケーション plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.kt.sms with the package containing SendSignedSms:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk:9.3.1'Create a class named SendSignedSms and add the following code to the main method:
import com.vonage.client.VonageClient;
import com.vonage.client.auth.hashutils.HashType;
import com.vonage.client.sms.MessageStatus;
import com.vonage.client.sms.SmsSubmissionResponse;
import com.vonage.client.sms.messages.TextMessage;Add the following to the main method of the SendSignedSms class:
);
SmsSubmissionResponse response = client.getSmsClient().submitMessage(message);
Write the code
Add the following to the main method of the SendSignedSms class:
System.out.println("Message sent successfully.");
} else {
System.out.println("Message failed with error: " + response.getMessages().get(0).getErrorText());
}
}
}
Run your code
We can use the アプリケーション plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.sms with the package containing SendSignedSms:
Prerequisites
Install-Package VonageCreate a file named SendSignedSms.cs and add the following code:
var credentials = Credentials.FromApiKeySignatureSecretAndMethod(
vonageApiKey,
vonageApiSignatureSecret,
Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash
);
Write the code
Add the following to SendSignedSms.cs:
var credentials = Credentials.FromApiKeySignatureSecretAndMethod(
vonageApiKey,
vonageApiSignatureSecret,
Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash
);
var vonageClient = new VonageClient(credentials);
var response = await vonageClient.SmsClient.SendAnSmsAsync(new Vonage.Messaging.SendSmsRequest()
{
To = SMS_TO_NUMBER,
From = SMS_SENDER_ID,
Text = "This is a Signed SMS"
});Prerequisites
composer require vonage/clientWrite the code
Add the following to send-signed-sms.php:
$signed = new \Vonage\Client\Credentials\SignatureSecret(
VONAGE_API_KEY,
VONAGE_API_SIGNATURE_SECRET,
'md5hash'
);
$client = new \Vonage\Client($signed);
$response = $client->sms()->send(
new \Vonage\SMS\Message\SMS(TO_NUMBER, FROM_NUMBER, 'Super interesting message')
);
echo "Message status: " . $response->current()->getStatus() . "\n";Run your code
Save this file to your machine and run it:
Prerequisites
pip install vonage python-dotenvWrite the code
Add the following to send-signed-sms.py:
from vonage import Auth, Vonage
from vonage_sms import SmsMessage, SmsResponse
client = Vonage(Auth(api_key=VONAGE_API_KEY, signature_secret=SMS_SIGNATURE))
message = SmsMessage(
to=SMS_TO_NUMBER,
from_=SMS_SENDER_ID,
text="A text message sent using the Vonage SMS API.",
)
response: SmsResponse = client.sms.send(message)
print(response)Run your code
Save this file to your machine and run it:
受信メッセージの署名を検証する
SMSエンドポイントに着信するWebhookの発信元を確認するために、着信メッセージのメッセージ署名を有効にすることができます。 サポート を使用して、受信メッセージに署名を添付するよう要求できます。この設定を有効にすると、着信SMSと配達受信の両方のウェブフックに sig パラメータを使用する。リクエストの他のパラメータとあなたの署名シークレットを使って署名を生成し、 送られた署名と比較する。この2つが一致すれば、リクエストは有効である。
連絡先 サポート をクリックして、アカウントのメッセージ署名を有効にしてください。
以下のコード例は、受信SMSメッセージの署名をVerifyする方法を示している。 sig パラメーターをクエリー文字列に追加する。
Prerequisites
npm install express @vonage/server-sdkWrite the code
Add the following to verify-signed-sms.js:
const { Vonage } = require('@vonage/server-sdk');
const app = require('express')();
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
app
.route('/webhooks/inbound-sms')
.get(handleInboundSms)
.post(handleInboundSms);
const handleInboundSms = (request, response) => {
const params = Object.assign(request.query, request.body);
const { sig } = params;
if (Vonage.sms.verifySignature(
sig,
params,
VONAGE_SIGNATURE_SECRET,
'md5hash', // one of md5hash, md5, sha1, sha256, or sha512
)) {
console.log('Valid signature');
} else {
console.log('Invalid signature');
}
response.status(204).send();
};
app.listen(process.env.PORT || 3000);Run your code
Save this file to your machine and run it:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk:9.3.1'Create a class named ReceiveSignedSms and add the following code to the main method:
import com.vonage.client.auth.RequestSigning;
import spark.Route;
import spark.Spark;Write the code
Add the following to the main method of the ReceiveSignedSms class:
* Route to handle incoming SMS GET request.
*/
Route inboundSmsAsGet = (req, res) -> {
String signatureSecret = VONAGE_SIGNATURE_SECRET;
System.out.println(signatureSecret);
if (RequestSigning.verifyRequestSignature(
req.raw().getInputStream(),
req.contentType(),
req.queryMap().toMap(),
signatureSecret
)) {
System.out.println("msisdn: " + req.queryParams("msisdn"));
System.out.println("messageId: " + req.queryParams("messageId"));
System.out.println("text: " + req.queryParams("text"));
System.out.println("type: " + req.queryParams("type"));
System.out.println("keyword: " + req.queryParams("keyword"));
System.out.println("messageTimestamp: " + req.queryParams("message-timestamp"));
res.status(204);
}
else {
System.out.println("Bad signature");
res.status(401);
}
return "";
};
Spark.port(5000);
Spark.get("/webhooks/inbound-sms", inboundSmsAsGet);
}Run your code
We can use the アプリケーション plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.sms with the package containing ReceiveSignedSms:
Prerequisites
Install-Package VonageCreate a file named SmsController.cs and add the following code:
{
[HttpGet("webhooks/inbound-sms")] Write the code
Add the following to SmsController.cs:
public IActionResult VerifySms()
{
var vonageApiSignatureSecret = Environment.GetEnvironmentVariable("VONAGE_API_SIGNATURE_SECRET") ?? "VONAGE_API_SIGNATURE_SECRET";
var sms = WebhookParser.ParseQuery<InboundSms>(Request.Query);
if (sms.ValidateSignature(vonageApiSignatureSecret, Vonage.Cryptography.SmsSignatureGenerator.Method.md5hash))
{
Console.WriteLine("Signature is valid");
}
else
{
Console.WriteLine("Signature not valid");
}
return NoContent();
}
}
}Prerequisites
composer require vonage/clientWrite the code
Add the following to verify-signed-sms.php:
$inbound = \Vonage\Message\InboundMessage::createFromGlobals();
if ($inbound->isValid()) {
$params = $inbound->getRequestData();
$signature = new Vonage\Client\Signature(
$params,
VONAGE_API_SIGNATURE_SECRET,
'md5hash'
);
$validSig = $signature->check($params['sig']);
if($validSig) {
error_log("Valid signature");
} else {
error_log("Invalid signature");
}
} else {
error_log('Invalid message');
}Run your code
Save this file to your machine and run it:
Prerequisites
pip install vonage python-dotenv fastapi[standard]Write the code
Add the following to main.py:
import os
from os.path import dirname, join
from dotenv import load_dotenv
envpath = join(dirname(__file__), '../.env')
load_dotenv(envpath)
VONAGE_API_KEY = os.getenv("VONAGE_API_KEY")
VONAGE_SIGNATURE_SECRET = os.getenv("VONAGE_SIGNATURE_SECRET")
from fastapi import FastAPI, Request
from vonage import Auth, Vonage
client = Vonage(Auth(api_key=VONAGE_API_KEY, signature_secret=VONAGE_SIGNATURE_SECRET))
app = FastAPI()
@app.post('/')
async def verify_signed_webhook(request: Request):
data = await request.json()
if client.http_client.auth.check_signature(data):
print('Valid signature')
else:
print('Invalid signature')Run your code
Save this file to your machine and run it:
注:A POST リクエストにはクエリー文字列データも含まれる可能性があります。両方の POST とクエリ文字列データは、SMS APIではサポートされていないため、予期しない結果になる可能性があります。
手動で署名を生成する
それは 一押し 署名の生成と検証には、Vonageライブラリの既存の機能をご利用ください。この機能を持つライブラリを使用していない場合は、自分で署名を生成する必要があります。MD5ハッシュ」署名やHMAC署名のいずれかを生成する場合は、テクニックが若干異なります。
ステップ1:ハッシュ署名とHMAC署名の場合
もしあなたが 署名を生成する: 現在のタイムスタンプをパラメータリストに追加する。 timestamp.これは、エポックからの秒数を含む整数でなければなりません (これは UNIX 時間としても知られています)。
もしあなたが 署名の検証 をVonageから取り外します:を削除します。 sig パラメータを使用します。 timestamp リクエストパラメータで指定された
それからだ:
- 各パラメーターをキー順にループする。
- パラメータリストのすべての値に対して
&そして=アンダースコア_. - で構成される文字列を生成する。
&akey=value&bkey=value. アンパサンド&を文字列の先頭に置く!
この時点で MD5 そして ハイマック ハッシュ法は異なる。以下のステップ2に従い、どのハッシュ技法を使うかを決める。
ステップ2
MD5ハッシュ
- 文字列の最後、最後の値の直後に署名の秘密を追加する。このようになります:
&akey=value&bkey=valueyour_signature_secret - 次に、この文字列をmd5ハッシュ関数に通し、結果のバイトを16進数の文字列に変換する。これがMD5ハッシュ署名となり、リクエストのHTTPパラメータに
sigパラメータが必要だ。
- 文字列の最後、最後の値の直後に署名の秘密を追加する。このようになります:
ハイマック
- 希望するアルゴリズムと署名の秘密をキーとしてHMACジェネレーターを作成する。
- 次に、この文字列をHMACジェネレーターに通し、結果のバイトを16進数の文字列に変換する。これがHMAC署名で、リクエストのHTTPパラメータに
sigパラメーター(例えば、PHPでは次のようになります。hash_hmac($algorithm, $data, $secret)).
ステップ3:補足事項
シグネチャを生成する際にパラメータ値を変更したが、HTTPパラメータとして渡される値は以下のとおりであることに留意されたい。 むかしながら これらのパラメータをSMS APIに送信する場合。
シグネチャーのトラブルシューティング
署名入りのメッセージを扱う際の注意点と落とし穴をご紹介します。
詳細は回答を確認
メッセージが期待通りに送信されない場合は、レスポンスに以下のようなものがないかチェックする。 エラーコード が返された。そうすれば、次に何をすべきか、より詳しくわかるでしょう。
エラー14:無効な署名
送信されるテキストに次のような特殊文字が含まれている場合 & (アンパサンド)または = (equals)の場合、署名を作成するためのテキストでこれらを置き換える必要がある。
これを行うには、以下の手順を使用する:
- テキストに以下の内容が含まれていることを確認する。
&または=. - を使用したテキストのバージョンを作成する。
_(アンダースコア)をこれらの特殊文字の代わりに使用する。 - 署名を作成するには、テキストのサニタイズ・バージョンを使用する。
元のテキストはそのまま送受信でき、文字の置き換えは署名を生成するためだけに必要である。