[GELÖST] RSA-AES-Verschlüsselungslib funktioniert nicht

  • 4 Antworten
  • Neuester Beitrag
Diskutiere [GELÖST] RSA-AES-Verschlüsselungslib funktioniert nicht im Android App Entwicklung im Bereich Betriebssysteme & Apps.
Linux4ever

Linux4ever

Fortgeschrittenes Mitglied
Hallo liebe "Mitentwickler",

ich habe mir eine kleine Verschlüsselungsbibliothek geschrieben, jedoch funktioniert sie nicht, wie sie sollte. Wenn ich einen String eingebe, wird dieser nicht mehr korrekt entschlüsselt, nach vorheriger Verschlüsselung...

Code:
Code:
public class Encryption
{
    public static final String ALGORITHM_ASY = "RSA";
    public static final String ALGORITHM_SY = "AES";
    public static final String PREFS_NAME = "hashes";
    
    public static Encrypted encrypt(Context context, String deviceId, String message)
    {
        String[] result = {"", ""};
        
        SecretKey secKey = generateRandomKey();
        PublicKey pubKey = getContactsPublicKey(context, deviceId);
        
        String encryptedMessage = encryptMessage(secKey, message);
        String encryptedKey = encryptSymetricKey(secKey, pubKey);
        
        result[1] = encryptedMessage;
        result[0] = encryptedKey;
        
        Encrypted encResult = new Encrypted(result);
        
        return encResult;
    }
    
    public static String decrypt(Context context, String key, String message)
    {
        PrivateKey priKey = getPrivateKey(context);
        SecretKey secKey = decryptSymetricKey(key, priKey);
        
        String decryptedMessage = decryptMessage(context, secKey, message);
        
        return decryptedMessage;
    }
    
    @SuppressLint("TrulyRandom")
    public static String encryptMessage(SecretKey key, String text)
    {
        byte[] encrypted = null;
        try
        {
            Cipher cipher = Cipher.getInstance(ALGORITHM_SY);
            cipher.init(Cipher.ENCRYPT_MODE, key);  
            encrypted = cipher.doFinal(text.getBytes());
        }
        catch (IllegalBlockSizeException e)
        {
            e.printStackTrace();
        }
        catch (BadPaddingException e)
        {
            e.printStackTrace();
        }
        catch (InvalidKeyException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
        }
        
        return Base64.encodeToString(encrypted, Base64.DEFAULT);
    }
    
    public static String decryptMessage(Context context, SecretKey key, String secretText)
    {        
        byte[] encoded = Base64.decode(secretText, Base64.DEFAULT);
        byte[] text = null;
        try
        {
            Cipher cipher = Cipher.getInstance(ALGORITHM_SY);
            cipher.init(Cipher.DECRYPT_MODE, key);
            text = cipher.doFinal(encoded);
        }
        catch (IllegalBlockSizeException e)
        {
            e.printStackTrace();
        }
        catch (BadPaddingException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
        }
        catch (InvalidKeyException e)
        {
            e.printStackTrace();
        }
        
        return text.toString();
    }
    
    public static String encryptSymetricKey(SecretKey key, PublicKey pubKey)
    {
        byte[] encryptedAesKey = null;
        try
        {
            Cipher cipher = Cipher.getInstance(ALGORITHM_ASY);
            cipher.init(Cipher.WRAP_MODE, pubKey);
            encryptedAesKey = cipher.wrap(key);
        }
        catch (InvalidKeyException e)
        {
            e.printStackTrace();
        }
        catch (IllegalBlockSizeException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
        }
        
        return Base64.encodeToString(encryptedAesKey, Base64.DEFAULT);
    }
    
    public static SecretKey decryptSymetricKey(String key, PrivateKey privateKey)
    {
        byte[] encoded = Base64.decode(key, Base64.DEFAULT);
        
        Key encodedKey = null;
        try
        {
            Cipher cipher = Cipher.getInstance(ALGORITHM_ASY);
            cipher.init(Cipher.UNWRAP_MODE, privateKey);
            encodedKey = cipher.unwrap(encoded, ALGORITHM_SY, Cipher.SECRET_KEY);
        }
        catch (InvalidKeyException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e)
        {
            e.printStackTrace();
        }
        
        return (SecretKey) encodedKey;
    }
    
    public static String getPublicKeyString(Context context)
    {
        return Base64.encodeToString(new X509EncodedKeySpec(getPublicKey(context).getEncoded()).getEncoded(), Base64.DEFAULT);
    }
    
    public static PublicKey getContactsPublicKey(Context context, String deviceId)
    {
        // TODO get from database
        
        return getPublicKey(context);
    }
    
    public static PublicKey getPublicKey(Context context)
    {
        SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
        String pubKey = shared.getString("publicKey", "0");
        
        if (pubKey == null)
        {
            try
            {
                generatePair(context);
            }
            catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            
            pubKey = shared.getString("publicKey", "0");
        }
        
        byte[] encodedPublicKey = Base64.decode(pubKey, Base64.DEFAULT);
        
        PublicKey publicKey = null;
        try
        {
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_ASY);
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
            publicKey = keyFactory.generatePublic(publicKeySpec);
        }
        catch (InvalidKeySpecException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        
        return publicKey;
    }
    
    public static PrivateKey getPrivateKey(Context context)
    {
        SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
        String privKey = shared.getString("privateKey", "0");
        
        if (privKey == null)
        {
            try
            {
                generatePair(context);
            }
            catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            
            privKey = shared.getString("privateKey", "0");
        }
        
        byte[] encodedPrivateKey = Base64.decode(privKey, Base64.DEFAULT);
        
        PrivateKey privateKey = null;
        try
        {
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_ASY);
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
            privateKey = keyFactory.generatePrivate(privateKeySpec);
        }
        catch (InvalidKeySpecException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        
        return privateKey;
    }
    
    @SuppressLint("TrulyRandom")
    public static void generatePair(Context context) throws NoSuchAlgorithmException
    {
        final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM_ASY);
        keyGen.initialize(2048);
        final KeyPair key = keyGen.generateKeyPair();
        
        PrivateKey privateKey = key.getPrivate();
        PublicKey publicKey = key.getPublic();
        
        String privKey = Base64.encodeToString(new PKCS8EncodedKeySpec(privateKey.getEncoded()).getEncoded(), Base64.DEFAULT);
        String pubKey = Base64.encodeToString(new X509EncodedKeySpec(publicKey.getEncoded()).getEncoded(), Base64.DEFAULT);
        
        SharedPreferences shared = context.getSharedPreferences(PREFS_NAME, 0);
        SharedPreferences.Editor editor = shared.edit();
        editor.putString("publicKey", pubKey);
        editor.putString("privateKey", privKey);
        editor.commit();
    }
    
    public static SecretKey generateRandomKey()
    {
        SecretKey key = null;
        
        try
        {
            KeyGenerator keygen = KeyGenerator.getInstance(ALGORITHM_SY);
            SecureRandom random = new SecureRandom();
            keygen.init(random);
            key = keygen.generateKey();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        
        return key;
    }
}

class Encrypted
{
    String encryptedKey;
    String encryptedMessage;
    
    public Encrypted()
    {
        this.encryptedKey = "";
        this.encryptedMessage = "";
    }
    
    public Encrypted(String[] result)
    {
        this.encryptedKey = result[0];
        this.encryptedMessage = result[1];
    }
    
    public String getEncryptedMessage()
    {
        return this.encryptedMessage;
    }
    
    public String getEncryptedKey()
    {
        return this.encryptedKey;
    }
}
Aufruf ist so:

Code:
Encrypted result = Encryption.encrypt(context, "12345", comment); // TestID, es wird ja mein PublicKey zurückgeliefert
String comment2 = Encryption.decrypt(context, result.getEncryptedKey(), result.getEncryptedMessage());  

==> comment != cooment2
Vielen Dank schon mal für die Hilfe! Ich hoffe, jemand findet den Fehler :thumbup:

L4E

EDIT: Ergebnis bei einer Entschlüsselung von "Test": [B@41000878

Der ursprüngliche Beitrag von 16:59 Uhr wurde um 17:33 Uhr ergänzt:

Hab den Fehler! War nachdem ich nach [B@ gegooglet habe, recht leicht. Ich Depp, sorry für den Aufwand!

Die Lösung ist folgende:

In
Code:
public static String decryptMessage(Context context, SecretKey key, String secretText)
macht man natürlich aus einem Byte-Array so:
Code:
return new String(text);
einen String und nicht so:

Code:
return text.toString();
 
Zuletzt bearbeitet:
markus.tullius

markus.tullius

Experte
Bevor du den Code einsetzt, solltest du ihn noch mal überarbeiten. Du solltest eine aktuellere Verschlüsselung wie
RSA/ECB/PKCS1Padding
RSA/ECB/OAEPWithSHA-1AndMGF1Padding
RSA/ECB/OAEPWithSHA-256AndMGF1Padding
benutzten

Ich würde auch die Anzahl der Methoden die public und static sind verringeren. Zwei reichen:

Code:
public String encrypt(String key, String text) {
   ....
}
// und

public String decrypt(String key, String text) {
   ....
}
Viel Code und viele Schnittstellen erhöhen die Möglichkeit von Fehler in der Implementierung.
 
DieGoldeneMitte

DieGoldeneMitte

Experte
OT Neugierfrage: Wieso empfiehlst du ECB? Sollte man ECB nicht eigentlich meiden?
 
markus.tullius

markus.tullius

Experte
Frage Oracle, das sind die aktuellen RSA Verschlüsselungen für Cipher. ;)

Besser ist natürlich eine OpenPGP Library für Android. (z.B. https://github.com/guardianproject/gnupg-for-android). Oder man benutzt eine symmetrische Verschlüsselung, da ist Cipher wesentlich besser aufgestellt.