繁体   English   中英

如何使用CBC实现Java 256位AES加密

[英]How to implement Java 256-bit AES encryption with CBC

我已经阅读了以下主题并且他们帮助了一点,但我正在寻找更多信息。

如何使用BlackBerry的初始化矢量参数编写AES / CBC / PKCS5Padding加密和解密

Java 256bit AES加密

基本上,我正在做的是编写一个程序,它将加密通过TCP / IP发送的请求,然后由服务器程序解密。 加密需要是AES,并且做了一些研究我发现我需要使用CBC和PKCS5Padding。 所以基本上我需要一个秘密密钥和一个IV。

我正在开发的应用程序是用于手机,所以我想使用java安全包来减小尺寸。 我已完成设计,但不确定IV和共享密钥的实现。

这是一些代码:

// My user name
byte[] loginId = "login".getBytes();

byte[] preSharedKey128 = "ACME-1234AC".getBytes();
byte[] preSharedKey192 = "ACME-1234ACME-1234A".getBytes();
// 256 bit key
byte[] preSharedKey256 = "ACME-1234ACME-1234ACME-1234".getBytes();
byte[] preSharedKey = preSharedKey256;

// Initialization Vector
// Required for CBC
byte[] iv ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
IvParameterSpec ips = new IvParameterSpec(iv);


byte[] encodedKey = new byte[loginId.length + preSharedKey.length];

System.arraycopy(loginId, 0, encodedKey, 0, loginId.length);
System.arraycopy(preSharedKey, 0, encodedKey, loginId.length, preSharedKey.length);

// The SecretKeySpec provides a mechanism for application-specific generation
// of cryptography keys for consumption by the Java Crypto classes.

// Create a key specification first, based on our key input.
SecretKey aesKey = new SecretKeySpec(encodedKey, "AES");

// Create a Cipher for encrypting the data using the key we created.
Cipher encryptCipher;

encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// Initialize the Cipher with key and parameters
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey, ips);

// Our cleartext
String clearString = "33,8244000,9999,411,5012022517,0.00,0,1,V330";
byte[] cleartext = clearString.getBytes();

// Encrypt the cleartext
byte[] ciphertext = encryptCipher.doFinal(cleartext);

// Now decrypt back again...
// Decryption cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// Initialize PBE Cipher with key and parameters
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ips);

// Decrypt the cleartext
byte[] deciphertext = decryptCipher.doFinal(ciphertext);

简而言之它应该做的是加密一些可以由服务器解密的消息,而无需服务器从手机获取密钥或IV。 有没有办法可以做到这一点,我可以保护手机上的IV和键,并且仍然有服务器知道的密钥和IV? 如果他们不是,请随时告诉我更清楚。

代码存在一些问题。 首先,您确实应该使用密钥生成器来生成密钥。 直接使用某些文本可能适用于某些算法,但其他算法则需要进行弱测试等等。

即使您想要进行基于密码的加密,也应该通过密钥派生算法运行密码以生成密钥,如对您已引用的问题的回答所示。

此外,您不应该使用String的no-arg getBytes()方法。 这取决于平台。 如果您编码的所有字符串仅包含US-ASCII字符集中的字符,请通过明确指定该编码来使其清楚。 否则,如果电话和服务器平台使用不同的字符编码,则密钥和IV将不会相同。

对于CBC模式,最好为发送的每条消息使用新的IV。 通常,CBC IV是随机生成的。 其他模式如CFB和OFB 需要为每条消息提供唯一的IV。 IV通常沿着密文发送 - IV不需要保密,但是如果使用可预测的IV,许多算法将会中断。

服务器不需要直接从手机获取秘密或IV。 可以使用密钥(或密码,从中派生密钥)配置服务器,但在许多应用程序中,这将是一个糟糕的设计。

例如,如果将应用程序部署到多个人的电话上,那么他们使用相同的密钥并不是一个好主意。 一个恶意用户可以恢复密钥并为每个人破坏系统。

更好的方法是在电话上生成新的密钥,并使用密钥协商算法与服务器交换密钥。 Diffie-Hellman密钥协议可以用于此,或者密钥可以用RSA加密并发送到服务器。


更新:

只要服务器的公钥嵌入应用程序中,Diffie-Hellman处于“短暂 - 静态”模式(以及“静态 - 静态”模式,尽管不太理想)也可以在没有从服务器到电话的初始消息的情况下实现。 。

服务器公钥与在电话中嵌入公共密钥的风险不同。 由于它是一个公钥,威胁将是攻击者接触(或远程入侵)手机并用假密钥替换真正的公钥,允许他冒充服务器。

可以使用静态静态模式,但实际上它更复杂,安全性稍差。 每部手机都需要自己独特的密钥对,否则您会回到密钥问题中。 至少不需要服务器跟踪哪个电话具有哪个密钥(假设在应用程序级别存在一些认证机制,如密码)。

我不知道手机有多快。 在我的桌面上,生成一个短暂的密钥对大约需要1/3秒。 生成Diffie-Hellman参数非常慢; 你肯定想重新使用服务器密钥中的参数。

之前在midlet做过类似的项目,我有以下建议:

  1. 没有安全的方法来存储手机上的共享密钥。 您可以使用它,但这属于一个名为Security through Obscurity的类别。 这就像是一种“垫下密钥”的安全性。
  2. 不要使用256位AES,因为它没有广泛使用。 您可能必须安装另一个JCE。 128位AES或TripleDES仍然被认为是安全的。 考虑到#1,你不应该担心这一点。
  3. 使用密码加密(每个用户不同)更加安全。 但是你不应该像在示例中那样使用密码作为密钥。 请使用PBEKeySpec(基于密码的加密)生成密钥。
  4. 如果您只是担心MITM(中间人)攻击,请使用SSL。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM