Java >> Java チュートリアル >  >> Tag >> String

Javaで文字列を暗号化する方法

私が必要とするのは、2D バーコード (PDF-417) に表示される文字列を暗号化することです。そのため、誰かがスキャンするアイデアを思いついたときに、何も読み取れなくなります。

その他の要件:

  • 複雑であってはなりません
  • RSA、PKI インフラストラクチャ、鍵ペアなどで構成しないでください。

のぞき見る人を排除できるほどシンプルで、そのデータの取得に関心のある他の企業が簡単に解読できる必要があります。彼らは私たちに電話をかけ、私たちは彼らに標準を伝えるか、復号化に使用できるいくつかの簡単なキーを提供します.

おそらく、これらの企業は異なるテクノロジーを使用する可能性があるため、特定のプラットフォームやテクノロジーに縛られていない標準に固執することをお勧めします。

何を指示してるんですか? encrypt() を実行する Java クラスはありますか &decrypt() 高いセキュリティ基準を達成するのにそれほど複雑なことはありませんか?

答え

これは Google 経由で表示される最初のページであり、すべての実装のセキュリティ脆弱性にうんざりしているので、他の人のために暗号化に関する情報を追加するためにこれを投稿して 7 年 経っています。 元の投稿から。 修士号を持っています コンピューター エンジニアリングの学士号を取得し、暗号化の研究と学習に多くの時間を費やしたので、インターネットをより安全な場所にするために 2 セントを投じています。

また、特定の状況では多くの実装が安全である可能性があることに注意してください。特別な理由がない限り、利用できる最も強力なツールを使用してください。全体として、ライブラリを使用し、可能であれば核心的な詳細には近づかないことを強くお勧めします。

2018 年 4 月 5 日更新: いくつかの部分をより簡単に理解できるように書き直し、推奨ライブラリを Jasypt から Google の新しいライブラリ Tink に変更しました。既存のセットアップから Jasypt を完全に削除することをお勧めします。

序文

以下では、安全な対称暗号化の基本を概説し、標準の Java ライブラリを使用して独自に暗号化を実装するときにオンラインで見られるよくある間違いを指摘します。すべての詳細をスキップしたい場合は、Google の新しいライブラリ Tink をプロジェクトにインポートし、すべての暗号化に AES-GCM モードを使用すれば安全です。

Java で暗号化する方法の詳細を知りたい場合は、続きを読んでください 🙂

ブロック暗号

まず、対称鍵ブロック暗号を選択する必要があります。ブロック暗号は、疑似ランダム性を作成するために使用されるコンピューター機能/プログラムです。疑似ランダム性は、量子コンピューター以外のコンピューターがそれと実際のランダム性との違いを見分けることができない偽のランダム性です。ブロック暗号は、暗号化のビルディング ブロックのようなものであり、さまざまなモードまたはスキームで使用すると、暗号化を作成できます。

現在利用可能なブロック暗号アルゴリズムについては、決してしないでください。 、繰り返します 決して DES を使用してください。3DES は絶対に使用しないでください。 Snowden の NSA リリースでさえ、可能な限り疑似ランダムに真に近いことを確認できた唯一のブロック暗号は AES 256 です。AES 128 も存在します。違いは、AES 256 は 256 ビット ブロックで動作するのに対し、AES 128 は 128 ブロックで動作することです。全体として、AES 128 は安全であると考えられていますが、いくつかの弱点が発見されていますが、256 はそれが得られるほどしっかりしています.

楽しい事実 DES は、NSA が最初に設立されたときに破られ、実際には数年間秘密にされていました。 3DES が安全であると主張する人もいまだにいますが、3DES の弱点を発見して分析した研究論文はかなりの数あります。

暗号化モード

ブロック暗号を使用して特定のスキームを使用すると、暗号化が作成され、ランダム性がキーと組み合わされて、キーを知っている限り元に戻すことができるものになります。これは暗号化モードと呼ばれます。

暗号化モードと ECB として知られる最も単純なモードの例を次に示します。これにより、何が起こっているかを視覚的に理解できるようになります:

オンラインで最もよく目にする暗号化モードは次のとおりです。

ECB CTR、CBC、GCM

リストされているモード以外にも他のモードが存在し、研究者は既存の問題を改善するために常に新しいモードに取り組んでいます.

それでは、実装と安全なものに移りましょう。 決して ECB を使用すると、有名な Linux ペンギンが示すように、繰り返しデータを隠すのが苦手です。

Java で実装する場合、次のコードを使用すると、デフォルトで ECB モードが設定されることに注意してください:

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

… 危険、これは脆弱性です! 残念ながら、これは StackOverflow 全体とオンラインのチュートリアルと例で見られます。

ノンスと IV

ECB モードで見つかった問題に対応して、IV とも呼ばれる nounce が作成されました。新しい確率変数を生成し、それをすべての暗号化に付加して、同じ 2 つのメッセージを暗号化すると、異なる結果になるようにするという考え方です。この背後にある美しさは、IV またはノンスが公の知識であることです。つまり、攻撃者はこれにアクセスできますが、あなたのキーを持っていない限り、その知識で何もできません.

私が目にする一般的な問題は、コード内の同じ固定値と同じように、IV を静的な値として設定することです。これが IV の落とし穴です。IV を繰り返すと、暗号化のセキュリティ全体が実際に危険にさらされます。

ランダム IV の生成

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

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

クリック率の実装

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」を暗号化すると、暗号化されたメッセージは「eu23ng」のようになり、攻撃者は 1 ビットを「eu53ng」に変更し、メッセージを復号化すると突然「Sell 900」と表示されます。

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

複雑なため、GCM の実装は避けたいと思います。 Google の新しいライブラリ Tink を使用することをお勧めします。これは、IV を誤って繰り返してしまうと、GCM の場合のキーが危険にさらされることになり、これは究極のセキュリティ上の欠陥です。新しい研究者は、IV を繰り返しても鍵が危険にさらされない IV 繰り返し防止暗号化モードに向けて取り組んでいますが、これはまだ主流にはなっていません。

GCM を実装したい場合は、素晴らしい GCM 実装へのリンクを次に示します。ただし、セキュリティを確保できないか、適切に実装されているかどうかはわかりませんが、基盤がダウンします。また、GCM にはパディングがないことに注意してください。

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

鍵とパスワード

もう 1 つの非常に重要な注意点は、暗号化に関して言えば、キーとパスワードは同じものではないということです。暗号化の鍵は、安全であると見なされるために、一定量のエントロピーとランダム性を備えている必要があります。これが、適切な暗号化ライブラリを使用してキーを生成する必要がある理由です。

したがって、ここで実際に実行できる実装は 2 つあります。1 つ目は、この StackOverflow スレッドにあるコードをランダム キー生成に使用することです。このソリューションでは、安全な乱数ジェネレーターを使用して、使用できるキーをゼロから作成します。

もう 1 つの安全性の低いオプションは、パスワードなどのユーザー入力を使用することです。議論した問題は、パスワードに十分なエントロピーがないことです。そのため、パスワードを取得して強化するアルゴリズムである PBKDF2 を使用する必要があります。これは、私が気に入った StackOverflow の実装です。ただし、Google Tink ライブラリにはこれらすべてが組み込まれているため、これを利用する必要があります。

Android デベロッパー

ここで指摘すべき重要な点の 1 つは、Android コードはリバース エンジニアリング可能であり、ほとんどの場合、ほとんどの Java コードもリバース エンジニアリング可能であることを知っていることです。つまり、パスワードをコードにプレーンテキストで保存する場合です。ハッカーは簡単にそれを取得できます。通常、これらのタイプの暗号化には、非対称暗号化などを使用します。これはこの投稿の範囲外なので、深く掘り下げることは避けます。

2013 年の興味深い読み物:Android での Crypto 実装の 88% が不適切に行われたことを指摘しています。

最終的な考え

繰り返しになりますが、暗号用の Java ライブラリを直接実装することは避け、Google Tink を使用することをお勧めします。Google Tink はすべてのアルゴリズムを適切に実装するという優れた仕事をしているため、頭痛の種から解放されます。その場合でも、Tink github で提起された問題、あちこちでポップアップする脆弱性を確認してください。

ご質問やご意見がございましたら、お気軽にコメントしてください!セキュリティは常に変化しており、それに遅れずについていくために最善を尽くす必要があります 🙂


Java タグ