blog

金融暗号:決済システムにおける暗号化と復号化の技術を解明

決済システムにおける暗号化・復号化技術の重要な位置づけ、コアとなるアプリケーションシナリオ、安全なアルゴリズムとは何か、安全でないアルゴリズムとは何か、対応するコアコードの実装。...

Dec 23, 2023 · 8 min. read
シェア

この記事では、以下のことを学びます。

  1. 暗号化と復号化とは何か
  2. 決済システムにおける暗号化と復号化が必要な主なシナリオ
  3. 安全な暗号化と復号化アルゴリズムと安全でないアルゴリズム
  4. 一般的な暗号化と復号化アルゴリズムのコアコード
  5. 日常的な研究開発における一般的な問題

1. 暗号化と復号とは?

オンライン決済システムはデジタル経済において重要な役割を果たしています。オープンなインターネット上で安全かつ確実に送金を行うことを可能にする技術とは何でしょうか。暗号化と復号は、資金の安全な流れと個人情報のセキュリティを確保する、この段階における隠れた技術です。

デジタル通信において、暗号化とは、特定のアルゴリズムとキーを使用して、平文を解読不可能な暗号文に変換するプロセスです。 つまり、データが傍受されたとしても、権限のない第三者はその内容を理解できないということです。復号化は暗号化の逆のプロセスであり、特定のアルゴリズムとキーを使用して、暗号文を平文に変換するプロセスです。

2. 主なアプリケーションのシナリオ

非常に高度なセキュリティシステムである決済システムにおいて、暗号化および復号化技術は極めて重要な役割を果たしています。暗号化および復号化技術は通常、以下の主要なアプリケーションのシナリオで使用されます。1)通信の暗号化、2)保存データの暗号化。

一般的な実装方法は2つあります。

2) 個々のフィールドを暗号化する:例えば、カード番号やその他の重要な情報を送信する前に暗号化します。

3) メッセージ全体を暗号化する:まずビジネスメッセージを作成し、メッセージ全体を暗号化してから送信します。

  1. ストレージの暗号化:クレジットカード情報、ユーザーID情報、パスワードなどの機密データは、データ漏洩を防ぐために暗号化してデータベースに保存する必要があります。

具体的な実装は通常、次の2種類に分けられます。

1)直接暗号化:元の情報を直接暗号化します。通常、クレジットカードやIDカードなどの通常のデータの暗号化に使用されます。

2)ソルトで暗号化:元の情報はまずソルトされ、その後暗号化されます。これは通常、パスワード管理に使用されます。

3. パスワードの特別な取り扱い

パスワードの保存は少し特殊であり、別途言及する価値があります。

前述の通り、ログインまたは支払い用のパスワードはソルトされ、その後暗号化されて保存されます。 では、なぜパスワード管理にソルトを使用する必要があるのでしょうか?それは、パスワードのセキュリティを向上させるためです。
  1. レインボーテーブル攻撃を防止します。レインボーテーブルとは、攻撃者がソルトされていないパスワードを見つけ出し解読するために使用できる、事前に計算されたハッシュ値のセットです。各ユーザーにソルトを付与することで、たとえ同じパスワードが使用されていたとしても、異なるソルト値により暗号化された暗号文は異なります。
  2. 同じパスワードを使用しているユーザーを保護します。ソルトを使用しない場合、複数のユーザーが同じパスワードを使用していると、ひとつのパスワードが破られた時点で、同じパスワードを使用している他のユーザーも特定されてしまいます。各ユーザーに異なるソルトを使用することで、生成される暗号文が異なることを保証します。
  3. パスワードの解析を困難にします。特に、弱いパスワードを使用している場合、攻撃者にとって解析が非常に困難になります。

    実装の際には、ソルト戦略に注意する必要があります。

  4. ソルト値は十分長い:複雑性を高めるため、少なくとも128ビットを使用することをお勧めします。
  5. 推奨される暗号化および復号アルゴリズムの選択

    推奨されるアルゴリズムは以下の通りです。

    AES:最も広く使用されている対称暗号化アルゴリズムで、高速であり、大量のデータの高速暗号化に適しています。 鍵の長さは256以上を推奨します。RSA:広く使用されている非対称暗号化アルゴリズムで、AESよりも安全ですが、暗号化には時間がかかります。 少量のデータやデジタル署名に適しています。 鍵の長さは2048以上を推奨します。

    httpsでは、データの暗号化にはAESが使用され、AESキーはRSAによって暗号化された後に送信されます。これにより、セキュリティと暗号化速度の両方の問題が解決されます。

    現在、安全ではないと考えられ、使用が推奨されていないアルゴリズムには、以下のようなものがあります。

    DES:キーの長さが短く、安全性が十分ではありません。特に注意すべき点として、「安全だと思われる独自のアルゴリズムを考案し、それを実稼働環境に適用してはならない」という点があります。業界が推奨するこれらのアルゴリズムの安全性は、多数のデジタル専門家やコンピューター科学者によって実証されており、また業界でも継続的に検証されています。毎日無数の攻撃やハッキングが発生しており、一度でも解読される危険性があれば、すぐに知れ渡ることになります。

    暗号化キーの保存と更新

    平文データは暗号化されて保存されるため安全です。しかし、平文データを暗号化する際に使用されるキーについてはどうでしょうか?

    暗号化キーの重要性はどの程度でしょうか?これには公式があります。キーの値=暗号文の値です。例えば、暗号化して保存した暗号文の値が10億の場合、対応するキーの値も10億となります。

    鍵の管理には、鍵の保管、更新、バックアップとリカバリー、および無効化と破棄という4つの側面があります。 鍵はマスター鍵作業鍵に分けられます。作業鍵は通常の業務データの暗号化と復号に使用され、マスター鍵は作業鍵の暗号化と復号に使用されます。

    一般的に、マスター鍵は専用ハードウェアセキュリティモジュール(一般にハードウェア暗号化マシンとして知られています)に保存されるべきです。しかし、その性能は比較的限定的で、高価であり、管理も複雑です。

    作業用キーは通常、マスターキーによって暗号化され、DBに保存されます。必要に応じて、マスターキーは暗号化または復号化される前に、復号化され、メモリにキャッシュされます。

    キー更新のメカニズム:

    定期的な更新は、クラッキングのリスクを低減するために必要です。

    自動かつ定期的な更新は、人的エラーを低減するために必要です。

  6. バージョン管理とロールバック:バージョン番号を設け、迅速なロールバックを可能にしなければなりません。

鍵のバックアップとリカバリ、廃棄と破棄のメカニズム、マスター鍵と作業鍵の設計方法の詳細については、鍵センターの設計と実装の章で詳しく説明します。

共通の暗号化と復号アルゴリズムのコアコード

よく使用されるAES暗号化と復号を例に説明します。

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.spec.KeySpec;
import java.util.Base64;
import java.security.SecureRandom;
import javax.crypto.SecretKey;
public class AESWithPasswordExample {
 private static final String PASSWORD = "123456";
 private static final int ITERATION_COUNT = 65536;
 private static final int KEY_LENGTH = 256; // AES鍵長は128ビット、192ビット、256ビットのいずれかとする。
 private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
 // PBKDF2を使ってパスワードからAES鍵を導出する
 private static SecretKey getKeyFromPassword(String password) throws Exception {
 SecureRandom random = new SecureRandom();
 byte[] salt = new byte[16];
 random.nextBytes(salt); // 安全なランダムソルトの作成
 
 KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
 byte[] secretKey = factory.generateSecret(spec).getEncoded();
 return new SecretKeySpec(secretKey, "AES");
 }
 //  
 public static String encrypt(String data, SecretKey key, IvParameterSpec iv) throws Exception {
 Cipher cipher = Cipher.getInstance(ALGORITHM);
 cipher.init(Cipher.ENCRYPT_MODE, key, iv);
 byte[] encrypted = cipher.doFinal(data.getBytes("UTF-8"));
 return Base64.getEncoder().encodeToString(encrypted);
 }
 //  
 public static String decrypt(String encryptedData, SecretKey key, IvParameterSpec iv) throws Exception {
 Cipher cipher = Cipher.getInstance(ALGORITHM);
 cipher.init(Cipher.DECRYPT_MODE, key, iv);
 byte[] original = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
 return new String(original, "UTF-8");
 }
 public static void main(String[] args) throws Exception {
 String originalData = "Confidential data that needs to be encrypted and decrypted";
 
 // 鍵と初期化ベクターの生成
 SecretKey key = getKeyFromPassword(PASSWORD);
 byte[] ivBytes = new byte[16]; // AES16バイトIVの使用
 SecureRandom random = new SecureRandom();
 random.nextBytes(ivBytes);
 IvParameterSpec iv = new IvParameterSpec(ivBytes);
 
 // 暗号化データ
 String encryptedData = encrypt(originalData, key, iv);
 System.out.println("Encrypted data: " + encryptedData);
 // データの暗号化解除
 String decryptedData = decrypt(encryptedData, key, iv);
 System.out.println("Decrypted data: " + decryptedData);
 }
}

PBKDF2を使用してパスワードからAESキーを生成します。

private static SecretKey getKeyFromPassword(String password) throws Exception {

SecureRandom random = new SecureRandom();

byte[] salt = new byte[16];

random.nextBytes(salt); // 安全なランダムなソルトを作成します。

KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");

byte[] secretKey = factory.generateSecret(spec).getEncoded();

return new SecretKeySpec(secretKey, "AES");

}

// 暗号化

public static String encrypt(String data, SecretKey key, IvParameterSpec iv) throws Exception {

Cipher cipher = Cipher.getInstance(ALGORITHM);

cipher.init(Cipher.ENCRYPT_MODE, key, iv);

byte[] encrypted = cipher.doFinal(data.getBytes("UTF-8"));

return Base64.getEncoder().encodeToString(encrypted);

}

// 復号

public static String decrypt(String encryptedData, SecretKey key, IvParameterSpec iv) throws Exception {

Cipher cipher = Cipher.getInstance(ALGORITHM);

cipher.init(Cipher.DECRYPT_MODE, key, iv);

byte[] original = cipher.doFinal(Base64.getDecoder().decode(encryptedData));

return new String(original, "UTF-8");

}

public static void main(String[] args) throws Exception {

String originalData = 「暗号化および復号化が必要な機密データ」;

// キーと初期ベクトル(IV)を生成します。

SecretKey key = getKeyFromPassword(PASSWORD);

byte[] ivBytes = new byte[16]; // AESは16バイトのIVを使用します

SecureRandom random = new SecureRandom();

random.nextBytes(ivBytes);

IvParameterSpec iv = new IvParameterSpec(ivBytes);

// データを暗号化します

String encryptedData = encrypt(originalData, key, iv);

System.out.println(「暗号化されたデータ: 」 + encryptedData);

// データを復号化します。

String decryptedData = decrypt(encryptedData, key, iv);

System.out.println(「復号化されたデータ: 」 + decryptedData);

}

}

これは簡略化されたバージョンであることにご注意ください。実際には、暗号化キーの保存やソルト値の保存など、より多くのセキュリティ対策が必要です。

8. 結論

デジタル決済の世界では、暗号化と復号化は、ユーザーとプラットフォーム資産を保護する、数あるセキュリティ対策のひとつとして、決済システムのセキュリティの基盤となっています。 安全性の高い暗号化と復号化アルゴリズムと厳格な鍵管理は、決済システムのセキュリティの2つの柱です。

暗号化と復号化を含む暗号学は広大な分野であり、決済システムのセキュリティはさらに広大な分野です。 紙面の都合上、ここでは入門的な知識の一部のみを紹介していますが、日常的な決済システムの開発には十分です。

Read next

エチャート円グラフ、リングチャート、デフォルトのズーム効果をキャンセルするマウスタッチの後

プロジェクトシナリオ:ecahrtsを使用してリングダイアグラムを作成していますが、マウスが凡例に触れるとズーム効果が発生します。

Dec 10, 2023 · 2 min read