我正在尝试解密已使用AES-128对称加密和随后的RSA-1024非对称加密对生成的对称密钥进行加密的消息。 我收到加密的AES密钥和加密的消息,从pfx文件中提取私钥,然后继续对对称密钥进行解密。 之后,我尝试使用解密的AES密钥解密加密的消息。

以下是我的代码:

// Get the private key

PrivateKey privateKey = (PrivateKey) keyStore.getKey(selectedAlias,"password".toCharArray());

System.out.println("Key information" + privateKey.getAlgorithm() +"" + privateKey.getFormat());

// Load aesSessionKey and encryptedMessage

byte[] aesSessionKey = ...

byte[] encryptedMessage = ...

// RSA Decryption of Encrypted Symmetric AES key - 128 bits

Cipher rsaCipher = Cipher.getInstance("RSA","BC");

rsaCipher.init(Cipher.UNWRAP_MODE, privateKey);

Key decryptedKey = rsaCipher.unwrap(aesSessionKey,"AES", Cipher.SECRET_KEY);

System.out.println("Decrypted Key Length:" + decryptedKey.getEncoded().length);

SecretKeySpec decrypskeySpec = new SecretKeySpec(decryptedKey.getEncoded(),"AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING","BC");

cipher.init(Cipher.DECRYPT_MODE, decryptedKey, new IvParameterSpec(new byte[16]));

byte[] message = cipher.doFinal(encryptedMessage);

System.out.println(new String(message,"UTF-8"));

问题在于解密的AES密钥的大小是128字节,而不是我期望的16字节。 我得到以下异常:

Key information RSA PKCS#8

Decrypted Key Length: 128

java.security.InvalidKeyException: Key length not 128/192/256 bits.

at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(Unknown Source)

at javax.crypto.Cipher.init(DashoA13*..)

at javax.crypto.Cipher.init(DashoA13*..)

at com.simarks.services.PKCS12.run(PKCS12.java:74)

at com.simarks.services.PKCS12.main(PKCS12.java:34)

我是Java密码学的新手。 我已经检查了许多其他问题,并尝试了几种不同的方法(例如使用DECRYPT_MODE而不是UNWRAP_MODE),但是却遇到了相同的错误。 任何帮助都感激不尽。

编辑:

加密消息的客户端代码是这样的:

PBYTE          pInputData = NULL;

DWORD          dwInputSize = 0;

PBYTE          pCertData = NULL;

DWORD          dwCertSize = 0;

PCCERT_CONTEXT pCertContext = NULL;

HCRYPTPROV     hCryptProv = NULL;

HCRYPTKEY      hPublicKey = NULL;

HCRYPTKEY      hSessionKey = NULL;

BYTE           InitializationVector[ 32 ] = { 0 };

DWORD          PKCS5Padding = PKCS5_PADDING;

DWORD          CBCMode = CRYPT_MODE_CBC;

PSIMPLEBLOB    pKeyBlob = NULL;

DWORD          dwBlobSize = 0;

DWORD          dwKeySize = 0;

PBYTE          pEncryptedData = NULL;

DWORD          dwEncryptedDataSize = 0;

HRESULT        hr = S_FALSE;

if( FAILED( hr = ReadBinaryFile( InputFile, &pInputData, &dwInputSize ) ) ) goto EncryptExit;

if( FAILED( hr = ReadBinaryFile( CertFile, &pCertData, &dwCertSize ) ) ) goto EncryptExit;

if( ( pCertContext = CertCreateCertificateContext( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, pCertData, dwCertSize ) ) == NULL ) goto EncryptExit;

if( !CryptAcquireContext( &hCryptProv, NULL, GetMsAesProviderName(), PROV_RSA_AES, 0 ) ) goto EncryptExit;

if( !CryptImportPublicKeyInfo( hCryptProv, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, &pCertContext->pCertInfo->SubjectPublicKeyInfo, &hPublicKey ) ) goto EncryptExit;

if( !CryptGenKey( hCryptProv, AlgId, CRYPT_EXPORTABLE, &hSessionKey ) ) goto EncryptExit;

if( !CryptSetKeyParam( hSessionKey, KP_IV, InitializationVector, 0 ) ) goto EncryptExit;

if( !CryptSetKeyParam( hSessionKey, KP_PADDING, (PBYTE)&PKCS5Padding, 0 ) ) goto EncryptExit;

if( !CryptSetKeyParam( hSessionKey, KP_MODE, (PBYTE)&CBCMode, 0 ) ) goto EncryptExit;

if( !CryptExportKey( hSessionKey, hPublicKey, SIMPLEBLOB, 0, NULL, &dwBlobSize ) ) goto EncryptExit;

if( ( pKeyBlob = (PSIMPLEBLOB)malloc( dwBlobSize ) ) == NULL ) { hr = E_OUTOFMEMORY; goto EncryptExit; }

if( !CryptExportKey( hSessionKey, hPublicKey, SIMPLEBLOB, 0, (PBYTE)pKeyBlob, &dwBlobSize ) ) goto EncryptExit;

dwKeySize = dwBlobSize - sizeof( BLOBHEADER ) - sizeof( ALG_ID );

dwEncryptedDataSize = dwInputSize;

if( !CryptEncrypt( hSessionKey, NULL, TRUE, 0, NULL, &dwEncryptedDataSize, 0 ) ) goto EncryptExit;

if( ( pEncryptedData = (PBYTE)malloc( dwEncryptedDataSize ) ) == NULL ) { hr = E_OUTOFMEMORY; goto EncryptExit; }

CopyMemory( pEncryptedData, pInputData, dwInputSize );

if( !CryptEncrypt( hSessionKey, NULL, TRUE, 0, pEncryptedData, &dwInputSize, dwEncryptedDataSize ) ) goto EncryptExit;

if( FAILED( hr = WriteBinaryFile( OutputFile, pEncryptedData, dwInputSize ) ) ) goto EncryptExit;

hr = WriteBinaryFile( KeyFile, pKeyBlob->Key, dwKeySize );

EncryptExit:

您可以尝试使用Cipher.getInstance("RSAECBPKCS1Padding","BC")而不是"RSA"的默认值进行解密吗? 对于这种功能,您还可以尝试使用默认的Oracle提供程序(因此也尝试删除"BC"参数。还要打印出返回键的类型。

使用安全填充(最好是OAEP)而不是PKCS#1v1.5对于RSA的安全性至关重要。 您确实应该修复填充。

与许多其他提供程序不同,当您指定"RSA"算法时,BouncyCastle提供程序默认情况下不使用填充。根据常见问题解答,BC提供程序会将"RSA"映射到"RSA/NONE/NoPadding"。

因此,您的解密数据仍然附加了填充,因此长度为128个字节。您需要确定密钥加密中使用了哪种填充,并确保在创建Cipher实例时明确指定此填充。例如:

Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding","BC")

正如猫头鹰在评论中提到的那样,如果您愿意的话,您也可以考虑使用标准的Oracle提供程序作为代码-看来BouncyCastle并不是必需的。

我尝试使用Cipher rsaCipher = Cipher.getInstance("RSAECBPKCS1Padding","BC"),但在rsaCipher.doFinal上收到以下异常:Key information RSA PKCS#8 javax.crypto.BadPaddingException: unknown block type at org.bouncycastle.jce.provider.JCERSACipher.engineDoFinal(Unknown Source) at javax.crypto.Cipher.doFinal(Cipher.java:1978) at com.simarks.services.PKCS12.run(PKCS12.java:73) at com.simarks.services.PKCS12.main(PKCS12.java:33)

另外,我尝试使用标准的Oracle提供程序,但遇到以下异常:Key information RSA PKCS#8 javax.crypto.BadPaddingException: Data must start with zero at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:325) at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272) at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:357) at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:383) at javax.crypto.Cipher.doFinal(Cipher.java:1978) at com.simarks.services.PKCS12.run(PKCS12.java:71) at com.simarks.services.PKCS12.main(PKCS12.java:31)

@spaniard听起来像在原始加密中没有使用PKCS#1填充。您是否具有加密AES密钥的源代码?如果没有,关于密钥如何加密的最佳描述是什么?

刚刚在问题中添加了客户端代码。我希望这有助于解决问题

AES采用128位密钥,该密钥长16个字节,因为一个字节可容纳8位。

1024位RSA加密1024位(或128个字节)的数据。您应该始终对RSA使用填充,因为这可以提高安全性并允许您加密任意数量的数据。

另请注意,1024位RSA在抵抗暴力攻击方面相当弱。 2048位被认为是最小的。

另外,带有静态IV的CBC模式只是自找麻烦。

这个答案只是关于AES密钥和RSA加密的陈述的集合。这如何解决原始问题?

我认为第一段很清楚地说明了问题所在。第二段说明了如何解决此问题。最后两段指出了代码中的其他加密问题。

不知道您要说什么@ntoskrnl。我知道我要解密的AES密钥必须是128位长(16字节),但是我却得到了128位长。我同意RSA-1024的弱点。

您将获得128个字节,因为那是1024位RSA加密的数据量。如果要加密不同数量的数据,则必须使用填充。

经过一些研究,我通过反转aesSessionKey的字节解决了这个问题:

org.apache.commons.lang.ArrayUtils.reverse(encryptedSessionKey);

显然,CryptoAPI结构通常以小端顺序表示数据,但是Java(和.NET)使用大端顺序。这是我找到解决方案的一些链接:

RSA加密/解密:.NET,Java 2和CryptoAPI

RE:MS加密API和Java安全API(KeyValue)

EncryptTo / DecryptTo:.NET中使用CryptoAPI证书存储区的加密

rsa1024 java 128 162_关于Java:RSA解密后,无效的AES密钥大小相关推荐

  1. RSA解密失败:javax.crypto.BadPaddingException : Decryption error

    一.由于项目需要,前端把密码用RSA加密后传输到后端,后端进行RSA解密后再与数据库中的密码进行对比,接受到前端传过来的加密后的密码,在进行解密的时候出现错误了: javax.crypto.BadPa ...

  2. javascript rsa java,用javascript与java执行 RSA加密与解密

    用javascript与java执行 RSA加密与解密 2009-12-12 14:58:30   出处:https://www.yqdown.com 这几天一直做安全登录,网上查了好多资料,不尽如意 ...

  3. java 解密后为空_java RSA加密解密

    该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar注意:RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行 ...

  4. java 和 c# 下的RSA证书+AES+DES加解密实现

    java 和 c# 下的RSA+AES+DES加解密实现 前言 在实际应用中,经常有需要使用加解密的情况,RSA\AES\DES是比较常用的几种加解密方式,使用和实现方式都比较成熟可靠,本文简要介绍一 ...

  5. 1、【java数据安全】数据安全之加密解密(base64、MD、SHA、DES、AES、IDEA、PBE、DH、RSA、EIGamal)、数字签名(DSA、ECDSA)和数字证书介绍、应用示例详细介绍

    java数据安全 系列文章 1.[java数据安全]数据安全之加密解密(base64.MD.SHA.DES.AES.IDEA.PBE.DH.RSA.EIGamal).数字签名(DSA.ECDSA)和数 ...

  6. python能解密java的_实现Java加密,Python解密的RSA非对称加密算法功能

    摘要 因为最近业务需要使用到openssl的rsa非对称加密算法,研究了下它的使用方式,但是特殊在于前端分IOS和android两端,所以前端部门要求使用java给他们做一个加密工具包,但是因为服务端 ...

  7. java rsa 公钥加密_java – 使用公钥进行RSA解密

    Java已经有了Java Cryptography Extension Framework,它就是为这些东西设计的. BouncyCastle是此框架的加密提供程序.这意味着,它为您的Java Cry ...

  8. java ios rsa解密乱码_java与IOS之间的RSA加解密

    很简单的一个需求,ipad端给密码RSA加密,传到java后台,解密.RSA加密算法是基于一个密钥对的,分为公钥和私钥,一般情况公钥加密,私钥解密,但也可私钥加密,公钥解密.还可以验签,就是先用私钥对 ...

  9. js java rsa 解密,JS RSA 公钥解密

    JS RSA 公钥解密 需求 后台使用私钥加密数据,然后前端使用公钥解密,也不知道怎么搞出来的这种需求,感觉很不符合逻辑.我对RSA的理解为:公钥负责加密,私钥负责解密.签名的话,私钥负责签名,公钥负 ...

最新文章

  1. 奇异值分解SVD和偏最小二乘奇异值分解PLSSVD
  2. dbunit java_Java – 让DbUnit使用Hibernate事务
  3. 论得失。。。技术方向
  4. 就业阶段-java语言进价_day06
  5. Java常量池学习总结-1
  6. 【正则表达式系列】零宽断言
  7. Nginx资源合并优化模块nginx-http-concat
  8. 28款数据恢复软件对比测试
  9. premiere pr 裁剪视频音频
  10. 自动化测试的7个步骤
  11. 利用PCL库做简单的三维立体图形
  12. 区块链行业人才市场大盘点(附求职指南)
  13. 最简单的内网穿透教程
  14. 关注电动汽车能效水平 提高续航能力
  15. win10系统服务器错误怎么解决方法,分享win10系统提示内部服务器错误的解决方案...
  16. 计算机毕业设计springboot+vue基本微信小程序的校园二手商城的设计与实现
  17. idea连接oracle可插拔数据库报ORA-12505
  18. BroadcastReceiver 广播
  19. socket服务器区分各个客户端信息,socket服务器如何区分哪个客户端
  20. 第一章-一大波数正在靠近——排序

热门文章

  1. CSDN提供的博客搬家功能体验[持续跟踪]
  2. nginx php .htaccess,Linux下nginx支持.htaccess文件实现伪静态的方法
  3. 书摘—拆掉思维里的墙
  4. 超全,我梳理了最频繁使用的 70 个数据分析网址
  5. Angel-Eye: A Complete Design Flow for MappingCNN onto Embedded FPGA
  6. push后再git status出现Your branch is ahead of ‘xxx‘ by 1 commit.
  7. iReport制作报表
  8. Latex CJK,tex使用中文
  9. Python3D绘图后用自带展示器查看(可旋转)
  10. html5知识点:超文本标记语言编程