Es gibt einen Server, der Passwort auf C# verschlüsseln (Methode verschlüsselnCSharp), Android App erhält verschlüsseltes Passwort, Salz, PassPhrase und InitVector. Ich muss dieses Passwort in Java entschlüsseln. Server-guy hat mir eine Verschlüsselungsmethode in C# geschickt und ich muss encryptJava und decryptJava Methoden erstellen, die in Java genauso funktionieren wie in C#. Um PasswordDeriveBytes
zu erstellen, die in Java abwesend sind, verwende ich ein Beispiel von hier Encryption Diff Between Java and C#Verschlüsselung/Entschlüsselung zwischen C# und Java
Also, meine Frage ist, was ist los mit meinen Java-Methoden? Beide haben nicht funktioniert
Update: Ich machte einige Änderungen in Schnipsel und jetzt funktioniert alles !!
rufe ich, dass Methoden:
String encryptedText = encryptJava("12345", "100", "@.erf.net34", "@[email protected]");//it works!!
String decryptedText = decryptJava(encryptedText, "100", "@.erf.net34", "@[email protected]");//it doesn't work!!
Hier sind Java-Methoden, die ich verwenden und C# Methode vom Server.
C# (was ich nicht ändern kann)
public static String encryptCSharp(String plainText, String saltValue, String passPhrase, String initVector) {
String hashAlgorithm = "SHA1";
int passwordIterations = 1;
int keySize = 256;
// Convert strings into byte arrays.
// Let us assume that strings only contain ASCII codes.
// If strings include Unicode characters, use Unicode, UTF7, or UTF8
// encoding.
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
// Convert our plaintext into a byte array.
// Let us assume that plaintext contains UTF8-encoded characters.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
// First, we must create a password, from which the key will be derived.
// This password will be generated from the specified passphrase and
// salt value. The password will be created using the specified hash
// algorithm. Password creation can be done in several iterations.
PasswordDeriveBytes password = new PasswordDeriveBytes(
passPhrase,
saltValueBytes,
hashAlgorithm,
passwordIterations);
// Use the password to generate pseudo-random bytes for the encryption
// key. Specify the size of the key in bytes (instead of bits).
byte[] keyBytes = password.GetBytes(keySize/8);
// Create uninitialized Rijndael encryption object.
RijndaelManaged symmetricKey = new RijndaelManaged();
// It is reasonable to set encryption mode to Cipher Block Chaining
// (CBC). Use default options for other symmetric key parameters.
symmetricKey.Mode = CipherMode.CBC;
// Generate encryptor from the existing key bytes and initialization
// vector. Key size will be defined based on the number of the key
// bytes.
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
keyBytes,
initVectorBytes);
// Define memory stream which will be used to hold encrypted data.
MemoryStream memoryStream = new MemoryStream();
// Define cryptographic stream (always use Write mode for encryption).
CryptoStream cryptoStream = new CryptoStream(memoryStream,
encryptor,
CryptoStreamMode.Write);
// Start encrypting.
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
// Finish encrypting.
cryptoStream.FlushFinalBlock();
// Convert our encrypted data from a memory stream into a byte array.
byte[] cipherTextBytes = memoryStream.ToArray();
// Close both streams.
memoryStream.Close();
cryptoStream.Close();
// Convert encrypted data into a base64-encoded string.
String cipherText = Convert.ToBase64String(cipherTextBytes);
// Return encrypted string.
return cipherText;
}
Java Nachricht verschlüsseln, es funktioniert und ich habe das gleiche Ergebnis wie Methode in C#
private String encryptJava(String plainText, String saltValue, String passPhrase, String initVector) {//working!!!
String result = "";
byte[] initVectorBytes = initVector.getBytes(US_ASCII);
byte[] saltValueBytes = saltValue.getBytes(US_ASCII);
byte[] plainTextBytes = plainText.getBytes(UTF_8);
Cipher cipher;
try {
final com.gmail.example.PasswordDeriveBytes password = new com.gmail.example.PasswordDeriveBytes(passPhrase, saltValueBytes);
final byte[] keyBytes = password.getBytes(256/Byte.SIZE);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(initVectorBytes));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
final byte[] ct = cipher.doFinal(plainTextBytes);
result = Base64.encodeToString(ct, Base64.DEFAULT);//**added this line!**
//result = new String(ct, "US-ASCII");**-- deleted this line!**
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return result;
}
Java-Methode, die die emulieren gleiche Methode in C#
public class PasswordDeriveBytes {
private final MessageDigest hash;
private final byte[] firstToLastDigest;
private final byte[] outputBuffer;
private int position = 0;
public PasswordDeriveBytes(String password, byte[] salt) {
try {
this.hash = MessageDigest.getInstance("SHA-1");
this.hash.update(password.getBytes(UTF_8));
this.hash.update(salt);
this.firstToLastDigest = this.hash.digest();
final int iterations = 1;//**changed from 100**
for (int i = 1; i < iterations - 1; i++) {
hash.update(firstToLastDigest);
hash.digest(firstToLastDigest, 0, firstToLastDigest.length);
}
this.outputBuffer = hash.digest(firstToLastDigest);
} catch (NoSuchAlgorithmException | DigestException e) {
throw new IllegalStateException("SHA-1 digest should always be available", e);
}
}
public byte[] getBytes(int requested) {
if (requested < 1) {
throw new IllegalArgumentException(
"You should at least request 1 byte");
}
byte[] result = new byte[requested];
int generated = 0;
try {
while (generated < requested) {
final int outputOffset = position % outputBuffer.length;
if (outputOffset == 0 && position != 0) {
final String counter = String.valueOf(position/outputBuffer.length);
hash.update(counter.getBytes(US_ASCII));
hash.update(firstToLastDigest);
hash.digest(outputBuffer, 0, outputBuffer.length);
}
final int left = outputBuffer.length - outputOffset;
final int required = requested - generated;
final int copy = Math.min(left, required);
System.arraycopy(outputBuffer, outputOffset, result, generated, copy);
generated += copy;
position += copy;
}
} catch (final DigestException e) {
throw new IllegalStateException(e);
}
return result;
}
}
und schließlich Java-Methode, die nicht funktioniert und versuchen zu und erstand, was ich falsch gemacht
private String decryptJava(String encryptedText, String saltValue, String passPhrase, String initVector) {
String result = "";
byte[] initVectorBytes = initVector.getBytes(US_ASCII);
byte[] saltValueBytes = saltValue.getBytes(US_ASCII);
byte[] encryptedTexttBytes = Base64.decode(encryptedText, Base64.DEFAULT);
Cipher cipher;
try {
final PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, saltValueBytes);
final byte[] keyBytes = password.getBytes(256/Byte.SIZE);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try {
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(initVectorBytes));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
final byte[] ct = cipher.doFinal(encryptedTexttBytes);
//result = Base64.encodeToString(ct, Base64.DEFAULT); - **deleted this line**
try {
result = new String(ct, "US-ASCII");//** added this line**
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return result;
}
Ich bin nicht in Kryptographie erfahren, also versuche ich, Ihre Antwort zu verstehen. Meinst du, dass der Typ, der mit Microsoft Server arbeitet, die Methode von 'PasswordDeriveBytes' auf' Rfc2898DeriveBytes' umstellen muss? – LumisD
Ja, das wäre sicherlich ratsam. 'PasswordDeriveBytes' wurde von' Rfc2898DeriveBytes' ersetzt. Soweit ich weiß, hat niemand den erweiterten Algorithmus, den der frühere verwendet, vollständig beschrieben (er enthält wahrscheinlich einige schreckliche Pufferüberläufe). –