1

データを暗号化できますが、復号化すると次のエラーが発生します。

エラー

HTTP Status 500 - Request processing failed; nested exception is javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

ここに私の暗号化と復号化コードがあります

//secret key 8 
    private static String strkey ="Blowfish";

更新しました

 //encrypt using blowfish algorithm
    public static byte[] encrypt(String Data)throws Exception{

        SecretKeySpec key = new SecretKeySpec(strkey.getBytes("UTF8"), "Blowfish");
         Cipher cipher = Cipher.getInstance("Blowfish");
         cipher.init(Cipher.ENCRYPT_MODE, key);

         return (cipher.doFinal(Data.getBytes("UTF8")));

    }

    //decrypt using blow fish algorithm
    public static String decrypt(byte[] encryptedData)throws Exception{
         SecretKeySpec key = new SecretKeySpec(strkey.getBytes("UTF8"), "Blowfish");
         Cipher cipher = Cipher.getInstance("Blowfish");
         cipher.init(Cipher.DECRYPT_MODE, key);
         byte[] decrypted = cipher.doFinal(encryptedData);
         return new String(decrypted); 

    }
4

3 に答える 3

5

メイン メソッドで暗号化および復号化メソッドを実行すると、機能します。しかし、encrypt の結果が url に入れられ、url パラメーターが復号化されると、失敗します。

暗号化後、バイト配列には URL の文字セット外 (ASCII 以外) の値が含まれるため、この値は URL に詰め込まれるときにエンコードされます。そして、復号化のために破損したバージョンを受け取ります。

例として、暗号化されたバイト配列から文字列を作成するとこのようŽ¹Qêz¦になりましたが、URL に入れるとŽ%0B¹Qêz¦.

他のコメントで提案されているように、修正はエンコード/デコードステップを追加することです。暗号化後、値は ASCII 文字を含む形式にエンコードする必要があります。Base 64 は優れた選択肢です。したがって、URL で暗号化およびエンコードされた値を返します。パラメータを受け取ったら、まずデコードしてから復号化すると、元のデータが得られます。

導入にあたっての注意点をまとめました。

  1. コモンズ コーデックのようなライブラリを使用します。これは私の武器です。このクラスは特にhttp://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Base64.htmlです。

  2. 暗号化と復号化を行うクラスには、 の共有インスタンスがありBase64ます。インスタンス化するにはnew Base64(true);、これを使用して URL セーフ文字列を生成します。

  3. 暗号化および復号化メソッドの署名は、バイト配列ではなく、文字列を受け入れて返す必要があります。

  4. したがって、暗号化の最後の行は次のようになります。URL で暗号return base64.encodeToString(cipher.doFinal(Data.getBytes("UTF8")));化された値を安全に渡すことができるようになりました

  5. 復号化では、最初のステップは復号化です。したがって、最初の行は次のようになりますbyte[] encryptedData = base64.decodeBase64(encrypted);

私はちょうどあなたのコードを取り、いくつかのベース 64 のものを追加しました。結果は次のようになります:

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;


public class Test {

    private static String strkey ="Blowfish";
    private static Base64 base64 = new Base64(true);

     //encrypt using blowfish algorithm
    public static String encrypt(String Data)throws Exception{

        SecretKeySpec key = new SecretKeySpec(strkey.getBytes("UTF8"), "Blowfish");
         Cipher cipher = Cipher.getInstance("Blowfish");
         cipher.init(Cipher.ENCRYPT_MODE, key);

         return base64.encodeToString(cipher.doFinal(Data.getBytes("UTF8")));

    }

    //decrypt using blow fish algorithm
    public static String decrypt(String encrypted)throws Exception{
        byte[] encryptedData = base64.decodeBase64(encrypted);
         SecretKeySpec key = new SecretKeySpec(strkey.getBytes("UTF8"), "Blowfish");
         Cipher cipher = Cipher.getInstance("Blowfish");
         cipher.init(Cipher.DECRYPT_MODE, key);
         byte[] decrypted = cipher.doFinal(encryptedData);
         return new String(decrypted); 

    }

    public static void main(String[] args) throws Exception {
        String data = "will this work?";
        String encoded = encrypt(data);
        System.out.println(encoded);
        String decoded = decrypt(encoded);
        System.out.println(decoded);
    }
}

これがあなたの質問に答えることを願っています。

于 2013-04-29T13:29:12.203 に答える
2

You can't create a String out of random (in this case encrypted) bytes like you're doing in the last line of your encrypt method - you need to create a Base64 encoded string instead (which you then need to decode back to a byte array in the decrypt method). Alternatively, just have your encrypt method return a byte array and have your decrypt method accept a byte array as its parameter.

于 2013-04-28T03:12:28.607 に答える
1

The problem is with the way you are creating String instances out of the raw encrypted byte[] data. You need to either use binhex encoding like that provided by javax.xml.bind.DatatypeConverter via the parseHexBinary and printHexBinary methods or base 64 using the parseBase64Binary and printBase64Binary methods of the same object.

One other word of advice, never rely on the default mode and padding, always be explicit. Use something like Cipher.getInstance("Blowfish/CBC/PKCS5Padding") depending on what your needs are.

于 2013-04-28T03:14:55.037 に答える