背景
LINEのMessagingAPIにてWebhookを使用する際、そのリクエストがLINEからのものであるかの検証を行うため、リクエストヘッダのx-line-signature
の署名を検証する必要がある。
公式 - 署名を検証する
https://developers.line.biz/ja/reference/messaging-api/#signature-validation
Node.jsのサンプルコードでconst crypto = require("crypto");
とあるが、npm view crypto
で見ると非推奨
bash-3.2$ npm view crypto
crypto@1.0.1 | ISC | deps: none | versions: 4
This package is no longer supported and has been deprecated. To avoid malicious use, npm is hanging on to the package name.
https://github.com/npm/deprecate-holder#readme
DEPRECATED ⚠️ - This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.
dist
.tarball: https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz
.shasum: 2af1b7cad8175d24c8a1b0778255794a21803037
.integrity: sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
maintainers:
- npm <npm@npmjs.com>
dist-tags:
latest: 1.0.1
published over a year ago by ehsalazar <ernie@npmjs.com>
どう対処するのか?
説明には下記の言及がある。
This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.
要するにNodeのネイティブパッケージとなったため、npm install
しなくてもそのままコードの中でimport
して使ってくださいということ。
なのでLINEさんの公式ドキュメント通り実装すれば問題なし。
実際に実装したコード
import crypto from 'crypto';
// X-Line-Signatureの検証
export const handler = async (event) => {
try {
// リクエストボディのダイジェストを計算
const channelSecret = process.env['SECRET_KEY']; // Channel secret string
const hmac = crypto.createHmac('sha256', channelSecret);
hmac.update(event.body);
const signature = hmac.digest('base64');
// リクエストヘッダーのx-line-signatureに含まれる署名と一致するかどうかを確認
if (signature !== event.headers['x-line-signature']) {
return {
statusCode: 401,
body: JSON.stringify('Error Request Unauthorized')
};
}
// 署名が一致した場合の処理
// 他の処理をここに追加
} catch (err) {
return {
statusCode: 500,
body: JSON.stringify('Error verifying signature')
};
}
};
ネイティブモジュールとは?
JavaScript で書かれている通常のモジュールとは異なり、C/C++ などのネイティブコードで記述されており、Node.js のランタイムに直接組み込まれている。これにより、パフォーマンスの向上やシステムレベルの機能へのアクセスが可能になる。
代表的なネイティブモジュール
- fs (File System)
- http
- path
- crypto
- buffer
- os
- child_process
- stream
(参考情報)
crypto-js
というnpmパッケージもあるがこちらも今後はメンテナンス予定なしのよう。
以下を見ると暗号に対してMath.random()
が安全でない...のようなことが記載にある。
ちなみに、crypto-jsを使って書くと下記の通り
import CryptoJS from 'crypto-js';
// X-Line-Signatureの検証
export const handler = async (event) => {
try {
// リクエストボディのダイジェストを計算
const channelSecret = process.env['SECRET_KEY']; // Channel secret string
const hash = CryptoJS.HmacSHA256(event.body, channelSecret);
const signature = CryptoJS.enc.Base64.stringify(hash);
// リクエストヘッダーのx-line-signatureに含まれる署名と一致するかどうかを確認
if (signature !== event.headers['x-line-signature']){
return {
statusCode: 401,
body: JSON.stringify('Error Request Unauthorized')
};
};
} catch (err) {
return {
statusCode: 500,
body: JSON.stringify('Error sending message to SQS')
};
};
};
以上、備忘まででした。