AES с ключом Base64 шифрования в Android - PullRequest
1 голос
/ 07 февраля 2012

Я делаю приложение для Android, в котором я должен зашифровать пароли, которые я беру у пользователя, и отправить их на мой движок приложений. Я хочу использовать технику AES с ключом Base64. Я новичок в шифровании / дешифровании, поэтому я использовал код, заданный в этом вопросе . Я сменил ключ и заменил его своим. Это мой код:

public String encrypt(String dataToEncrypt)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        // I'm using AES encription

        if (!dataToEncrypt.equals("")) {
            String key = "rEqrHrhdd9I1sg==";

            Cipher c = Cipher.getInstance("AES");
            SecretKeySpec k;
            try {
                k = new SecretKeySpec(key.getBytes(), "AES");
                c.init(Cipher.ENCRYPT_MODE, k);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return new String(c.doFinal(Base64.decode(dataToEncrypt, 0)));
        }
        return "";
    }

Но иногда я получаю сообщение об ошибке «java.lang.IllegalArgumentException: bad base-64», когда я пытаюсь зашифровать определенные строки, например, «asdasdasd» выдает эту ошибку при шифровании. Может кто-нибудь подскажите пожалуйста в чем проблема ??
-Спасибо заранее

Ответы [ 4 ]

3 голосов
/ 10 февраля 2012

Попробуйте это в качестве примера того, как использовать строки для ключей и сообщений.По крайней мере, он использует правильную (символьную) кодировку, использует режим CBC и заполнение PKCS5 / 7.Обратите внимание, что существует много проблем с отправкой паролей в зашифрованном виде на сервер.Как правило, безопасность должна быть достигнута с использованием SSL для конфиденциальности и bcrypt или PBKDF2 на сервере (но это снова и снова рассматривается в стеке потока).

Обратите внимание, что приведенный ниже код не обеспечивает проверки целостности или подлинность.

public static String encrypt(final String plainMessage,
        final String symKeyHex) {
    final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);

    final byte[] encodedMessage = plainMessage.getBytes(Charset
            .forName("UTF-8"));
    try {
        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final int blockSize = cipher.getBlockSize();

        // create the key
        final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

        // generate random IV using block size (possibly create a method for
        // this)
        final byte[] ivData = new byte[blockSize];
        final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
        rnd.nextBytes(ivData);
        final IvParameterSpec iv = new IvParameterSpec(ivData);

        cipher.init(Cipher.ENCRYPT_MODE, symKey, iv);

        final byte[] encryptedMessage = cipher.doFinal(encodedMessage);

        // concatenate IV and encrypted message
        final byte[] ivAndEncryptedMessage = new byte[ivData.length
                + encryptedMessage.length];
        System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
        System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage,
                blockSize, encryptedMessage.length);

        final String ivAndEncryptedMessageBase64 = DatatypeConverter
                .printBase64Binary(ivAndEncryptedMessage);

        return ivAndEncryptedMessageBase64;
    } catch (InvalidKeyException e) {
        throw new IllegalArgumentException(
                "key argument does not contain a valid AES key");
    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(
                "Unexpected exception during encryption", e);
    }
}

public static String decrypt(final String ivAndEncryptedMessageBase64,
        final String symKeyHex) {
    final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);

    final byte[] ivAndEncryptedMessage = DatatypeConverter
            .parseBase64Binary(ivAndEncryptedMessageBase64);
    try {
        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final int blockSize = cipher.getBlockSize();

        // create the key
        final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

        // retrieve random IV from start of the received message
        final byte[] ivData = new byte[blockSize];
        System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize);
        final IvParameterSpec iv = new IvParameterSpec(ivData);

        // retrieve the encrypted message itself
        final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length
                - blockSize];
        System.arraycopy(ivAndEncryptedMessage, blockSize,
                encryptedMessage, 0, encryptedMessage.length);

        cipher.init(Cipher.DECRYPT_MODE, symKey, iv);

        final byte[] encodedMessage = cipher.doFinal(encryptedMessage);

        // concatenate IV and encrypted message
        final String message = new String(encodedMessage,
                Charset.forName("UTF-8"));

        return message;
    } catch (InvalidKeyException e) {
        throw new IllegalArgumentException(
                "key argument does not contain a valid AES key");
    } catch (BadPaddingException e) {
        // you'd better know about padding oracle attacks
        return null;
    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(
                "Unexpected exception during decryption", e);
    }
}
0 голосов
/ 12 марта 2014

Привет, я переписываю пример Java-методов owlstead без DatatypeConverter и с использованием Apache Commons.

public static String encrypt(final String plainMessage,
        final String symKeyHex) {


    try {

    final byte[] symKeyData = Hex.decodeHex(symKeyHex.toCharArray());

    final byte[] encodedMessage = plainMessage.getBytes(Charset.forName("UTF-8"));

        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final int blockSize = cipher.getBlockSize();

        // create the key
        final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

        // generate random IV using block size (possibly create a method for
        // this)
        final byte[] ivData = new byte[blockSize];
        final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
        rnd.nextBytes(ivData);
        final IvParameterSpec iv = new IvParameterSpec(ivData);

        cipher.init(Cipher.ENCRYPT_MODE, symKey, iv);

        final byte[] encryptedMessage = cipher.doFinal(encodedMessage);

        // concatenate IV and encrypted message
        final byte[] ivAndEncryptedMessage = new byte[ivData.length
                + encryptedMessage.length];
        System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
        System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage,
                blockSize, encryptedMessage.length);

        final String ivAndEncryptedMessageBase64 = Base64.encodeBase64String(ivAndEncryptedMessage);

        return ivAndEncryptedMessageBase64;
    } catch (InvalidKeyException e) {
        throw new IllegalArgumentException(
                "key argument does not contain a valid AES key");
    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(
                "Unexpected exception during encryption", e);
    } catch (DecoderException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "";

}

public static String decrypt(final String ivAndEncryptedMessageBase64,
        final String symKeyHex) {

    try {
        final byte[] symKeyData = Hex.decodeHex(symKeyHex.toCharArray());
        final byte[] ivAndEncryptedMessage = Base64.decodeBase64(ivAndEncryptedMessageBase64);


        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final int blockSize = cipher.getBlockSize();

        // create the key
        final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

        // retrieve random IV from start of the received message
        final byte[] ivData = new byte[blockSize];
        System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize);
        final IvParameterSpec iv = new IvParameterSpec(ivData);

        // retrieve the encrypted message itself
        final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length
                - blockSize];
        System.arraycopy(ivAndEncryptedMessage, blockSize,
                encryptedMessage, 0, encryptedMessage.length);

        cipher.init(Cipher.DECRYPT_MODE, symKey, iv);

        final byte[] encodedMessage = cipher.doFinal(encryptedMessage);

        // concatenate IV and encrypted message
        final String message = new String(encodedMessage,
                Charset.forName("UTF-8"));

        return message;
    } catch (InvalidKeyException e) {
        throw new IllegalArgumentException(
                "key argument does not contain a valid AES key");
    } catch (BadPaddingException e) {
        // you'd better know about padding oracle attacks
        return null;
    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(
                "Unexpected exception during decryption", e);
    } catch (DecoderException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "";
}

Вы даже не можете использовать это на Android, потому что у вас могут быть проблемы с Base64 Class. На Android вы можете использовать следующие методы, которые используют класс Android Base64:

public static String encrypt(final String plainMessage,
                             final String symKeyHex) {


    try {

        final byte[] symKeyData = Hex.decodeHex(symKeyHex.toCharArray());

        final byte[] encodedMessage = plainMessage.getBytes(Charset.forName("UTF-8"));

        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final int blockSize = cipher.getBlockSize();

        // create the key
        final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

        // generate random IV using block size (possibly create a method for
        // this)
        final byte[] ivData = new byte[blockSize];
        final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
        rnd.nextBytes(ivData);
        final IvParameterSpec iv = new IvParameterSpec(ivData);

        cipher.init(Cipher.ENCRYPT_MODE, symKey, iv);

        final byte[] encryptedMessage = cipher.doFinal(encodedMessage);

        // concatenate IV and encrypted message
        final byte[] ivAndEncryptedMessage = new byte[ivData.length
                + encryptedMessage.length];
        System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
        System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage,
                blockSize, encryptedMessage.length);

        //final String ivAndEncryptedMessageBase64 = Base64.encodeBase64String(ivAndEncryptedMessage);
        final String ivAndEncryptedMessageBase64 = Base64.encodeToString(ivAndEncryptedMessage,Base64.DEFAULT);

        return ivAndEncryptedMessageBase64;
    } catch (InvalidKeyException e) {
        throw new IllegalArgumentException(
                "key argument does not contain a valid AES key");
    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(
                "Unexpected exception during encryption", e);
    } catch (DecoderException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "";

}

public static String decrypt(final String ivAndEncryptedMessageBase64,
                             final String symKeyHex) {


    try {

        final byte[] symKeyData = Hex.decodeHex(symKeyHex.toCharArray());
        //final byte[] ivAndEncryptedMessage = Base64.decodeBase64(ivAndEncryptedMessageBase64);
        final byte[] ivAndEncryptedMessage = Base64.decode(ivAndEncryptedMessageBase64,Base64.DEFAULT);

        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        final int blockSize = cipher.getBlockSize();

        // create the key
        final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

        // retrieve random IV from start of the received message
        final byte[] ivData = new byte[blockSize];
        System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize);
        final IvParameterSpec iv = new IvParameterSpec(ivData);

        // retrieve the encrypted message itself
        final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length
                - blockSize];
        System.arraycopy(ivAndEncryptedMessage, blockSize,
                encryptedMessage, 0, encryptedMessage.length);

        cipher.init(Cipher.DECRYPT_MODE, symKey, iv);

        final byte[] encodedMessage = cipher.doFinal(encryptedMessage);

        // concatenate IV and encrypted message
        final String message = new String(encodedMessage,
                Charset.forName("UTF-8"));

        return message;
    } catch (InvalidKeyException e) {
        throw new IllegalArgumentException(
                "key argument does not contain a valid AES key");
    } catch (BadPaddingException e) {
        // you'd better know about padding oracle attacks
        return null;
    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(
                "Unexpected exception during decryption", e);
    } catch (DecoderException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return "";
}

Надеюсь, это поможет!

0 голосов
/ 24 ноября 2013

Посмотрите на мой ответ здесь Шифрование базы данных Android . Он содержит 2 файла, которые вы можете включить в любое из ваших приложений, которые требуют хранения данных для шифрования. Существует реализованный метод, который облегчает преобразование данных байтового массива в печатные данные Base64 и наоборот. Использовал алгоритм AES с режимом шифрования Cipher Block Chaining (CBC) и заполнением PKCS # 5.

0 голосов
/ 07 февраля 2012

simplecrypto.java

     import java.security.SecureRandom;
     import javax.crypto.Cipher;
     import javax.crypto.KeyGenerator;
     import javax.crypto.SecretKey;
     import javax.crypto.spec.SecretKeySpec;

     public class SimpleCrypto {

public  String encrypt(String seed, String cleartext) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
}

public  String decrypt(String seed, String encrypted) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
}

//done
private  byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
    kgen.init(128, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
}


private  byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
}

private  byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
}

public  String toHex(String txt) {
        return toHex(txt.getBytes());
}
public  String fromHex(String hex) {
        return new String(toByte(hex));
}

public  byte[] toByte(String hexString) {
        int len = hexString.length()/2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
                result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
        return result;
}

public  String toHex(byte[] buf) {
        if (buf == null)
                return "";
        StringBuffer result = new StringBuffer(2*buf.length);
        for (int i = 0; i < buf.length; i++) {
                appendHex(result, buf[i]);
        }
        return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private  void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}

  }

и в действии введите следующий код:

SimpleCrypto simpleCrypto = new SimpleCrypto();
    String s = "";
    try {
        s = simpleCrypto.encrypt("abc", "xyz");
    } catch (Exception e) {
        e.printStackTrace();
    }

abc - это текст для шифрования, а xyz - ключ для шифрования

...