用CBC进行AES加密
我已阅读以下主题,他们已经帮助了一些,但我正在寻找更多信息。
如何使用BlackBerry的初始化向量参数编写AES / CBC / PKCS5Padding加密和解密
Java 256位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中完成过类似的项目,我为您提供以下建议:
上一篇: bit AES encryption with CBC
下一篇: Based Encryption