首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何用CBC实现Java256位AES加密

如何用CBC实现Java256位AES加密
EN

Stack Overflow用户
提问于 2009-09-17 16:49:26
回答 1查看 50.5K关注 0票数 16

我已经阅读了下面的帖子,它们有一些帮助,但我正在寻找更多的信息。

How to write AES/CBC/PKCS5Padding encryption and decryption with Initialization Vector Parameter for BlackBerry

Java 256bit AES Encryption

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

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

下面是一些代码:

代码语言:javascript
复制
// 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?如果不是,请随时告诉我,让事情变得更清楚。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-09-17 17:22:49

代码中有一些问题。首先,您确实应该使用密钥生成器来生成密钥。直接使用一些文本可能适用于某些算法,但其他算法具有弱密钥等需要测试的内容。

即使您想要进行基于密码的加密,密码也应该通过密钥派生算法来生成密钥,如您已经引用的问题的my answer中所示。

此外,您不应该使用String的no-arg getBytes()方法。这是平台相关的。如果您正在编码的所有字符串只包含US-ASCII字符集的字符,请通过显式指定该编码来明确这一点。否则,如果电话和服务器平台使用不同的字符编码,密钥和IV将不会相同。

对于CBC模式,最好对您发送的每条消息使用新的静脉输液。通常,CBC IV是随机生成的。其他模式,如CFB和OFB,每条消息都需要唯一的IVs。IV通常与密文一起发送-IV不需要保密,但如果使用可预测的IV,许多算法将崩溃。

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

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

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

更新:

Diffie-Hellman在“临时性-静态”模式(和“静态-静态”模式,尽管这不太可取)中是可能的,而不需要从服务器到电话的初始消息,只要服务器的公钥被嵌入到应用程序中。

服务器公钥不会带来与在电话中嵌入公共密钥相同的风险。由于它是公钥,因此威胁将是攻击者获得(或远程侵入)电话,并将真正的公钥替换为允许他冒充服务器的假密钥。

可以使用静态-静态模式,但它实际上更复杂,而且不太安全。每部手机都需要自己的唯一密钥对,否则就会陷入密钥问题。至少服务器不需要跟踪哪部手机拥有哪个密钥(假设在应用程序级别有某种身份验证机制,如密码)。

我不知道电话有多快。在我的桌面上,生成一个临时密钥对大约需要1/3秒。生成Diffie-Hellman参数非常慢;您肯定希望重用服务器密钥中的参数。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1440030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档