Hallo,
erst einmal wünsche ich euch allen ein gesundes neues Jahr!
Nun zu meinem Problem. Ich muss folgende zwei Methoden aus PHP in Java umsetzten. Diese beiden Methoden dienen der Ver- und Entschlüsselung von Zeichenketten mittels Rijndael-256 im CBC Modus. Hier wird speziell ein 32stelliger Schlüssel verwendet.
//!!!! PHP Funktionen !!!!
/**
* Use this function to encrypt raw XML data (eg. your reports)
* @param $encrypt (string needed to be encrypted)
* @param $key (the secret key provided by REMIT and is 32 characters of lowercase letters and digits)
* @return encrypted string - eg. encrypted XML report
*/
function mc_encrypt($encrypt, $key){
$encrypt = serialize($encrypt);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM);
$mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
$passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
$encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
return $encoded;
}
/**
* Use this function to decrypt encrypted data (eg. encrypted XML receipts from ACER/GIE)
* @param $decrypt (string that needs to be decrypted)
* @param $key (the secret key provided by REMIT and is 32 characters of lowercase letters and digits)
* @return raw XML/string - eg. decrypted XML receipts from ACER/GIE
*/
function mc_decrypt($decrypt, $key){
$decrypt = explode('|', $decrypt.'|');
$decoded = base64_decode($decrypt[0]);
$iv = base64_decode($decrypt[1]);
if(strlen($iv)!==mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)){ return false; }
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
$mac = substr($decrypted, -64);
$decrypted = substr($decrypted, 0, -64);
$calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
if($calcmac!==$mac){ return false; }
$decrypted = unserialize($decrypted);
return $decrypted;
}
Zu Beginn wollte ich mich zunächst auf die Entschlüsselung von Nachrichten konzentrieren, da ich diese Aufgabe primär mit Java umsetzen muss.
Leider stoße ich immer wieder an die Grenzen der Crypto-Funktionen von Java und weiß nicht, wie ich diese umgehen kann. Wenn ich eine Entschlüsselung starte, erhalte ich immer folgende Fehlermeldung.
Exception in thread „main“ java.security.InvalidAlgorithmParameterException: IV must be 16 bytes long.
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(Unknown Source)
at javax.crypto.Cipher.implInit(Cipher.java:806)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at test.Test.main(Test.java:39)
Dank Google bin ich weiß ich, das im Java die Schlüssel nicht länger als 16 Zeichen im Standard sein sollen. Wenn man größere Schlüssel verwenden will/muss, dann muss man auf alternative Biblioteken ausweisen. Ich habe es mit BouncyCastle versuche. Aber auch hier kein Erfolg.
Mein QuellCode ist folgender:
package test;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import java.security.GeneralSecurityException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Test {
private static final String KEY = "2fe0213d48bb0ca63cb7a502dd7d10f5";
public static void main(String[] args) throws GeneralSecurityException {
//Nachricht im Klartext: "das ist ein Test";
String base64Msg = "QktHTUVNeUJ1M09mRXhaUGRMU20vOFlRY1d0NzI1Qy9nY0VRcGxENS80QURGcVFzT1N3QXoyOWhGRTU3ZjIydUFFYU51U2M0MlFqN2Noc3NsYUQ5ZHY5VHRGdW53dE0rQXZaZzcwdWtUMUZycnJIb2ZEYldIN1pFeW5Yb3RvLy98a3V6TWs2Y2ExRGswcHdaL1dFRFdIK0tsbURzUm5uLzErSUZ3RXBkY1o0bz0=";
byte[] oriMsg = Base64.decode(base64Msg);
System.out.println(new String(oriMsg) + "\n\n");
String[] dataParts = (new String(oriMsg)).split("\\|");
String rawIv = dataParts[1].trim();
byte[] iv = Base64.decode(rawIv);
String rawMsg = dataParts[0].trim();
byte[] msg = rawMsg.getBytes();
System.out.println(new String(iv) + "\n"+String.valueOf(iv.length)+"\n");
System.out.println(new String(msg) + "\n\n");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7Padding");
SecretKeySpec key = new SecretKeySpec(new byte[256 / Byte.SIZE],KEY);
IvParameterSpec ivPS = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivPS);
byte[] out = cipher.doFinal(msg);
System.out.println(new String(out));
}
}
Könntet ihr mir bitte weiterhelfen?
Danke!
Grüße Hans
Nachtrag:
Bevor ich Ärger bekomme, das ich hier einen privaten Schlüssel veröffentlicht habe, sage ich gleich, das dieser frei erfunden und nur für die Forumsdiskussion erstellt wurde