【问题标题】:Encrypting and decrypting a message with Blowfish使用 Blowfish 加密和解密消息
【发布时间】:2016-07-19 06:48:15
【问题描述】:

下面是加密和解密消息的基本代码:

#include <stdio.h>
#include <openssl/blowfish.h>
#include <string.h>

//gcc cryptage.c -o cryptage -lcrypto

int main(){

BF_KEY *key = malloc(sizeof(BF_KEY));

unsigned char *crypt_key = "Key of encryption";
const unsigned char *in = "Message to encrypt";
int len = strlen(crypt_key);
unsigned char *out = malloc(sizeof(char)*len);
unsigned char *result = malloc(sizeof(char)*len);


//Defining encryption key
BF_set_key(key, len, crypt_key);

//Encryption
BF_ecb_encrypt(in, out, key, BF_ENCRYPT);

//Décryption
BF_ecb_encrypt(out, result, key, BF_DECRYPT);

fprintf(stdout,"Result: %s\n",result);

return 0;

}

我的问题是我得到的结果。它始终是 8 个字符的字符串,仅此而已。 你能帮我加密和解密完整的消息吗?

谢谢!

【问题讨论】:

  • 我现在已经开始输入两次答案并得出结论,要剖析的东西太多了,所以我只想说出来。 Blowfish 是一种对称分组密码。它对块大小的块进行操作。您正在加密一个块(默认 BF 块大小为 8 个字节;64 位),然后将这些字节解密到另一个缓冲区。因此,您只能获得前 8 个字节。
  • 根据BF_encrypt man page"BF_encrypt() 和 BF_decrypt() 是 Blowfish 加密的最低级别函数。它们加密/解密数据指向的向量的前 64 位,使用密钥密钥。除非您实现 Blowfish 的“模式”,否则不应使用这些函数。替代方法是使用 BF_ecb_encrypt()。如果您仍想使用这些函数,您应该知道它们占用每个 32 位块按主机字节顺序,在小端平台上是小端,在大端平台上是大端”.

标签: c encryption openssl blowfish


【解决方案1】:

正如@WhozCraig 所说,一次处理 8 个字节。

要加密的数据应被视为字节数组而不是 C 字符串。
因此,考虑使用\0 加密的字符串并用随机 数据填充以形成一个8 的倍数的字节数组。
多次调用 encrypt,每次迭代加密 8 个字节。

要解密,请以相同的迭代次数调用解密。请注意,结果缓冲区的大小可能需要达到 8 的倍数。

const unsigned char *in = "Message to encrypt";
size_t InSize = strlen(in) + 1;
int KeyLen = strlen(crypt_key);
size_t OutSize = (InSize + 7) & (~7);
unsigned char *out = malloc(Outsize);
unsigned char *outnext = out;
//Defining encryption key
BF_set_key(key, KeyLen, crypt_key);

//Encryption
while (InSize >= 8) {    
  BF_ecb_encrypt(in, outnext, key, BF_ENCRYPT);
  in += 8;
  outnext += 8;
  InSize -= 8;
}
if (Insize > 0) {  // Cope with non-octal length
  unsigned char buf8[8];
  memcpy(buf8, in, InSize);
  for (i=InSize; i<8; i++) {
    buf8[i] = rand();
  }  
  BF_ecb_encrypt(buf8, outnext, key, BF_ENCRYPT);
}

//Décryption
unsigned char *result = malloc(OutSize);
unsigned char *resultNext = result;
while (OutSize) {
  BF_ecb_encrypt(out, resultNext, key, BF_DECRYPT);
  out += 8;
  resultNext += 8;
  OutSize -= 8;
}

fprintf(stdout,"Result: %s\n",result);
// No need to print the random bytes that were generated.
return 0;
}

在最后一个块中编码一个已知字节 (\0) 不太舒服。不同的长度指示可能是谨慎的。

【讨论】:

  • +1 具有讽刺意味的是,您距离使此 PKCS15 填充兼容仅一步之遥。如果您将尾随奇数块字节的字节值设置为未使用的字节数(假设您是三个短字节,它将是 0x03、0x03、0x03)tt 将允许解密器知道原始 真实明文。注意:如果您这样做,您必须考虑您的原始明文可能恰好是块大小的倍数,在这种情况下,您必须添加一个完整 填充块;你不能省略填充ever。很好的答案。
  • @WhozCraig 不会在 PKCS15 填充上花太多钱,但为什么要0x03, 0x03, 0x03?为什么不Rand(), Rand(), 0x03?我还假设填充值是 1 到 8?想知道为什么不使用 5 MSBits/byte 随机的 0 到 7?
  • 它是填充算法规范的一部分。它是检查方法之一。帮助我指错了规格。它实际上是 7.See this description 以及许多其他算法。抱歉,不准确。坦率地说,你真的不需要随机数据,因为如果你这样做了,那算法一开始就不会是你的薄弱环节(它不是;调用者应该使用 cbc 模式;没有理智的人使用 ecb不再)。
  • 谢谢大家 很有帮助 :) 一个问题:size_t OutSize = (InSize + 7)& (~7);我不明白粗体部分是什么意思?
  • @HaTiMuX 7 在二进制中是 000...000111,除了 3 个 LSBits 为 1 之外,所有最高有效位都是 0。~7 是 111...111000,所有最高有效位为 1,除了 3 个 LSBits 为 0。(~7) 很简单,便于评估顺序清晰。通过(InSize + 7) 与 111...111000 进行运算,将清除和的最低 3 位。你可能更喜欢((InSize + 7)/8)*8 - 类似的效果。存在其他形式。
猜你喜欢
  • 2018-12-23
  • 2019-05-15
  • 2011-01-10
  • 2015-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
  • 2021-07-04
相关资源
最近更新 更多