密码算法使用:
1 对称加密:本地随机的密钥
方案:直接使用androidstore生成随机数,随机数做密钥
1.1 AES_CBC android 实现
函数主体:
public class AesCbcAlg{
private static final String AndroidKeyStore = "AndroidKeyStore";
private static final String AES_MODE_CBC = KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7;
private static final String KEY_ALIAS = "AESCBCKEY";//这个别名
public static byte[] cbc_iv = null;
public static byte[] Encyption(String plaintext,SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance(AES_MODE_CBC);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encodedBytes = cipher.doFinal(plaintext.getBytes());
//保存解密需要的IV变量
cbc_iv = cipher.getIV();
return encodedBytes;
}
public static byte[] Decyption(String encrypted) throws Exception {
Cipher cipher = Cipher.getInstance(AES_MODE_CBC);
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_ALIAS, null);
cipher.init(Cipher.DECRYPT_MODE, secretKey,new IvParameterSpec(cbc_iv));
byte[] decodedBytes = cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT));
return decodedBytes;
}
//上面这案例中是将IV保存到文件中,实际使用时,建议将IV保存到Data中,用于解密的时候使用,
public static SecretKey createKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, AndroidKeyStore);
keyGenerator.init(
new KeyGenParameterSpec.Builder(KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
//这里还有几个用户认证的程序需要搞定setUserAuthenticationRequired,setUserAuthenticationValidityDurationSeconds(int seconds)
return keyGenerator.generateKey();
}
}
验证函数:
public void CiperAesCbc(View view) throws Exception {
String plaintext = "123456789012345" +
"123456789012345" +
"123456789012345" +
"123456789012345";
System.out.println(LOG_CBC_TAG + "加密明文为:" + plaintext);
System.out.println(LOG_CBC_TAG + "加密模式为:CBC" );
SecretKey secretKey = AesCbcAlg.createKey();
System.out.println(LOG_CBC_TAG + "加密密钥为:" + secretKey);
byte[] encodedBytes = AesCbcAlg.Encyption(plaintext, secretKey);
String encryptedBase64Encoded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
System.out.println(LOG_CBC_TAG + "加密结果为:" + encryptedBase64Encoded);
byte[] decodedBytes = AesCbcAlg.Decyption(encryptedBase64Encoded);
System.out.println(LOG_CBC_TAG + "初始向量为:" + AesCbcAlg.cbc_iv);
System.out.println(LOG_CBC_TAG + "解密结果为:" + new String(decodedBytes, "UTF-8"));
}
1.2 AES_GCM android 实现
函数主体:
public class AesGcmAlg{
private static final String AndroidKeyStore = "AndroidKeyStore";
private static final String AES_MODE_GCM = KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
+ KeyProperties.ENCRYPTION_PADDING_NONE;
private static final String KEY_ALIAS = "AESGCMKEY";
public static byte[] gcm_iv = null;
public static byte[] Encyption(String plaintext,SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance(AES_MODE_GCM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encodedBytes = cipher.doFinal(plaintext.getBytes());
//保存解密需要的IV变量
gcm_iv = cipher.getIV();
return encodedBytes;
}
public static byte[] Decyption(String encrypted) throws Exception {
Cipher cipher = Cipher.getInstance(AES_MODE_GCM);
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_ALIAS, null);
cipher.init(Cipher.DECRYPT_MODE, secretKey,new GCMParameterSpec(128, gcm_iv));
byte[] decodedBytes = cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT));
return decodedBytes;
}
public static SecretKey createKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, AndroidKeyStore);
keyGenerator.init(
new KeyGenParameterSpec.Builder(KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
return keyGenerator.generateKey();
}
}
验证函数
public void CiperAesGcm(View view) throws Exception {
String plaintext = "123456789012345" +
"123456789012345" +
"123456789012345" +
"123456789012345";
System.out.println(LOG_GCM_TAG + "加密明文为:" + plaintext);
System.out.println(LOG_GCM_TAG + "加密模式为:GCM" );
SecretKey secretKey = AesGcmAlg.createKey();
System.out.println(LOG_GCM_TAG + "加密密钥为:" + secretKey);
byte[] encodedBytes = AesGcmAlg.Encyption(plaintext, secretKey);
String encryptedBase64Encoded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
System.out.println(LOG_GCM_TAG + "加密结果为:" + encryptedBase64Encoded);
byte[] decodedBytes = AesGcmAlg.Decyption(encryptedBase64Encoded);
System.out.println(LOG_GCM_TAG + "初始向量为:" + AesGcmAlg.gcm_iv);
System.out.println(LOG_GCM_TAG + "解密结果为:" + new String(decodedBytes, "UTF-8"));
2 非对称加密:本地随机的密钥
方案:直接使用androidKeyStore生成,密钥对,不需要考虑密钥保存方案。
2.1 函数主体
public class RsaOaepCiper{
private static final String AndroidKeyStore = "AndroidKeyStore";
private static final String RSA_MODE_OAEP = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
private static final String KEY_ALIAS = "RSACIPERKEY";
public static byte[] Encyption(String plaintext) throws Exception {
Cipher cipher = Cipher.getInstance(RSA_MODE_OAEP);
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
PublicKey publicKey = keyStore.getCertificate(KEY_ALIAS).getPublicKey();
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encodedBytes = cipher.doFinal(plaintext.getBytes());
return encodedBytes;
}
public static byte[] Decyption(String encrypted) throws Exception {
Cipher cipher = Cipher.getInstance(RSA_MODE_OAEP);
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS, null);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decodedBytes = cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT));
return decodedBytes;
}
public static KeyPair createKey() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, AndroidKeyStore);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
KEY_ALIAS,
KeyProperties.PURPOSE_DECRYPT)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.setKeySize(2048)
//默认为2048,保险期间最好加上,否则容易扯皮
.build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
}
2.2 验证函数
public void CiperRsaOaep(View view) throws Exception {
String plaintext = "123456789012345" +
"123456789012345" +
"123456789012345" +
"123456789012345";
System.out.println(LOG_RSA_OAEP_LOG + "加密明文为:" + plaintext);
System.out.println(LOG_RSA_OAEP_LOG + "加密模式为:RSAOAEP" );
KeyPair secretKey = RsaOaepCiper.createKey();
System.out.println(LOG_RSA_OAEP_LOG + "RSA公钥为:" + secretKey.getPublic());
System.out.println(LOG_RSA_OAEP_LOG + "RSA私钥为:" + secretKey.getPrivate());
byte[] encodedBytes = RsaOaepCiper.Encyption(plaintext);
String encryptedBase64Encoded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
System.out.println(LOG_RSA_OAEP_LOG + "加密结果为:" + encryptedBase64Encoded);
byte[] decodedBytes = RsaOaepCiper.Decyption(encryptedBase64Encoded);
System.out.println(LOG_RSA_OAEP_LOG + "解密结果为:" + new String(decodedBytes, "UTF-8"));
}
3 数字签名
3.1 函数主体
public class RsaSignCiper{
private static final String AndroidKeyStore = "AndroidKeyStore";
private static final String RSA_MODE_SIGN = "SHA256withRSA/PSS";
private static final String KEY_ALIAS = "RSASIGNCIPERKEY";//别名
public static byte[] SignRsa(String plaintext) throws Exception {
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
KeyStore.Entry entry = keyStore.getEntry(KEY_ALIAS, null);
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w("RSASIGN", "Not an instance of a PrivateKeyEntry");
return null;
}
Signature signature = Signature.getInstance(RSA_MODE_SIGN);
signature.initSign(((KeyStore.PrivateKeyEntry) entry).getPrivateKey());
signature.update(plaintext.getBytes());
byte[] signatureBytes = signature.sign();
return signatureBytes;
}
public static Boolean VerifyRsa(String plaintext,byte[] signatureBytes) throws Exception {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.Entry entry = keyStore.getEntry(KEY_ALIAS, null);
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w("RSASIGN", "Not an instance of a PrivateKeyEntry");
return null;
}
Signature signature = Signature.getInstance(RSA_MODE_SIGN);
signature.initVerify(((KeyStore.PrivateKeyEntry) entry).getCertificate());
signature.update(plaintext.getBytes());
boolean valid = signature.verify(signatureBytes);
return valid;
}
public static KeyPair createKey() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, AndroidKeyStore);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
KEY_ALIAS,
KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS)
.setKeySize(2048)
.build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
}
3.2 验证函数
public void CiperRsaOaep(View view) throws Exception {
String plaintext = "123456789012345" +
"123456789012345" +
"123456789012345" +
"123456789012345";
System.out.println(LOG_RSA_OAEP_LOG + "加密明文为:" + plaintext);
System.out.println(LOG_RSA_OAEP_LOG + "加密模式为:RSAOAEP" );
KeyPair secretKey = RsaOaepCiper.createKey();
System.out.println(LOG_RSA_OAEP_LOG + "RSA公钥为:" + secretKey.getPublic());
System.out.println(LOG_RSA_OAEP_LOG + "RSA私钥为:" + secretKey.getPrivate());
byte[] encodedBytes = RsaOaepCiper.Encyption(plaintext);
String encryptedBase64Encoded = Base64.encodeToString(encodedBytes, Base64.DEFAULT);
System.out.println(LOG_RSA_OAEP_LOG + "加密结果为:" + encryptedBase64Encoded);
byte[] decodedBytes = RsaOaepCiper.Decyption(encryptedBase64Encoded);
System.out.println(LOG_RSA_OAEP_LOG + "解密结果为:" + new String(decodedBytes, "UTF-8"));
}
4 MAC算法
4.1 函数主体
public class MacCiper{
private static final String AndroidKeyStore = "AndroidKeyStore";
private static final String HMACMODE = "HmacSHA256";
private static final String KEY_ALIAS = "HMACKEY";//这个非必要条件
public static byte[] ServerSign(String plaintext,SecretKey secretKey) throws Exception {
Mac mac = Mac.getInstance(HMACMODE);
mac.init(secretKey);
byte[] encodedBytes = mac.doFinal(plaintext.getBytes());
return encodedBytes;
}
public static byte[] ClientSign(String plaintext) throws Exception {
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_ALIAS, null);
Mac mac = Mac.getInstance(HMACMODE);
mac.init(secretKey);
byte[] encodedBytes = mac.doFinal(plaintext.getBytes());
return encodedBytes;
}
public static SecretKey createKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_HMAC_SHA256, AndroidKeyStore);
keyGenerator.init(
new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_SIGN).build());
SecretKey key = keyGenerator.generateKey();
return key;
}
}
4.2 验证函数
public void CiperHmac(View view) throws Exception{
String plaintext= "123456789012345" +
"123456789012345"+
"123456789012345"+
"123456789012345";
Log.v(LOG_MAC_TAG, "消息明文为:" + plaintext);
SecretKey secretKey= MacCiper.createKey();
Log.v(LOG_MAC_TAG, "MAC密钥为:" + secretKey);
byte[] encodedBytes= MacCiper.ServerSign(plaintext, secretKey);
String encryptedBase64Encoded= Base64.encodeToString(encodedBytes, Base64.DEFAULT);
Log.v(LOG_MAC_TAG, "签名结果为:" + encryptedBase64Encoded);
byte[] decodedBytes= MacCiper.ClientSign(plaintext);
Log.v(LOG_MAC_TAG, "认证结果为:" + Base64.encodeToString(encodedBytes, Base64.DEFAULT));
}
5 对称加密/非对称加密:固定密钥的保存(协商密钥)
方案:通过使用android_keystore使用RSA非对称加密算法对固定密钥进行保存,关于非对称加密的方案参考使用2.2(使用2.2的算法加密你的固定密钥,保存)