1
0

x-line-signatureの署名検証についての備忘

Last updated at Posted at 2024-08-17

背景

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 のランタイムに直接組み込まれている。これにより、パフォーマンスの向上やシステムレベルの機能へのアクセスが可能になる。

代表的なネイティブモジュール

  1. fs (File System)
  2. http
  3. path
  4. crypto
  5. buffer
  6. os
  7. child_process
  8. stream

(参考情報)

crypto-jsというnpmパッケージもあるがこちらも今後はメンテナンス予定なしのよう。
以下を見ると暗号に対してMath.random()が安全でない...のようなことが記載にある。

image.png

ちなみに、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')
        };
    };
};

以上、備忘まででした。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0