如何使用javax.crypto

时间:2018-05-10 12:37:57

标签: java encryption

在我们的一个内部软件中,我们正在实施一个新的API端点,必须通过互联网访问外部资源,然后必须以某种方式保护它。

由于我们不允许将库用作OAuth或公钥和私钥,因此我们选择javax.crypto AES以这种方式在每个外部源中隐藏“自定义授权令牌”:

...
Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] applicationIdEncrypted = cipher.doFinal(applicationId.getBytes());
...

token包含自定义applicationId,以便在另一方识别谁正在联系该终端。

由于我们必须执行HTTP调用,因此我们将applicationIdEncrypted转换为base64字符串

String base64Encoded = Base64.getEncoder().encodeToString(applicationIdEncrypted);

在另一边

我们正在获取标题并从base64

解码
String base64Decoded = new String(Base64.getDecoder().decode(header));

但是在尝试执行上一次操作时

Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey);

String headerDecoded = new String(cipher.doFinal(base64Decoded.getBytes())); //<- THIS

我们得到javax.crypto.BadPaddingException: Given final block not properly padded

两个base64Encodedbase64Decoded都有相同的值。

尝试在其中一端执行相同的操作(不使用HTTP通道)不会抛出异常 - 但是{{1}返回了不同的headerDecoded }}

查找字节new String(cipher.doFinal(base64Decoded.getBytes()));applicationIdEncrypted,它们略有不同:

applicationIdEncrypted

base64Decoded.getBytes()

base64Decoded.getBytes()

[-28, -103, 107, 70, -112, 121, 4, -14, -80, -114, -14, 92, -81, -13, -128, 97]

我读到可能从字节传递到字符串可能是信息丢失(可能?)但我无法弄清楚这种行为的原因,因为[-28, -103, 107, 70, 63, 121, 4, -14, -80, -114, -14, 92, -81, -13, -128, 97] base64Encoded都具有SAME值案例和情景。

如何仅使用Java 1.7 base64Decoded库来实现“自定义授权令牌”?

修改

javax.crypto类似于"API-KEY"

1 个答案:

答案 0 :(得分:1)

正如@James K Polk所说,我对String转换进行了数千次混乱,所以我设法先使用更清晰的代码来获得更好的综合代码。

在客户端

Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);

byte[] applicationIdEncrypted = cipher.doFinal(applicationId.getBytes());
byte[] base64Encoded = Base64.getEncoder().encode(applicationIdEncrypted);

String out = new String(base64Encoded);

其中outString中唯一的一次转换,它是HTTP标头的有效负载。

在另一边

byte[] in = out.getBytes();
byte[] base64Decoded = Base64.getDecoder().decode(in);

Key aesKey = new SecretKeySpec("API-KEY".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] applicationIdDecrypted = cipher.doFinal(base64Decoded);

String applicationId= new String(applicationIdDecrypted);

我只有两次转换为Stringout(标头的base64值)和applicationId

通过这种方式,我曾经拥有相同的applicationId值。