1. ホーム
  2. java

[解決済み] Javaで文字列を暗号化する方法

2022-03-02 16:27:26

質問

2次元バーコード(PDF-417)に表示される文字列を暗号化し、誰かがスキャンしようとしたときに何も読み取れないようにする必要があります。

その他の要件

  • 複雑であってはならない
  • RSA、PKIインフラ、キーペアなどで構成されるべきではない。

また、データを入手しようとする他の企業にとっても、簡単に復号化できるものでなければなりません。そして、そのデータを入手しようとする他の企業にとっても、簡単に解読できるものでなければなりません。

おそらく、それらの企業はさまざまな技術を使用する可能性があるので、特別なプラットフォームや技術に縛られない標準にこだわるのは良いことです。

何かいい方法はないでしょうか?Javaクラスで encrypt() & を使用します。 decrypt() 高いセキュリティ基準を達成するために、あまり複雑なことは考えずに?

どのように解決するのか?

<ブロッククオート

これは、Google経由で最初に表示されるページで、セキュリティの すべての実装にある脆弱性にはぞっとさせられます。 暗号化について、他の人のために情報を追加するために投稿します。 されている 7年 元の投稿から を保有しています。 修士号 で コンピュータ工学を専攻し、多くの時間を費やして勉強してきました。 インターネットをより良いものにするために、私は2つのセントを投じます。 より安全な場所です。

また、多くの実装がある種の安全であることに注意してください。 しかし、なぜそのようなものを使って、偶然に失敗する可能性があるのか。 を間違えないようにしましょう。特に理由がない限り、最強のツールを使ってください。 を使用しない特別な理由があります。全体として、私はライブラリを使用することを強くお勧めします。 できれば、細かい部分には手を出さない。

UPDATE 4/5/18: わかりやすくするために一部書き直し、推奨ライブラリーを ジャスラック から Googleの新ライブラリTink を完全に削除することをお勧めします。 Jasypt を既存のセットアップから削除してください。

序文

以下、安全な共通鍵暗号の基本を概説し、標準的なJavaライブラリを用いて独自に暗号を実装する際に私がネット上で目にする一般的な誤りを指摘します。もし、すべての詳細を読み飛ばしたい場合は、以下のサイトをご覧ください。 Googleの新ライブラリTink それをプロジェクトにインポートして、すべての暗号化にAES-GCMモードを使用すれば安全です。

さて、Javaで暗号化する方法について詳しく知りたい方は、こちらをお読みください :)

ブロック暗号

まず最初に、対称鍵ブロック暗号を選択する必要があります。ブロック暗号とは、擬似乱数を作り出すために使われるコンピュータの関数/プログラムです。疑似乱数とは、量子コンピュータ以外のコンピュータでは本物の乱数との区別がつかないような偽の乱数のことです。ブロック暗号は暗号の構成要素のようなもので、異なるモードやスキームで使用することにより、暗号を作り出すことができる。

現在利用可能なブロック暗号アルゴリズムについて、以下のことを確認してください。 NEVER 繰り返しになりますが 決して 使用 DES は絶対に使わないでください。 3DES(スリーディエス . スノーデン氏のNSAのリリースでさえ、本当に疑似ランダムに近いと確認できた唯一のブロック暗号は AES 256 . AES128もありますが、AES256は256ビットブロック、AES128は128ブロックで動作する点が異なります。AES128は弱点が発見されたものの安全性が高いとされているが、256はそれに匹敵するほど強固なものである。

楽しい事実 DES は、設立当初にNSAによって破られ、実は数年間秘密にされていた。しかし、一部の人々は今でも 3DES(スリーディーエス は安全ですが、その弱点を発見し分析した研究論文はかなり多くあります。 3DES .

暗号化モード

暗号化とは、ブロック暗号に特定の方式を採用し、ランダム性と鍵を組み合わせることで、鍵さえ知っていれば可逆性を持つものを作ることです。これを暗号化モードと呼ぶ。

ここでは、暗号化モードの例と、ECBと呼ばれる最もシンプルなモードの例を示します。

ネット上でよく見かける暗号化モードは以下の通りです。

ecb ctr, cbc, gcm

ここに挙げた以外にもモードは存在し、研究者は常に既存の問題を改善するために新しいモードの開発に取り組んでいる。

では、次に実装について、何が安全かについて説明します。 NEVER ECBを使用することで、繰り返しのデータを隠すことができます。 リナックスペンギン .

Javaで実装する場合、以下のコードを使用すると、ECBモードがデフォルトで設定されてしまうので注意が必要です。

Cipher cipher = Cipher.getInstance("AES");

... 危険 これは脆弱性です! で、残念ながら、これはStackOverflowやオンラインのチュートリアルや例の至る所で見受けられます。

ノンセスとIV

ECBモードで見つかった問題に対応するため、IVと呼ばれる名詞が作られました。これは、新しいランダムな変数を生成し、それをすべての暗号化に付加することで、同じメッセージを暗号化したときに、異なる結果が得られるようにするというものです。この仕組みの優れた点は、IVやnonceが公知であることです。つまり、攻撃者はこの情報にアクセスすることができますが、彼らがあなたの鍵を持っていない限り、その知識を使って何かをすることはできません。

よくある問題は、IVを静的な値、つまり同じ固定値としてコードに設定することです。そしてここにIVの落とし穴があり、1つを繰り返した瞬間に暗号化のセキュリティ全体が損なわれます。

ランダムIVの生成

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);

SHA1は壊れていますが、SHA256をこのユースケースに適切に実装する方法を見つけることができませんでした。また、SHA1攻撃は、巨大なクラスタ上でクラックするのに数年かかるので、まだ型破りです。 詳しくはこちらでご確認ください。

CTRの導入

CTRモードでは、パディングは必要ありません。

 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

CBCの実装

CBCモードを実装する場合は、以下のようにPKCS7Paddingを使用してください。

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

CBCとCTRの脆弱性とGCMを使用すべき理由

CBCやCTRなどの他のモードは安全ですが、攻撃者が暗号化されたデータを反転させ、復号化したときの値を変えることができるという問題があります。例えば、ある銀行のメッセージ「Sell 100」を暗号化した場合、暗号化されたメッセージは次のように表示されます。

これを避けるために、インターネットの大部分はGCMを使用しており、HTTPSを見るたびに、彼らはおそらくGCMを使用しています。GCM は暗号化されたメッセージにハッシュで署名し、この署名を用いてメッセージが変更されて いないことを確認します。

GCMは複雑なので、私は実装を避けたいと思います。それよりも グーグルの新ライブラリ Tink なぜなら、ここでもまた、誤ってIVを繰り返してしまうと、GCMの場合、鍵を危険にさらすことになり、これは究極のセキュリティ上の欠陥だからです。新しい研究者は、IVを繰り返しても鍵が危険にさらされないようなIV繰り返し耐性暗号化モードの開発に取り組んでいますが、これはまだ主流にはなっていません。

さて、もしGCMを実装したいのであれば、次のようなものがあります。 GCMの優れた実装へのリンク . しかし、私はそのセキュリティや適切に実装されているかどうかを保証することはできませんが、これは基本を押さえています。また、GCMではパディングがないことに注意してください。

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

キーとパスワード

もうひとつ重要なことは、暗号技術において、鍵とパスワードは同じものではないということです。暗号技術における鍵は、ある程度のエントロピーとランダム性がないと安全とは言えません。このため、適切な暗号ライブラリを使用して鍵を生成する必要があります。

つまり、ここでできる実装は2つあります。 ランダムキー生成に関するStackOverflowのスレッドです。 . このソリューションでは、安全な乱数生成器を使用して、ゼロからキーを作成し、それを使用することができます。

もうひとつの安全性の低い選択肢は、パスワードのようなユーザー入力を利用することです。この場合、パスワードには十分なエントロピーがないことが問題になります。 PBKDF2 これは、パスワードを受け取り、それを強化するアルゴリズムです。以下は 私が気に入ったStackOverflowの実装 . しかし、Google Tink ライブラリには、これらすべてが組み込まれているので、それを利用するのがよいでしょう。

Android開発者

ここで一つ重要なのは、アンドロイドのコードはリバースエンジニアリングが可能であり、ほとんどの場合、Javaのコードもそうだということです。つまり、パスワードをプレーンテキストでコードに保存した場合、そのパスワードはリバースエンジニアリング可能であるということです。ハッカーは簡単にそれを取得することができます。通常、これらのタイプの暗号化には、非対称暗号などを使用したい。これはこの記事の範囲外なので、私はそれに飛び込むことを避けるでしょう。

2013年の興味深い読み物 : Android における暗号化実装の 88% が不適切であったことを指摘。

最終的な感想

繰り返しになりますが、crypto 用の java ライブラリを直接実装することは避け、次のような方法で実装することをお勧めします。 Google Tink 彼らはすべてのアルゴリズムを適切に実装しているので、頭痛の種を減らすことができます。その場合でも、Tinkのgithubで提起された問題をチェックするようにしてください。

ご質問やご意見がありましたら、お気軽にコメントください。 セキュリティは常に変化しているので、それについていくためにベストを尽くす必要があります :)