3

調査のためにElGamalを使用してテキストファイルを暗号化および復号化しようとしていますが、正しく機能させることができなかったようです。1kbから1mbの範囲のテキストファイルのグループがあり、キーサイズに512ビットを使用しています。RSAと同様に、ELGamalはモジュラスを超える値を暗号化できないことをすでに知っているので、最初の解決策として、暗号化できるように各ファイルをチャンク(モジュラスよりも小さい)に分割することにしました。幸いなことに、これらのソリューションは暗号化に使用できます。私の問題はこれです、私がそれを解読しようとしたとき、生成された出力は私が期待している実際の出力ではありません。問題の原因がわからないので、数日以内に解決策を見つける必要があります。

わかりやすくするために、コードスニペットの一部を紹介します。

私は次のようにキーペアを生成しました

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ElGamal", "BC";
keyGen.initialize(512);

電話で暗号化する

public static void encryptFile(String srcFileName, String destFileName, PublicKey key) throws Exception
{
    encryptDecryptFile(srcFileName,destFileName, key, Cipher.ENCRYPT_MODE);
}

と私は呼び出すことによって復号化します

public static void decryptFile(String srcFileName, String destFileName, PrivateKey key) throws Exception
{
    encryptDecryptFile(srcFileName,destFileName, key, Cipher.DECRYPT_MODE);
}

これがencryptDecryptFile(..)メソッドの定義です

public static void encryptDecryptFile(String srcFileName, String destFileName, Key key, int cipherMode) throws Exception
    {
        OutputStream outputWriter = null;
        InputStream inputReader = null;
        try
        {
            Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC"");
            String textLine = null;
    //buffer(my chunks) depends wether it is encyption or decryption
            byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[64]);
            int bufl;
            // init the Cipher object for Encryption...
            cipher.init(cipherMode, key);

            // start FileIO
            outputWriter = new FileOutputStream(destFileName);
            inputReader = new FileInputStream(srcFileName);
            while ( (bufl = inputReader.read(buf)) != -1)
            {
                byte[] encText = null;
                if (cipherMode == Cipher.ENCRYPT_MODE)
                {
                      encText = encrypt(copyBytes(buf,bufl),(PublicKey)key);
                }
                else
                {
                    if (_log.isDebugEnabled())
                    {
                        System.out.println("buf = " + new String(buf));
                    }
                    encText = decrypt(copyBytes(buf,bufl),(PrivateKey)key);
                }
                outputWriter.write(encText);
                if (_log.isDebugEnabled())
                {
                    System.out.println("encText = " + new String(encText));
                }
            }
            outputWriter.flush();

        }
        catch (Exception e)
        {
            _log.error(e,e);
            throw e;
        }
        finally
        {
            try
            {
                if (outputWriter != null)
                {
                    outputWriter.close();
                }
                if (inputReader != null)
                {
                    inputReader.close();
                }
            }
            catch (Exception e)
            {
                // do nothing...
            } // end of inner try, catch (Exception)...
        }
    }

copyBytesの場合:

public static byte[] copyBytes(byte[] arr, int length)
{
    byte[] newArr = null;
    if (arr.length == length)
    {
        newArr = arr;
    }
    else
    {
        newArr = new byte[length];
        for (int i = 0; i < length; i++)
        {
            newArr[i] = (byte) arr[i];
        }
    }
    return newArr;
}

encypt(...)の場合

    public static byte[] encrypt(byte[] text, PublicKey key) throws Exception
{
    byte[] cipherText = null;
    try
    {

        Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC"");
        if (_log.isDebugEnabled())
        {
            _log.debug("\nProvider is: " + cipher.getProvider().getInfo());
            _log.debug("\nStart encryption with public key");
        }

        // encrypt the plaintext using the public key
        cipher.init(Cipher.ENCRYPT_MODE, key);
        cipherText = cipher.doFinal(text);
    }
    catch (Exception e)
    {
        _log.error(e, e);
        throw e;
    }
    return cipherText;
}

と復号化(..)

   public static byte[] decrypt(byte[] text, PrivateKey key) throws Exception
    {
        byte[] dectyptedText = null;
        try
        {
            // decrypt the text using the private key
            Cipher cipher = Cipher.getInstance("ElGamal/None/NoPadding", "BC"");
              cipher.init(Cipher.DECRYPT_MODE, key);
            dectyptedText = cipher.doFinal(text);
        }
        catch (Exception e)
        {
            _log.error(e, e);
            throw e;
        }
        return dectyptedText;

    }

AviranMondoによる元のコード

必要なのはそれだけだと思います。完全なソースコードを見たいかどうか教えてください。ありがとう、

4

2 に答える 2

3

これはコードとはあまり関係がありませんが、固定幅のブロックサイズのブロック暗号を、入力をブロックに分割して暗号化するだけでストリームで機能するブロック暗号に変換しようとすることは、暗号的に安全ではありません。それらのそれぞれ。これを行うと、基本的に、各「文字」が1ブロック幅である栄光のモノアルファベット換字式暗号を実行することになります。これにより、攻撃者は入力の構造の一部を回復でき、これらの暗号化プリミティブから通常得られる保証が台無しになります。例として、この特定の暗号化モードに関するウィキペディアの説明を参照し、Linuxペンギンのタックスを暗号化する方法を確認してください。暗号化された画像により、入力の構造をすぐに確認できます。

ElGamalのようなブロック暗号を使用してテキストのストリームを暗号化する場合は、暗号ブロック連鎖(CBC)カウンターモード(CTR)などのより複雑な構造を使用する必要があります。これらは、妥当なサイズの入力に対して暗号的に安全であることが証明されています。これらのモードのいずれかを使用した場合、攻撃者はセキュリティを破ろうとするのに非常に苦労します。

あなたのコードについてこれ以上実質的なことを言うことがないことをお詫びしますが、これをデバッグする前に、強力な暗号システムをバックアップして選択する価値があると正直に思います。そうしないと、巧妙な攻撃者が失敗する可能性のあるシステムになってしまいます。

于 2011-02-04T05:39:22.243 に答える
2

私はついに解決策を手に入れました。とにかく、誰かが私と同じ問題を抱えている場合に備えて、ここにそれを置きます。あなたがしなければならないのは交換することだけです

byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[64]);

encodeDecryptFile(..)メソッドで

byte[] buf = (cipherMode == Cipher.ENCRYPT_MODE? new byte[50] : new byte[128]);

キーサイズが512のElGamalは、50bを暗号化すると128bを生成するためです。これが十分に明確であることを願っています。

于 2011-02-08T05:37:56.407 に答える