移动设备上的数据安全性是极为重要的。移动设备一旦丢失或被盗,而设备上的数据没有进行某种加密,将带来不
有几种方法试图解决这个问题,其中之一是允许授权用户访问同一设备上安全存储的数据,而不需要保存多份拷贝
Android实现了Java Cryptographic Extensions (JCE) ,并提供多种加密方法。加密可以在任何字节阵列上进行,所以能实现双层加密系统,其中密钥用来加密敏感数据
这种方法的好处是你只需要保存主要数据的一份拷贝,这可以节省空间。要访问数据你需要使用设备上没有保存的
Android使用下面的JCE方法产生256比特的AES key:
KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(256); SecretKey key = kg.generateKey();
有了key之后,可以使用JCE来加密任何字节:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); byte[] encryptedData = cipher.doFinal(originalByteArray);
它使用了Android 加密实现方法的另两个部分:
- CBC; 这是密文段链接方法,允许加密算法能工作在特定大小的数据段(如AES),来加密比算法长的数据,它会把数
据分成多个段,依次加密,然后使用某个段的加密结果去加密下一个段。 - PKCS7Padding; 前面提到过,AES只能工作在一定大小的数据段,而CBC只能工作在段大小倍数的数据上。PKCS7Pad
ding通过添加填充字节来保证数据有合适的大小。
你需要保存iv和encryptedData 来加密数据(如果你不知道iv包括什么,请查询初始化向量及在CBC中 如何使用它们)
要解密数据,你要使用同样的代码,并用Cipher.ENCRYPT_MODE替代 Cipher.DECRYPT_MODE,并提供在加密阶段获得的iv。
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); byte[] originalByteArray = cipher.doFinal(encryptedData);
现在已经实现第一级加密,接下来继续第二级加密,这可以允许多个用户访问同一被AES 密钥加密的数据。
SecretKey JCE类包括一个获得密钥的字节阵列的函数。字节阵列可以使用下面的Password Based Encryption (PBE) 进行加密。
byte[] keyBytes = key.getEncoded(); PBEKeySpec passwordKeySpec = new PBEKeySpec(password.toCharArray(), salt, 100, 256); SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); SecretKey passwordKey = kf.generateSecret(passwordKeySpec); Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); cipher.init(Cipher.ENCRYPT_MODE, passwordKey); byte[] encryptedKey = cipher.doFinal(keyBytes);
salt 是用密码来创建的加密密钥的字节阵列。salt 值对每个用户都是唯一地,你应当为每个用户保存其salt 值,因为你需要它来解密密钥。另外两个数(100和256)用来构建PBEKeySpec,前一个数是加密算法迭代次数,后一个数是密码生成的密钥的比特长度。这里加密算法要
再次使用同样代码,替换DECRYPT_MODE 来解密数据(这里是AES 密钥),并从解密数据中重新生成 SecretKey 对象。
PBEKeySpec passwordKeySpec = new PBEKeySpec(PASSWORD.toCharArray(), salt, 100, 256); SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); SecretKey passwordKey = kf.generateSecret(passwordKeySpec); Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); cipher.init(Cipher.DECRYPT_MODE, passwordKey); byte[] keyBytes = cipher.doFinal(encryptedKey); SecretKey key = new SecretKeySpec(keyBytes,"AES");
这就实现了第二级加密,这样每个用户都可以访问共享的加密密钥。
有了双层加密系统,如果一个新用户要使用这个设备,或一个老用户不能再使用这个设备,只需要增加或删除用
这样可以减少数据存储和复制,同时保证数据安全。