データを暗号化するための次のプログラムがあります。
import Java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.Apache.commons.codec.binary.Base64;
public class Test {
private static final String ALGORITHM = "AES";
private static final byte[] keyValue = "ADBSJHJS12547896".getBytes();
public static void main(String args[]) throws Exception {
String encriptValue = encrypt("dude5");
decrypt(encriptValue);
}
/**
* @param args
* @throws Exception
*/
public static String encrypt(String valueToEnc) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
System.out.println("valueToEnc.getBytes().length "+valueToEnc.getBytes().length);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
System.out.println("encValue length" + encValue.length);
byte[] encryptedByteValue = new Base64().encode(encValue);
String encryptedValue = encryptedByteValue.toString();
System.out.println("encryptedValue " + encryptedValue);
return encryptedValue;
}
public static String decrypt(String encryptedValue) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] enctVal = c.doFinal(encryptedValue.getBytes());
System.out.println("enctVal length " + enctVal.length);
byte[] decordedValue = new Base64().decode(enctVal);
return decordedValue.toString();
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
return key;
}
}
ここで私は例外を除いて次の出力を取得していますか?
valueToEnc.getBytes().length 5
encValue length16
encryptedValue [B@aa9835
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.Sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.Sun.crypto.provider.SunJCE_f.b(DashoA13*..)
誰かが原因を説明できますか?その長さを復号化するときの唯一の言い方は16です。doFinalメソッドで暗号化するように、16に変換しませんか。
そして例外として「パディング暗号なしで復号化する方法は?」
暗号化の注文:getBytes、encrypt、encode、toString
decrypt(Wrong *)の注文:getBytes、decrypt、decode、toString
2つの問題:
注:また、generateKey()
を2回呼び出す必要はありません。
問題1を修正復号化の逆順を使用します。
復号化の正しい順序:getBytes、decode、decrypt、toString
問題を修正#2xxx.toString()
をnew String(xxx)
に置き換えることにより。暗号化機能と復号化機能の両方でこれを行います。
復号化は次のようになります:
c.init(Cipher.DECRYPT_MODE, key)
val decodedValue = new Base64().decode(encryptedValue.getBytes())
val decryptedVal = c.doFinal(decodedValue)
return new String(decryptedVal)
これにより、「dude5」が返されます。
この線
_String encryptedValue = encryptedByteValue.toString();
_
問題です。 encryptedByteValueのタイプはbyte []であり、その上でtoStringを呼び出すことは、そこで行うことではありません。代わりに試してください
_String encryptedValue = Base64.getEncoder().encodeToString(encValue);
_
次に、復号化でBase64.decodeBase64(encryptedValue)
を使用します。ただし、復号化を試みる前にそれを行う必要があります。暗号化方式の逆の順序で操作を元に戻す必要があります。
EncodeToStringまたはencodeBase64Stringを持つApacheコーデックのバージョンはどこで入手しますか?
Apacheサイトから1.5をダウンロードしましたが、ドキュメントにはこれらのメソッドが存在すると書かれていますが、コード補完を行うと表示されず、提供時に未知のメソッドが作成されます。
私はできました:
byte raw[] = md.digest(); //step 4
byte hashBytes[] = Base64.encodeBase64(raw); //step 5
StringBuffer buffer = new StringBuffer();
for( int i=0; i<hashBytes.length; i++ )
buffer.append(hashBytes[i]);
return buffer.toString(); //step 6
そして、私が取得した文字列は非常に長かったが、正しく解読された。
私はこれが物事を行うための「正しい」方法だとは思わないが、ドキュメンテーションがそこにあると言う方法を見つけることができない。
基本的に、暗号化機能と復号化機能には非対称性があります。暗号化するときはAES暗号化を実行し、次にbase64エンコードを実行します。解読するときは、最初にbase64エンコードステップを元に戻しません。
[
がbase64エンコード文字列に表示されないように、base64エンコードに何か問題があると思います。
org.Apache.commons.codec.binary.Base64
のドキュメントを見ると、エンコード時にこれを実行できるはずです。
String encryptedValue = Base64.encodeBase64String(encValue);
デコード時にこれ:
byte[] encValue = Base64.decodeBase64(encryptedValue);
私は例の行を置き換えています:
String encryptedValue = encryptedByteValue.toString();
次のものと:
String encryptedValue = new String(encryptedByteValue);
すべてうまくいきます!
大丈夫でした
1)toString()はここで必要なものを返さないため、toString()の代わりに新しい文字列を使用します(どちらの場合も暗号化と復号化)
2)値はbase64でエンコードされるため、最初にデコードする必要があります。
私はこのスレッドに出くわしましたが、実際のポイントを見つけるのに時間がかかりました。この問題に出くわした他の人々にコードを投稿しています。
public abstract class EncryptionDecryption {
static byte[] key = "!@#$!@#$%^&**&^%".getBytes();
final static String algorithm="AES";
public static String encrypt(String data){
byte[] dataToSend = data.getBytes();
Cipher c = null;
try {
c = Cipher.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SecretKeySpec k = new SecretKeySpec(key, algorithm);
try {
c.init(Cipher.ENCRYPT_MODE, k);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] encryptedData = "".getBytes();
try {
encryptedData = c.doFinal(dataToSend);
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] encryptedByteValue = new Base64().encode(encryptedData);
return new String(encryptedByteValue);//.toString();
}
public static String decrypt(String data){
byte[] encryptedData = new Base64().decode(data);
Cipher c = null;
try {
c = Cipher.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SecretKeySpec k =
new SecretKeySpec(key, algorithm);
try {
c.init(Cipher.DECRYPT_MODE, k);
} catch (InvalidKeyException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] decrypted = null;
try {
decrypted = c.doFinal(encryptedData);
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new String(decrypted);
}
public static void main(String[] args){
String password=EncryptionDecryption.encrypt("password123");
System.out.println(password);
System.out.println(EncryptionDecryption.decrypt(password));
}
}