添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Android中的加密

Android中的加密

目录,本文主要分为两部分:

1.使用AES算法进行加密
2.使用RSA算法进行加密

在使用Encryption之前最好学习一些东西:

  • 算法类型(非对称和对称)
  • 模式和填充
  • 按键类型
  • Java密码体系结构
  • Android Key Store

1、安卓中的AES加密

AES是一种众所周知且最推荐的标准加密算法,该算法使用替换置换网络通过对称密钥对纯数据进行加密。

对称密钥是由 基于密码的密钥派生功能( PBKDF2 生成的是获取密码并用 salt 对其进行哈希处理多次,以确保生成唯一的密钥,即使不同的用户使用相同的密码也是如此。该密钥还可以使用 Android Keystore Galois / Counter Mode( GCM 用作阻止模式来生成 AES支持128、192和256位的密钥长度。

AES仅将128位数据作为一个块进行加密,要对整个消息进行加密,我们必须选择一种块模式,例如 电子密码簿(ECB) 密码块链接(CBC),计数器模式(CTR) ,其中可以对多个块进行加密到单个密文。

ECB在每个块上使用相同的未更改密钥进行加密
CBC使用先前生成的密码对新块进行加密,并对第一个块使用Initialization Vector
CTR将块密码转换为流密码,这意味着无需填充

AES加密将在API 23+以上提供

带有GCM块模式的AES加密

在这种方法中,将使用密码生成一个初始向量,随后将用于解密数据,该方法中不需要加salt。

创建密钥库:

val keyStore = KeyStore.getInstanceANDROID_KEYSTORE
keyStore.loadnull

创建对称密钥:

VAL的KeyGenerator =  的KeyGenerator .getInstance(KeyProperties。KEY_ALGORITHM_AES,ANDROID_KEYSTORE)
val keyGenParameterSpec =  KeyGenParameterSpec.Builder(
    KEY_ALIAS,
    关键属性。PURPOSE_ENCRYPT  或 KeyProperties。PURPOSE_DECRYPT)
    .setBlockModes(KeyProperties。BLOCK_MODE_GCM)
    .setEncryptionPaddings(KeyProperties。ENCRYPTION_PADDING_NONE)
    // .setUserAuthenticationRequired(true)//需要锁定屏幕,如果禁用了锁定屏幕则无效
    // .setUserAuthenticationValidityDurationSeconds(120)//仅在密码验证后的x秒内可用。
    .setRandomizedEncryptionRequired(true)//每次调用时相同明文的4种不同密文
    。建立()
keyGenerator。初始化(keyGenParameterSpec)
val secretkey = keyGenerator.generateKey()

setUserAuthenticationRequired()对于加密和解密所需的身份验证为true,这可能取决于移动提供商,有时会导致崩溃应用

然后我们需要检查秘钥是否已经存在了,当然这是可选的:

fun isKeyExists(keyStore : KeyStore): Boolean {
    val aliases = keyStore.aliases()
    while (aliases.hasMoreElements()) {
        return (KEY_ALIAS == aliases.nextElement())
    return false
}

使用AES加密数据:

fun encryptData(data: ByteArray): HashMap<String, ByteArray> {
  val cipher = Cipher.getInstance("AES/GCM/NoPadding")
  cipher.init(Cipher.ENCRYPT_MODE, getSymmetricKey())
  val eiv = (Base64.encodeToString(cipher.iv,Base64.NO_WRAP)).toByteArray()
  val edata = (Base64.encodeToString(cipher.doFinal(data),Base64.NO_WRAP)).toByteArray()
  return hashMapOf(Pair(IV_VALUE,eiv),Pair(ENC_VALUE,edata))
}

密码实例转换格式应为算法/模式/填充,加密数据和IV将以字节数组格式生成。将其转换为Base64只是增加了一层安全性,并且是完全可选的

解密数据:

fun decryptNoBase(ivBytes : ByteArray,encryptedBytes : ByteArray): String {
  val cipher = Cipher.getInstance("AES/GCM/NoPadding")
  cipher.init(Cipher.DECRYPT_MODE, getSymmetricKey(), GCMParameterSpec(128, ivBytes))
  val decryptedData =  cipher.doFinal(encryptedBytes).fromBytetoString()
  return decryptedData
}

具有CBC块模式的AES加密

在这种方法中,将需要使用 密码 charArray来加密和解密数据:

加密:

fun encrypt(datatoEncrypt: ByteArray): HashMap<String, ByteArray> {
  val salt = ByteArray(256)
  SecureRandom().nextBytes(salt)
  val iv = ByteArray(16)
  SecureRandom().nextBytes(iv)
  val iterationCount = 1324
  val keyLength = 256
  val pbKeySpec = PBEKeySpec(ENCRYPT_PASSWORD.toCharArray(), salt, iterationCount, keyLength)
  val keyBytes = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(pbKeySpec).encoded
  val secKey = SecretKeySpec(keyBytes, KeyProperties.KEY_ALGORITHM_AES)
  val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
  cipher.init(Cipher.ENCRYPT_MODE, secKey , IvParameterSpec(iv))
  return hashMapOf(Pair(SALT_VALUE,salt),Pair(IV_VALUE,iv),Pair(ENC_VALUE,cipher.doFinal(datatoEncrypt)))
}

解密数据,使用异常处理和断点需要与加密数据时生成的盐和IV相同的盐和IV,以更好地了解执行流程和异常(如果引发)


2、使用RSA加密

一种非对称密码算法,基本上使用两个不同的密钥来加密和解密数据。公钥用于加密,而私钥用于解密

RSA从API级别10+开始,但是不建议使用,大多数填充都在API级别18+上运行,与对称加密相比,加密过程有点慢。

先创建秘钥对:

fun createAsymmetricKeyPair(): KeyPair {
  val generator: KeyPairGenerator
  if (hasMarshmallow()) {
    generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEYSTORE)
    val builder = KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
        .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
        //.setUserAuthenticationRequired(true)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
    generator.initialize(builder.build())
  } else {
      generator = KeyPairGenerator.getInstance("RSA")
      generator.initialize(2048)
  return generator.generateKeyPair()
}

加密解密数据:

fun encrypt(data: String, publicKey: Key?): String {
  val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
  cipher.init(Cipher.ENCRYPT_MODE, publicKey)
  val bytes = cipher.doFinal(data.toByteArray())
  return Base64.encodeToString(bytes, Base64.DEFAULT)
fun decrypt(data: String, privateKey: Key?): String {