我正在尝试在运行FreeRTOS的微处理器上使用mbedTLS加密一些文本。我正在使用带有PKCS7填充的AES 128 CBC。如果我尝试在mbedTLS中加密,并在文本少于16个字符时在Java中解密,则可以正常工作。我可以在Java中解密它,并且文本匹配。如果它更长,那么它就不再有效。我做错了什么?
mbedTLS 代码:
unsigned char key[17] = "asdfghjklqwertzu";
unsigned char iv[17] = "qwertzuiopasdfgh";
unsigned char output[1024];
size_t olen;
size_t total_len = 0;
mbedtls_cipher_context_t ctx;
mbedtls_cipher_init(&ctx);
mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_PKCS7);
mbedtls_cipher_setup(&ctx,
mbedtls_cipher_info_from_values(MBEDTLS_CIPHER_ID_AES, 128,
MBEDTLS_MODE_CBC));
mbedtls_cipher_setkey(&ctx, key, 128, MBEDTLS_ENCRYPT);
mbedtls_cipher_set_iv(&ctx, iv, 16);
mbedtls_cipher_reset(&ctx);
char aa[] = "hello world! test long padd";
for( int offset = 0; offset < strlen(aa); offset += mbedtls_cipher_get_block_size( &ctx ) ) {
int ilen = ( (unsigned int) strlen(aa) - offset > mbedtls_cipher_get_block_size( &ctx ) ) ?
mbedtls_cipher_get_block_size( &ctx ) : (unsigned int) ( strlen(aa) - offset );
char sub[100];
strncpy ( sub, aa+offset, ilen );
unsigned char* sub2 = reinterpret_cast<unsigned char *>(sub);
mbedtls_cipher_update(&ctx, sub2, ilen, output, &olen);
total_len += olen;
}
// After the loop
mbedtls_cipher_finish(&ctx, output, &olen);
total_len += olen;
mbedtls_cipher_free(&ctx);
Java代码:
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
SecretKeySpec skey = new SecretKeySpec(encryptionKey.getBytes(), "AES");
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, skey, ivParameterSpec);
return Optional.ofNullable(ByteString.copyFrom(cipherDecrypt.doFinal(message.toByteArray())));
} catch (BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e) {
log.error("Error during message decryption: ", e);
}
Java抛出javax.crypto。BadPaddingException:填充块已损坏
谢谢
编辑:
尝试了一种更新方法,仍然没有运气,同样的例外:
unsigned char key[17] = "asdfghjklqwertzu";
unsigned char iv[17] = "qwertzuiopasdfgh";
//unsigned char buffer[1024];
unsigned char output[1024];
size_t olen;
unsigned char text[] = "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc";
mbedtls_cipher_context_t ctx;
mbedtls_cipher_init(&ctx);
mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_PKCS7);
mbedtls_cipher_setup(&ctx,
mbedtls_cipher_info_from_values(MBEDTLS_CIPHER_ID_AES, 128,
MBEDTLS_MODE_CBC));
mbedtls_cipher_setkey(&ctx, key, 128, MBEDTLS_ENCRYPT);
mbedtls_cipher_set_iv(&ctx, iv, 16);
mbedtls_cipher_reset(&ctx);
mbedtls_cipher_update(&ctx, text, strlen((char*) text), output, &olen); // Olen is 48
mbedtls_cipher_finish(&ctx, output, &olen); // Olen is 16
mbedtls_cipher_free(&ctx);
// 48 + 16 = 64 which is according to https://www.devglan.com/online-tools/aes-encryption-decryption correct
Java获得64字节的数据,但仍然抛出相同的异常。
Topaco请您提供更新和完成功能使用的简短示例?非常感谢。
您的代码中还有一个问题。您需要在设置填充模式之前设置密码信息。否则函数mbedtls_cipher_set_padding_mode将返回错误
因为它是在评论中写的,所以它仍然不起作用。下面是您的代码,注释中有@Topaco建议的更改:
#include <stdio.h>
#include <string.h>
#include <mbedtls/cipher.h>
int main() {
unsigned char key[17] = "asdfghjklqwertzu";
unsigned char iv[17] = "qwertzuiopasdfgh";
unsigned char output[1024];
size_t olen;
size_t total_len = 0;
mbedtls_cipher_context_t ctx;
mbedtls_cipher_init(&ctx);
mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_PKCS7);
mbedtls_cipher_setup(&ctx,
mbedtls_cipher_info_from_values(MBEDTLS_CIPHER_ID_AES, 128,
MBEDTLS_MODE_CBC));
mbedtls_cipher_setkey(&ctx, key, 128, MBEDTLS_ENCRYPT);
mbedtls_cipher_set_iv(&ctx, iv, 16);
mbedtls_cipher_reset(&ctx);
char aa[] = "hello world! test long padd";
for (int offset = 0; offset < strlen(aa); offset += mbedtls_cipher_get_block_size(&ctx)) {
int ilen = ((unsigned int) strlen(aa) - offset > mbedtls_cipher_get_block_size(&ctx)) ?
mbedtls_cipher_get_block_size(&ctx) : (unsigned int) (strlen(aa) - offset);
char sub[100];
strncpy (sub, aa + offset, ilen);
unsigned char *sub2 = (unsigned char *) (sub);
mbedtls_cipher_update(&ctx, sub2, ilen, output + total_len, &olen);
total_len += olen;
}
mbedtls_cipher_finish(&ctx, output + total_len, &olen);
total_len += olen;
for (int i = 0; i < total_len; i++)
printf("%02X", output[i]);
mbedtls_cipher_free(&ctx);
return 0;
}
测验
我添加了两行:
for (int i = 0; i < total_len; i++)
printf("%02X", output[i]);
这给出了输出:
2FE64A72125E30B15C376FD2142D36FA778142DC4FD4A1F36EECDBCDA19BFAA0
如果我稍微修改Java端,并使用以下方式传输消息:
byte[] message = hexStringToByteArray("2FE64A72125E30B15C376FD2142D36FA778142DC4FD4A1F36EECDBCDA19BFAA0");
其中hexStringToByteArray取自此答案:https://stackoverflow.com/a/140861/2331445
在Java方面,我得到了以下代码:
public Optional<ByteString> test() {
String encryptionKey = "asdfghjklqwertzu";
String iv = "qwertzuiopasdfgh";
byte[] message = hexStringToByteArray("2FE64A72125E30B15C376FD2142D36FA778142DC4FD4A1F36EECDBCDA19BFAA0");
Security.addProvider(new BouncyCastleProvider());
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
SecretKeySpec skey = new SecretKeySpec(encryptionKey.getBytes(), "AES");
Cipher cipherDecrypt = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, skey, ivParameterSpec);
return Optional.ofNullable(ByteString.copyFrom(cipherDecrypt.doFinal(message)));
} catch (BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e) {
System.out.println("Error during message decryption: " + e);
}
return null;
}
它最终在调试控制台上给出以下输出:
Optional[<ByteString@1e127982 size=27 contents="hello world! test long padd">]
这就是最初的信息——所以它是这样工作的。
问题内容: 我想将加密的密码存储在Java文件中。我在使用 javax.crypto 的解决方案中看到了一个问题,但是问题在于密钥是动态生成的,并且是随机的。 然后将在运行时在Java程序中获取并解密该密码。鉴于我要在文件中存储一个已经加密的密码-解密时我想要正确的文本。 有没有办法告诉javax.crypto方法: 可以将其替换为基于某个私钥生成的我自己的密钥吗? 谁能指出一些有关执行此操作的资
问题内容: 我想用Java加密和解密密码,然后以加密形式存储到数据库中。如果它是开源的,那就太好了。有什么建议/建议吗? 问题答案: 编辑 :这个答案是旧的。现在 不建议 使用MD5,因为它很容易被破坏。 我想象中的MD5必须足够好?您可以使用MessageDigest实现它。 这里还列出了其他算法。 如果确实需要,这是它的第三方版本: Fast MD5
问题内容: 有没有一种方法可以解密Java中的密码。Java将算法实现为。我得到了创建密码哈希的代码。我在下面提到了哈希技术的链接: http://howtodoinjava.com/security/how-to-generate-secure-password-hash- md5-sha-pbkdf2-bcrypt-examples/ 我的要求是以加密格式存储第三方FTP服务器密码,并在需要登
问题内容: 我想使用128位AES加密和16字节密钥对密码进行加密和解密。解密值时出现错误。解密时我丢失任何内容吗? 错误信息 最后我基于@QuantumMechanic答案使用以下解决方案 } 问题答案: 如果对于块密码,您将不使用包含填充方案的转换,则需要使明文中的字节数为该密码的块大小的整数倍。 因此,要么将纯文本填充到16字节的倍数(即AES块大小),要么在创建对象时指定填充方案。例如,您
这是可能的还是加密必须共享和使用相同的密钥? 主要目的就是这样。 我将有两个客户端可以发送和接收加密数据到彼此。
问题内容: 我是密码学的新手。我希望学习如何在文件中加密和解密文本……当我在net中引用相关文章时。我怀疑对同一文本进行多次加密后,单个文本的加密文本是否会相同?谁能解决我的疑问? 问题答案: 这是使用该类的示例: