我在Java客户端中使用公钥时遇到了一些奇怪的问题。我从C服务器获取公钥,我知道以下内容:B64Encoded,X.509 RSA密钥,我应该使用PKCS1Padding。到目前为止,我已完成以下操作,以确保在客户端和服务器之间传输的数据是正确的:
1)从服务器发送的数据内容和长度与java客户端
相同2)一旦它被B64解码,数据和长度是相同的
3)我还验证了C客户端和Java客户端之间的数据是一样的,直到我开始从解码数据创建公钥。
我遇到了一个问题,即在Cipher加密密码后,Java客户端会将过多的数据发送回服务器。我试图在创建公钥对象时使用不同的方法,但似乎没有任何效果。我要么得到“ algid解析错误,而不是序列” - 错误,或者密钥被创建,我最终发送了太多字节的数据(来自Java的139与来自C客户端的128) 。 这是代码(剪掉一些不相关的东西)。一切都被分解为单一尝试/捕获,因为我试图找出问题所在:
byte[] pk = getKeyFromServer(); // 191 bytes
String keyString = new String(pk);
byte[] decoded = decode(keyString); // 139 bytes
try {
keySpec = new X509EncodedKeySpec(decoded);
} catch (Exception e) { e.printStackTrace();}
try {
keyFactory = KeyFactory.getInstance("RSA", "IBMJCE");
} catch (Exception e) { e.printStackTrace();}
try {
publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) { e.printStackTrace();}
try {
cipher = Cipher.getInstance("RSA/SSL/PKCS1Padding", "IBMJCE");
} catch (Exception e) { e.printStackTrace(); }
try {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
} catch (Exception e) { e.printStackTrace(); }
try { sendEncrypted(cipher.doFinal(pwd.getBytes()));
} catch (Exception e) { e.printStackTrace(); }
上面的代码遇到了我之前提到过的异常,如果我删除了KeySpec和KeyFactory部分,并按照以下内容进入加密部分,但后来我发送了太多数据,而且服务器不能解密它(我从挖掘中获得了指数)。
java.math.BigInteger modulus = new java.math.BigInteger(decoded);
java.math.BigInteger exponent = new java.math.BigInteger("22111");
publicKey = new RSAPublicKey(modulus, exponent);
所以我想问题是,我做了一些完全错误的事情,或者是否有一些事情我应该更多地了解C客户端在使用它加密之前对BASE64解码的公钥做了什么,并尝试复制?现在我无法访问该部分:(
我尝试使用不同的KeySpecs,PublicKeys和paddings,但结果总是相同的(尽管异常可能会因我使用KeySpec而偏离基础而不同。)
服务器和客户端之间的通信运行良好。只是这部分使用了无效的公钥。
编辑:只是想添加公钥String,如果有的话:
Public key from server:
MIGIAoGBAMZawVoP6mHl0xD3Epn1l4S/6Ke20ZTNLKaXyi425NwhiE7LoTysAcpx
y3i9LXLVNGpdPNtpGD3mvlNJc/HfGQQ7NQpNyKpe5EzsODb1YCbODtfmaRODDW9B
qsrE8DCxI0g8gzu3NJTrUh4NfRaSBn9HaOnBUwiyQyihq2I6MB6bAgJWXw==
答案 0 :(得分:1)
你可以试试“RSA / ECB / PKCS1Padding”而不是中间的“/ SSL”吗?如果我没有弄错的话,SSL会使用特殊的结构。
另外: 编码不兼容X509!似乎密钥的编码是PKCS#1,而X509使用围绕该编码的小包装器!
来自PKCS#1:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
来自X509EncodedKeySpec:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
因此,您必须在您收到的数据前面添加序列标签,长度,算法标识符和BIT STRING标签和长度!奇怪的是,你可以让它做任何事情。
对于这个特定的keylength和(奇怪的)两个字节的公共指数,标题将包含以下字节:
(byte) 0x30, (byte) 0x81, (byte) 0x9E, (byte) 0x30, (byte) 0x0D, (byte) 0x06, (byte) 0x09, (byte) 0x2A,
(byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xF7, (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01,
(byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8C, (byte) 0x00,
或者,您也可以从结构中检索两个整数,并从中创建RSAPublicKeySpec
。