admin管理员组

文章数量:1594647

Undoubtedly, security is a critical issue in Android application development; however, accomplishing all tasks correctly could be tricky. At Google IO/2019, Google introduced the Jetpack Security library, which aims to address some controversial issues in Android security to ease the process of making apps more secure. This essay will discuss some concepts and features in Android Jetpack Security for having more secure Android apps.

毫无疑问,安全性是Android应用程序开发中的关键问题。 但是,正确完成所有任务可能很棘手。 在Google IO / 2019上,Google引入了Jetpack安全性库,该库旨在解决Android安全性中的一些有争议的问题,以简化使应用程序更安全的过程。 本文将讨论Android Jetpack Security中的一些概念和功能,以使Android应用程序更安全。

简介与概述 (Introduction and Overview)

At Google IO/2019, Google introduced the new Jetpack Security library, which aims to solve some critical issues in Android security. Jetpack Security provides an abstraction over security. In fact, it is a wrapper around primitives that are built into the platform. Therefore, it makes encrypting files and shared preferences more effectively. In addition, the Android KeyStore stores cryptographic keys in a container to make it much more difficult to extract from the device. Once keys are in the KeyStore, they could be used for cryptographic operations in the trusted execution environment, and the key material is not exportable. The Android KeyStore also provides some options like StrongBox to store and operate on keys in a secure hardware chip. Thus, the question is how does an Android developer take advantage of these platform features?

在Google IO / 2019上,Google引入了新的Jetpack安全性库,旨在解决Android安全性中的一些关键问题。 Jetpack Security提供了对安全性的抽象。 实际上,它是一个包装器 围绕平台中内置的原语。 因此,它可以更有效地加密文件和共享首选项。 此外,Android KeyStore将加密密钥存储在容器中,这使得从设备中提取密码变得更加困难。 一旦密钥进入KeyStore,就可以在受信任的执行环境中将其用于加密操作,并且密钥材料不可导出。 Android KeyStore还提供了诸如StrongBox之类的一些选项来存储和操作安全硬件芯片中的密钥。 因此,问题是Android开发人员如何利用这些平台功能?

The Security library, part of Android Jetpack, provides an implementation of the security best practices related to reading and writing data at rest, as well as key creation and verification.

安全性库是Android Jetpack的一部分,可提供与静态数据读写有关以及密钥创建和验证相关的安全性最佳实践的实现。

Basically, Jetpack Security, or JetSec for short, takes advantage of the Android KeyStore to maintain encryption keys in hardware, which makes accessing the key material would be extremely hard. Besides, JetSec supports high level of abstractions for encrypting files and shared preferences to allow Android developers to encrypt their data safely. Another significant point is that there is no need to understand algorithms and block modes. Fundamentally, JetSec is classified into two sections: Key Management and Data Encryption.

基本上,Jetpack Security或简称JetSec,利用Android KeyStore来维护硬件中的加密密钥,这使得访问密钥资料非常困难。 此外,JetSec支持用于加密文件和共享首选项的高级抽象,以允许Android开发人员安全地加密其数据。 另一个重要的一点是,无需了解算法和块模式。 从根本上讲,JetSec分为两部分:密钥管理数据加密

The Android KeyStore system lets you store cryptographic keys in a container to make it more difficult to extract from the device. Once keys are in the KeyStore, they can be used for cryptographic operations with the key material remaining non-exportable.

Android KeyStore系统可让您将加密密钥存储在容器中,从而使其更难从设备中提取。 一旦密钥进入密钥存储区,就可以将其用于加密操作,而密钥材料仍不可导出。

Both of these abstractions provide authenticated encryption with associated data, or AEAD for short, which provides simultaneous insurance for confidentiality and integrity of the data.

这两种抽象都为关联的数据(或简称AEAD)提供了经过身份验证的加密,从而为数据的机密性和完整性提供了同时保证。

密钥管理 (Key Management)

As a matter of fact, the Jetpack Security library uses two types of key for key management concept as follows:

实际上,Jetpack安全性库将两种类型的密钥用于密钥管理概念,如下所示:

  1. A key-set that includes one or more keys to encrypt a file or shared preferences data. The key-sets are encrypted and stored in the shared preferences.

    一种密钥集,包括一个或多个用于加密文件或共享首选项数据的密钥。 密钥集被加密并存储在共享首选项中。

2. A master key that encrypts all key-sets. Only the master key is stored in the Android Key-store system to make it much more difficult to extract from the device.

2.加密所有密钥集的主密钥。 只有主密钥存储在Android密钥存储系统中,这使得从设备中提取密钥更加困难。

Also, all data secured by JetSec is performed via the Android store. JetSec uses the concept of a master key, which is hardware-backed and optionally locked by bio-metrics such as fingerprint or face identification. This helps secure key sets, which are treated per cryptographic algorithm. In fact, AndroidX Security is using the Tink library under the hood. Tink is an open-source crypto library created by Google that supports cryptographic APIs. Out of the box, JetSec enables developers to create a master key with one line of code:

另外,JetSec保护的所有数据都通过Android商店执行。 JetSec使用主密钥的概念,该主密钥由硬件支持,并可以选择通过生物特征(例如指纹或面部识别)锁定。 这有助于保护密钥集,每个密钥集都会对其进行处理。 实际上, AndroidX Security在后台使用Tink库。 Tink是Google创建的一种开放源代码加密库,支持加密API。 开箱即用的JetSec使开发人员可以用一行代码创建一个主密钥:

val masterKey = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

JetSec creates an industry standard AES256-bit key. This could be useful for most use cases, but for more sensitive data, there are more customization that could be accomplished. So, it is highly recommended to connect hardware-backed keys to user presence via a bio-metric credential. The Android keystore enforces bio-metrics at the hardware level, and keys will not be available for use without authorizing the device using the bio-metric prompt Jetpack Library. For utilizing JetSec, Google has recommended the time-bound key approach, which enables developers to lock and unlock keys for a limited amount of time. This is particularly useful when dealing with enterprise, financial, and other very sensitive data. To crate a custom key, you will need to indicate keystoreAlias and key purposes along with other encryption configurations. For instance:

JetSec创建了行业标准的AES256位密钥。 这对于大多数用例可能很有用,但是对于更敏感的数据,可以实现更多的自定义。 因此,强烈建议通过生物特征凭证将硬件支持的密钥连接到用户状态。 Android密钥库在硬件级别实施生物识别,如果未使用生物识别提示Jetpack Library授权设备,则密钥将无法使用。 为了利用JetSec,Google建议使用限时密钥方法,该方法使开发人员可以在有限的时间内锁定和解锁密钥。 在处理企业,财务和其他非常敏感的数据时,这特别有用。 要创建自定义密钥,您将需要指示keystoreAlias和密钥用途以及其他加密配置。 例如:

val keySpecifications = KeyGenParameterSpec.Builder(
    "key_alias",
    KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
).apply {
    setKeySize(256)
    setBlockModes(KeyProperties.BLOCK_MODE_GCM)
    setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
}.build()


val masterKey = MasterKeys.getOrCreate(keySpecifications)

Furthermore, we can be able to use its setUserAuthenticationRequired property to enable user authentication feature. The master key can just only be obtained for the seconds mentioned in setUserAuthenticationValidityDurationSeconds after the user authenticates himself by using bio-metric fingerprint or screen lock. For example:

此外,我们可以使用其setUserAuthenticationRequired属性来启用用户身份验证功能。 仅在用户使用生物特征指纹或屏幕锁定对自己进行身份验证之后,才可以在setUserAuthenticationValidityDurationSeconds提到的中获取主密钥。 例如:

setUserAuthenticationRequired(true)
setUserAuthenticationValidityDurationSeconds(6)

Eventually, we can be able to use the key for specified time once we obtain success in BiometricPrompt’s onAuthenticationSucceeded method as follows:

最终,一旦我们在BiometricPrompt的onAuthenticationSucceeded方法中获得成功,就可以在指定的时间内使用密钥,如下所示:

override fun onAuthenticationSucceeded(result: AuthenticationResult) {
    super.onAuthenticationSucceeded(result)
    // key is unlocked
}

For time-bound master keys, Jetpack BiometricPrompt is a quick and easy way to display a backwards compatible bio-metric check on the device. You should use the Jetpack library rather than the direct platform APIs because Jetpack manages pin passwords, as well as multiple modalities, such as fingerprint and face identification.

对于有时间限制的主密钥,Jetpack BiometricPrompt是一种在设备上显示向后兼容的生物识别检查的快捷方式。 您应该使用Jetpack库而不是直接平台API,因为Jetpack会管理个人密码,以及多种方式,例如指纹和面部识别。

数据加密:如何加密文件和共享首选项 (Data encryption: how to encrypt your files and shared preferences)

As you know, encrypted files have been a challenge in the past due to size limitations because the entire file would have had to have been required to be loaded into memory. EncryptedFile takes advantage of streaming AES encryption that can manage files of all sizes with just only disk space as the limiting factor. EncryptedFile could be treated similar to a normal file in Android. Once the encrypted file object has been created, you may operate on the file with the file input/output streams provided. As a result, the same encryption concepts would be applicable for EncryptedFile. For instance:

如您所知,由于大小限制,加密文件在过去一直是一个挑战,因为必须将整个文件加载到内存中。 EncryptedFile利用流式AES加密的优势,该功能可以仅将磁盘空间作为限制因素来管理所有大小的文件。 EncryptedFile的处理方式类似于Android中的普通文件。 一旦创建了加密文件对象,就可以使用提供的文件输入/输出流对该文件进行操作。 结果,相同的加密概念将适用于EncryptedFile。 例如:

encryptedFile = EncryptedFile.Builder(
            secretFile,
            applicationContext,
            MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), //master key
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        )
            .setKeysetAlias("file_key") //optional
            .setKeysetPrefName("secret_file_shared_prefs")  //optional
            .build()

These lines of codes can create an EncryptedFile object from a normal file object. Some parameters such as FileEncryptionScheme, KeysetPrefName ,KeysetAlias are optional in implementation. In other words, they are used to name the XML file and the key inside it, which stores the encryption key value. At the moment, after obtaining the encrypted file, if you want to write some data to your encrypted file or read from it, you can use the openFileOutput() and openFileInput() methods as follows:

这些代码行可以从普通文件对象创建EncryptedFile对象。 一些参数,例如FileEncryptionSchemeKeysetPrefNameKeysetAlias在实现中是可选的。 换句话说,它们用于命名XML文件及其内部的密钥,该文件存储加密密钥值。 目前,在获取加密文件之后,如果要向加密文件中写入一些数据或从中读取数据,则可以如下使用openFileOutput()openFileInput()方法:

//save data
encryptedFile.openFileOutput().use { outputstream ->
    outputstream.write(et_data.text.toString().toByteArray())
}
//read data
encryptedFile.openFileInput().use { inputstream ->
    tv_result.text = String(inputstream.readBytes(), Charsets.UTF_8)
}

共享首选项加密(SharedPreferences Encryption)

If you just need to persist data that can be easily model in key value pairs, encrypted shared preferences provides an implementation of shared preferences which handles encryption automatically. In general, encrypting shared preferences is similar to encrypting files. So, we store our data in SharedPreferences because it is easy to use. In the meantime, it would be an easy target for the attackers to obtain the keys from SharedPreferences. Therefore, we require to encrypt our SharedPrefernce data with utilizing EncryptedSharedPreferences feature in Security library. The important note to indicate is that the keys and values are encrypted in a different way. You can encrypt shared preferences as follows:

如果只需要持久存储可以轻松地在键值对中建模的数据,则加密的共享首选项提供了共享首选项的实现,该实现可以自动处理加密。 通常,加密共享首选项类似于加密文件。 因此,我们将数据存储在SharedPreferences中,因为它易于使用。 同时,对于攻击者来说,从SharedPreferences获取密钥将是一个容易的目标。 因此,我们需要利用安全性库中的EncryptedSharedPreferences功能来加密SharedPrefernce数据。 需要指出的重要注意事项是,键和值以不同的方式加密。 您可以如下加密共享的首选项:

val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)


EncryptedSharedPreferences.create(
            "encrypted_preferences", // fileName
            masterKeyAlias, // masterKeyAlias
            this, // context
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, // prefKeyEncryptionScheme
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM // prefvalueEncryptionScheme
        )

结论(In conclusion)

Undoubtedly, security is a critical issue in Android development, but accomplishing all tasks correctly could be tricky. This article explained some concepts and features in Android Jetpack Security. Although there are some prominent classes in this library for Android developers, there are some drawbacks are remained to consider such as some limitations in applying some algorithms and comparability of Android devices in working with this library (This is available for Android version 6.0 or higher).

毫无疑问,安全性是Android开发中的关键问题,但是正确完成所有任务可能很棘手。 本文介绍了Android Jetpack Security中的一些概念和功能。 尽管此库中有一些针对Android开发人员的突出类,但仍有一些弊端需要考虑,例如在应用某些算法时存在一些限制以及与该库一起使用时Android设备的可比性(适用于Android 6.0或更高版本) 。

翻译自: https://medium/kayvan-kaseb/using-android-jetpack-security-a24113d2266e

本文标签: androidJetpack