Sie haben nicht viele Informationen über Ihre Benutzung Fall zur Verfügung gestellt, aber ich würde sagen, dass dies geschieht, weil Sie nicht sind Verwenden der gleichen Verschlüsselungseinstellungen während der Verschlüsselungs- und Entschlüsselungsvorgänge. Symmetrische Chiffren erfordern, dass Sie bei der Datenverschlüsselung und -entschlüsselung genau die gleichen Einstellungen/Parameter verwenden. Zum Beispiel für AES CBC müssen Sie genau den gleichen Schlüssel, IV, Chiffriermodus und Padding auf beiden Geräten verwenden. Am besten ist es diese Einstellung explizit im Code zu setzen:
System.Security.Cryptography.RijndaelManaged aes = new System.Security.Cryptography.RijndaelManaged();
aes.Key = new byte[] { ... };
aes.IV = new byte[] { ... };
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
Wenn Sie sicher, dass Sie die gleichen Einstellungen verwenden, dann sollten Sie auch Szenario berücksichtigen, dass einige Daten beschädigt werden oder während der Netzwerkübertragung verändert.
bearbeiten, nachdem einige Codefragmente zur Verfügung gestellt wurden:
Decryption Methode, die Sie zur Verfügung gestellt haben ist für mich nicht funktioniert überhaupt so habe ich zusammen alle Proben und verwandelte sie in den Code, der das Gleiche tut wie Ihre, aber verwendet IMO ein etwas sauberer Ansatz. Zum Beispiel verwendet dieser Code eine robustere "Schlüsselableitung" (bitte verzeiht mir kryptoguys) und hat auch eine grundlegende Codeanalyse bestanden.
sollten Sie in der Lage sein, leicht öffentliche Methoden zu verwenden, um zu tun, was Sie brauchen:
string plainData = "This information should be encrypted";
string encryptedData = EncryptStringified(plainData);
string decryptedData = DecryptStringified(encryptedData);
if (plainData != decryptedData)
throw new Exception("Decryption failed");
Implementierung und private Methoden folgen:
/// <summary>
/// Encrypts string with the key derived from device ID
/// </summary>
/// <returns>Base64 encoded encrypted data</returns>
/// <param name="stringToEncrypt">String to encrypt</param>
public string EncryptStringified(string stringToEncrypt)
{
if (stringToEncrypt == null)
throw new ArgumentNullException("stringToEncrypt");
byte[] key = DeviceIdToDesKey();
byte[] plainData = Encoding.UTF8.GetBytes(stringToEncrypt);
byte[] encryptedData = Encrypt(key, plainData);
return Convert.ToBase64String(encryptedData);
}
/// <summary>
/// Decrypts Base64 encoded data with the key derived from device ID
/// </summary>
/// <returns>Decrypted string</returns>
/// <param name="b64DataToDecrypt">Base64 encoded data to decrypt</param>
public string DecryptStringified(string b64DataToDecrypt)
{
if (b64DataToDecrypt == null)
throw new ArgumentNullException("b64DataToDecrypt");
byte[] key = DeviceIdToDesKey();
byte[] encryptedData = Convert.FromBase64String(b64DataToDecrypt);
byte[] decryptedData = Decrypt(key, encryptedData);
return Encoding.UTF8.GetString(decryptedData);
}
private byte[] DeviceIdToDesKey()
{
TelephonyManager telephonyMgr = Application.Context.GetSystemService(Context.TelephonyService) as TelephonyManager;
string deviceId = telephonyMgr.DeviceId ?? "UNAVAILABLE";
// Compute hash of device ID so we are sure enough bytes have been gathered for the key
byte[] bytes = null;
using (SHA1 sha1 = SHA1.Create())
bytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(deviceId));
// Get last 8 bytes from device ID hash as a key
byte[] desKey = new byte[8];
Array.Copy(bytes, bytes.Length - desKey.Length, desKey, 0, desKey.Length);
return desKey;
}
private byte[] Encrypt(byte[] key, byte[] plainData)
{
if (key == null)
throw new ArgumentNullException("key");
if (plainData == null)
throw new ArgumentNullException("plainData");
using (DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider())
{
if (!desProvider.ValidKeySize(key.Length * 8))
throw new CryptographicException("Key with invalid size has been specified");
desProvider.Key = key;
// desProvider.IV should be automatically filled with random bytes when DESCryptoServiceProvider instance is created
desProvider.Mode = CipherMode.CBC;
desProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream encryptedStream = new MemoryStream())
{
// Write IV at the beginning of memory stream
encryptedStream.Write(desProvider.IV, 0, desProvider.IV.Length);
// Perform encryption and append encrypted data to the memory stream
using (ICryptoTransform encryptor = desProvider.CreateEncryptor())
{
byte[] encryptedData = encryptor.TransformFinalBlock(plainData, 0, plainData.Length);
encryptedStream.Write(encryptedData, 0, encryptedData.Length);
}
return encryptedStream.ToArray();
}
}
}
private byte[] Decrypt(byte[] key, byte[] encryptedData)
{
if (key == null)
throw new ArgumentNullException("key");
if (encryptedData == null)
throw new ArgumentNullException("encryptedData");
using (DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider())
{
if (!desProvider.ValidKeySize(key.Length * 8))
throw new CryptographicException("Key with invalid size has been specified");
desProvider.Key = key;
if (encryptedData.Length <= desProvider.IV.Length)
throw new CryptographicException("Too short encrypted data has been specified");
// Read IV from the beginning of encrypted data
// Note: New byte array needs to be created because data written to desprovider.IV are ignored
byte[] iv = new byte[desProvider.IV.Length];
Array.Copy(encryptedData, 0, iv, 0, iv.Length);
desProvider.IV = iv;
desProvider.Mode = CipherMode.CBC;
desProvider.Padding = PaddingMode.PKCS7;
// Remove IV from the beginning of encrypted data and perform decryption
using (ICryptoTransform decryptor = desProvider.CreateDecryptor())
return decryptor.TransformFinalBlock(encryptedData, desProvider.IV.Length, encryptedData.Length - desProvider.IV.Length);
}
}
Es ist wirklich schwer zu sagen, was genau war Problem mit Ihr Code, weil Ihre Entschlüsselungsmethode überhaupt nicht funktioniert hat - wahrscheinlich weil CryptoStream im Schreibmodus für die Entschlüsselung verwendet wird, was mir etwas merkwürdig vorkommt.
So viel für den Code. Kommen wir zur Verschlüsselung, die wirklich sehr schwach ist. Es ist nur eine Verschleierung, die die Daten davor schützen soll, versehentlich in Klartextform angezeigt zu werden (manche Leute benutzen die BASE64-Kodierung für dasselbe). Der Hauptgrund dafür ist ein relativ alter Verschlüsselungsalgorithmus und ein leicht vorhersagbarer Verschlüsselungsschlüssel. AFAIK Jede Anwendung, die auf demselben Gerät ausgeführt wird, kann die Geräte-ID ohne Berechtigungen lesen. Das bedeutet, dass jede Anwendung Ihre Daten entschlüsseln kann. Natürlich ist Ihre SQLite-Datenbank wahrscheinlich nur für Ihre Anwendung zugänglich, aber das kann nicht mehr wahr sein, wenn Sie die SD-Karte entfernen oder Ihr Telefon rooten.Um dies ein wenig besser zu machen, könnten Sie beispielsweise den Benutzer bitten, ein Passwort anzugeben und dann einen eindeutigen Verschlüsselungsschlüssel abzuleiten, aber das ist ein völlig anderes Problem. Ich bin mir jedoch nicht wirklich sicher, was Sie mit dieser Verschlüsselung erreichen wollen - es kann für Ihre Bedürfnisse völlig ausreichen, auch wenn es als schwach angesehen werden kann.
Hoffe, das hilft.
Welche Blockchiffre und Betriebsart? Können Sie eine Kopie der Nachricht bereitstellen, die nicht entschlüsselt werden konnte? 147 scheint wie eine ungerade Länge. Es * normalerweise * sollte ein Vielfaches der Blockchiffrierung sein (oft 16). Modi wie CTS und CTR haben diese Anforderung jedoch nicht. Geht man von einem Modus wie CBC aus, dann sieht es fast so aus, als ob eine unvollständige Nachricht verarbeitet wird. – jww
Ich habe den Code meiner ursprünglichen Frage hinzugefügt =) –
basierend auf Ihrer Bearbeitung und der Code mit DES, 147 *** ist *** falsch. Die Blockgröße von DES beträgt 8 Byte, daher muss die Nachricht ein Vielfaches von 8 Byte sein. Finden Sie die fehlenden 3 Bytes (es sollte 152 Bytes sein), und Ihr Problem ist gelöst. Außerdem sollten Sie für die verschlüsselten Daten ein 'byte []', nicht ein 'String' verwenden. Die verschlüsselten Daten könnten ein 0x00 Byte enthalten, was zu Problemen führen könnte. Oder Base64 die Daten, damit es die NULL-Bytes verarbeiten kann. – jww