我必须解密我服务器上的一个帧。加密帧通过套接字上的 GPRS 来自客户端设备。加密 是使用 TripleDes 和给定 key 完成的。我在服务器端使用相同的算法和 key 。 Frame 是 Hex 和 Ascii String 的组合。现在的问题是:当我用零填充字节数组时,出现以下异常。
javax.crypto.BadPaddingException: Given final block not properly padded
以下是我的代码:
byte[] key = new byte[]{31, 30, 31, 36, 32, 11, 11, 11, 22, 26,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30};
myKeySpec = new DESedeKeySpec(key);
mySecretKeyFactory = SecretKeyFactory.getInstance("TripleDES");
de = mySecretKeyFactory.generateSecret(myKeySpec);
Cipher c = Cipher.getInstance("TripleDES");
c.init(Cipher.DECRYPT_MODE, key);
int l = completeHexStr.length();
if (l%8==1){
completeHexStr = completeHexStr + "0000000";
}else if (l%8==7){
completeHexStr = completeHexStr + "0";
}
byte decordedValue[] =completeHexString.getBytes();
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
System.out.println("decryptedValue= " + decryptedValue);
以下是我在代码中使用的函数:
public String stringToHex(String base) {
StringBuffer buffer = new StringBuffer();
int intValue = 0;
for (int x = 0; x < base.length(); x++) {
intValue = base.charAt(x);
String hex = Integer.toHexString(intValue);
if (hex.length() == 1) {
buffer.append("0" + hex + "");
} else {
buffer.append(hex + "");
}
}
return buffer.toString();
}
public String byteToAscii(byte[] b, int length) {
String returnString = "";
for (int i = 0; i < length; i++) {
returnString += (char) (b[i] & 0xff);
}
return returnString;
}
这是客户端加密用的c代码。
#include <svc_sec.h>
const unsigned char fixed_key[] = { 0x31, 0x30, 0x31, 0x36, 0x32, 0x11, 0x11, 0x11, 0x22, 0x26, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
int Comm_Encrypt_Data(unsigned char *Test_Input_Data, int Len_Input_Data)
{
int Count_Input_Data, Counter_Input_Data;
unsigned long Timer_1;
unsigned char Init_Vector[8];
int Counter_Init_Vector, Temp_Byte_Count;
unsigned char *Temp_Dst_Ptr, *Temp_Src_Ptr;
unsigned char Temp_Input_Frame[9], Temp_Output_Frame[9];
unsigned char Test_Output_Data[500];
unsigned char Test_Key_Arr[9];
memset(&Init_Vector[0], '\0', sizeof(Init_Vector));
memset(Test_Key_Arr, '0', sizeof(Test_Key_Arr));
memcpy(Test_Key_Arr, &fixed_key[0], 8);
Test_Key_Arr[sizeof(Test_Key_Arr)-1] = '\0';
Display_Data("KEY: ", Test_Key_Arr, sizeof(Test_Key_Arr)-1);
memset(Test_Output_Data, '\0', sizeof(Test_Output_Data));
memcpy(Test_Output_Data, Test_Input_Data, 48);
Count_Input_Data = Len_Input_Data -48 -3; //minus Data before payload, 3 bytes of '|' and CRC
Counter_Input_Data = 0;
while(Counter_Input_Data < Count_Input_Data)
{
Temp_Byte_Count = Count_Input_Data- Counter_Input_Data;
if(Temp_Byte_Count > 8)
Temp_Byte_Count = 8;
memcpy(Temp_Input_Frame, &Test_Input_Data[48+Counter_Input_Data], Temp_Byte_Count);
//succeeding bytes to be 0
if(Temp_Byte_Count < 8)
{
memset(&Temp_Input_Frame[Temp_Byte_Count], '0', (8-Temp_Byte_Count));
}
Display_Data("InPut Data Before Init",Temp_Input_Frame, Temp_Byte_Count);
//============Initialize the data
Temp_Dst_Ptr = (unsigned char *)Temp_Input_Frame;
Temp_Src_Ptr = (unsigned char *)&Init_Vector[0];
for(Counter_Init_Vector =0;Counter_Init_Vector < 8; Counter_Init_Vector++)
*Temp_Dst_Ptr++ ^= *Temp_Src_Ptr++;
//============Initializing data ends
DES(DESE, (unsigned char *)&Test_Key_Arr[0],
(unsigned char *)&Temp_Input_Frame[0], (unsigned char *)&Temp_Output_Frame[0]);
//DES(TDES3KE, (unsigned char *)&Test_Key_Arr[0],
// (unsigned char *)&Temp_Input_Frame[0], (unsigned char *)&Temp_Output_Frame[0]);
Display_Data("AFTER DES::::", Temp_Output_Frame, Temp_Byte_Count);
memcpy(&Test_Output_Data[48+Counter_Input_Data], Temp_Output_Frame, Temp_Byte_Count);
Counter_Input_Data += Temp_Byte_Count;
if(Counter_Input_Data < Count_Input_Data)
{
memcpy(Init_Vector, Temp_Output_Frame, 8);
}
}
{
memset(Test_Input_Data, '\0', Len_Input_Data);
memcpy(&Test_Input_Data[0], &Test_Output_Data[48], Counter_Input_Data); //1 Separator + 2 CRCs
}
Display_Data("Final Output Frame", Test_Input_Data, Counter_Input_Data);
return Counter_Input_Data;
}
我是 java Cryptography 的新手。请告诉我该怎么做?任何人都可以发布可以正常工作的代码来解密我的框架。提前致谢。
最佳答案
您的代码的主要问题是您使用默认的 PKCS5Padding 进行解密。 "TripleDES" 将在内部生成 "TripleDES/ECB/PKCS5Padding"。这是在 Sun JCE 提供程序中实现的;大多数其他提供商复制此默认值。
您似乎需要零填充,这意味着您应该改用 "DESede/ECB/NoPadding"。之后,您可以使用外部函数来计算纯文本大小(如果不小心,删除零填充可能会删除末尾的零值纯文本)。
其他问题:
“0”的字符值进行填充,这很可能是错误的我指定了 "ECB" 因为我不知道实际使用的模式。如果你能找到的话,你可以用正确的模式和填充算法修改你的问题。如果 ECB 不起作用,您可能还想尝试 CBC 模式。
请注意,除非非常特殊的情况,否则使用 ECB 模式并不安全。使用 CBC 和随机 IV 是最低要求。
关于javax.crypto.BadPaddingException :Given final block not properly padded,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10427205/
我正在尝试解密使用OpenSSL命令行界面创建的文件。此文件创建于:opensslaes-256-cbc-a-infile.txt-outfile_encrypted.txt并且可以用以下方法解密:opensslaes-256-cbc-d-a-infile_encrypted.txt通过使用-p标志,我可以检索WebCryptoAPI所需的实际值、salt和IV:>opensslaes-256-cbc-d-a-p-infile_encrypted.txtsalt=F57F1CC0CD384326key=0E971326890959386F1CFB91F185CFE109203DCEBC
我使用Crypto-JSsourcesiteatGooglecode中的示例进行了简单测试:在页眉中:在Javascript函数中:varencrypted=CryptoJS.AES.encrypt("Message","SecretPassphrase");vardecrypted=CryptoJS.AES.decrypt(encrypted,"SecretPassphrase");alert('encrypted:'+encrypted+'decrypted:'+decrypted);但是输出是:encrypted:U2FsdGVkX19hsNqFBS5xcUoVBCu/hPHep
我收到以下错误:TypeError:__WEBPACK_IMPORTED_MODULE_0_aws_sdk_global__.util.crypto.lib.randomBytesisnotafunction当我尝试使用我编写的以下代码对用户进行身份验证时:import{CognitoUserPool,CognitoUserAttribute,CognitoUser,AuthenticationDetails}from'amazon-cognito-identity-js';letauthenticationDetails=newAuthenticationDetails({Usern
我目前使用以下设置来注册新用户://createsanewuserapp.post('/users',function(req,res){//createnewuservaruser=newUser();//assignpostuser.username=req.body.username;user.email=req.body.email;crypto.randomBytes(32,function(err,buf){if(err)throwerr;user.salt=buf.toString('hex');crypto.pbkdf2(req.body.password,user.s
我正在尝试通过Java调用JavaScript中的函数。这在直接将脚本作为字符串读取时效果很好,但我使用的是CompiledScripts。当我使用编译脚本执行此操作时,如果我还添加绑定(bind),它会提示找不到方法。没有绑定(bind)它可以工作,但当然函数失败,因为它需要绑定(bind)。有什么想法吗?CompiledScriptscript=...getscript....Bindingsbindings=script.getEngine().createBindings();LoggerscriptLogger=LogManager.getLogger("TEST_SCRIP
我们使用CryptoJSSHA3将我们的用户名和密码哈希在一起。该函数从两个html输入字段获取用户名和密码的输入,将它们与盐连接起来,并对它们进行哈希处理。第一个散列成功运行,但是再次散列相同的输出会产生不同的结果。这是相关代码:$prehash=$salt+$user+$pass;$prehash=CryptoJS.enc.Utf8.parse($prehash);varsha3=CryptoJS.algo.SHA3.create();sha3.update($prehash);varpassword=sha3.finalize().toString(CryptoJS.enc.He
我是NodeJs的新手,正在尝试弄清楚如何使用“crypto”模块。在玩弄它时,我注意到NodeJs和crypto-js中的“crypto”模块之间的区别:使用crypto-js,我有:functionSHA256Hash(password,salt,iteration){varsaltedpassword=salt+password;varsha256=CryptoJS.algo.SHA256.create();for(vari=0;i然后调用:varhashedPassword=SHA256Hash("123456789","ASIN",3)并接收:saltedpassword=A
我已经无计可施了。知道网络worker无法访问window对象,有什么办法可以做到这一点吗?请帮忙! 最佳答案 我知道这是一个老问题,但我偶然发现了这个问题,事情发生了变化。大多数浏览器现在都支持网络worker中的加密。在webworkers中,您可以访问self,它不包含所有“窗口”属性(尤其是与dom无关的属性),但包含加密函数等API方法。因此,您可以从webworker中简单地访问self.crypto.getRandomValues()。我做了一个fiddle作为例子:http://jsfiddle.net/jbrosi
看起来Math.random()生成范围[0,1)中的64位float,而新的crypto.getRandomValues()API仅返回整数。使用此API在[0,1)中生成数字的理想方法是什么?这似乎可行,但似乎不是最理想的:ints=newUint32Array(2)window.crypto.getRandomValues(ints)returnints[0]/0xffffffff*ints[1]/0xffffffff编辑:澄清一下,我试图产生比Math.random()更好的结果。根据我对float的理解,应该可以得到52位随机数的完全随机分数。(?)编辑2:为了提供更多背景知
我正在尝试从文件中加载PFX和密码,以便发出HTTPS请求。在开始之前,我已经知道PFX很好,这不是问题所在。我正在做以下事情:config.options.pfx=fs.readFileSync('file.pfx');config.options.passphrase='passphrase';我正在将我的选项传递给代理。config.options.agent=newhttps.Agent(options);然后我尝试构建rquest,但出现以下错误:crypto.js:143c.context.loadPKCS12(pfx,passphrase);^Error:headerto