簡體   English   中英

Android中具有Base64密鑰加密的AES

[英]AES with Base64 key encryption in android

我正在制作一個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”在我對其進行加密時會出現此錯誤。 誰能告訴我問題出在哪里嗎?
-提前致謝

以此為例,說明如何使用字符串作為鍵和消息。 至少它使用正確的(字符)編碼,使用CBC模式和PKCS5 / 7填充。 請注意,將加密的密碼發送到服務器存在很多問題。 通常,應通過使用SSL來確保機密性並在服務器上使用bcrypt或PBKDF2來實現安全性(但是在stackoverflow上已一再提及)。

請注意,以下代碼不提供完整性檢查或真實性。

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);
    }
}

在這里查看我的答案Android數據庫加密 它包含2個文件,您可以將它們包含在任何需要加密數據存儲的應用程序中。 已實現的方法使將字節數組數據轉換為可打印的Base64數據更加容易,反之亦然。 使用具有密碼塊鏈接(CBC)加密模式和PKCS#5填充的AES算法。

嗨,我改寫了沒有DatatypeConverter和apache commons的owlstead java方法示例。

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類可能會出現一些問題。 在android上,您可以使用以下使用Base64 android類的方法:

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 "";
}

希望有幫助!

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是加密的密鑰

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM