问题描述
我有这个 Android 移动应用程序,它是 NVR 软件的客户端。它使用基本身份验证和 api 密钥进行服务器身份验证。我现在正在为 android 电视构建一个应用程序。我正在添加一个允许使用移动设备进行身份验证的功能。为此,我使用了 Google 的 Nearby 库,其中电视成为广告商,手机成为发现者。我可以毫无问题地将数据(凭据)从手机发送到电视。但是,我想保护数据。我想过使用加密来保护数据,并阅读了 this 和 this,但遇到了“javax.crypto.AEADBadTagException:数据太短”或“javax.crypto.BadPaddingException:pad 块损坏”等问题。我认为问题是因为我使用了一个短字符串(6 个字符)作为密钥。
我正在做的是让电视生成一个随机的 6 位代码并将其显示在屏幕上。现在在移动应用程序上,我要求用户输入 6 位代码。然后我使用此代码来加密凭据。当电视接收到数据时,我需要使用相同的数字代码对其进行解密。
这是我的加密和解密代码。目前无法使用。
public class DoCrypto {
private static final String ENCRYPT_ALGO = "AES/GCM/nopadding";
private static final int TAG_LENGTH_BIT = 128;
private static final int IV_LENGTH_BYTE = 12;
private static final int AES_KEY_BIT = 256;
private static final Charset UTF_8 = StandardCharsets.UTF_8;
public static String encrypt(String clearText,String code) throws Exception {
KeySpec keySpec = new PBEKeySpec(code.tochararray(),code.getBytes(UTF_8),1000,256);
SecretKey secretKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(keySpec);
return new String(encrypt(clearText.getBytes(),secretKey));
}
public static String decrypt(String encryptedText,256);
SecretKey secretKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(keySpec);
return decrypt(encryptedText.getBytes(),secretKey);
}
public static byte[] encrypt(byte[] pText,SecretKey secret) throws Exception {
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.ENCRYPT_MODE,secret);
byte[] encryptedText = cipher.doFinal(pText);
return encryptedText;
}
public static String decrypt(byte[] cText,SecretKey secret) throws Exception {
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.DECRYPT_MODE,secret);
byte[] plainText = cipher.doFinal(cText);
return new String(plainText,UTF_8);
}
}
我正在测试这个
try {
String code = DoCrypto.encrypt("Clear Text","1234");
Log.d("crypt",code);
Log.d("crypt",DoCrypto.decrypt(code,"1234"));
} catch (Exception e) {
e.printstacktrace();
}
这段代码给了我上面提到的错误“javax.crypto.AEADBadTagException: data too short”。所以也许我在想我可能没有正确地做这件事,因为我只使用了一个 4-6 位的密钥。
是否有更好的方法来保护数据?
更新 #1:
经过一些修补后,我现在收到错误“javax.crypto.AEADBadTagException:GCM 中的 mac 检查失败”。目前正在谷歌搜索以了解原因。
解决方法
Nearby Connections 为两台设备提供一个身份验证令牌 (https://developers.google.com/android/reference/com/google/android/gms/nearby/connection/ConnectionInfo#getAuthenticationToken())。只要您在发送敏感数据前确认,实际连接和数据传输将是安全的。
大多数客户端只是在两个屏幕上显示令牌并有一个确认步骤。有些人将它散列(成一个数字,或成一系列图像),使其更易于阅读。