寻求可以在Delphi和C中处理整个文件en / de-crypt的单文件加密实现

时间:2012-12-10 01:18:00

标签: c delphi encryption aes microcontroller

[更新]我正在为此提供奖金。坦率地说,我不关心使用哪种加密方法。最好像XTEA,RC4,BlowFish这样的东西...但你选择了。

我希望尽我所能,最好只将文件放入我的项目并构建。

想想你应该已经使用代码在Delphi和C中加密/解密文件(我想在Atmel UC3微处理器(用C编码)和Windows PC(用Delphi编码)之间交换文件两个方向的en-and-de-crypt。)

我对单个.PAS单元和单个.C / .H文件有首选项。我不想使用支持许多加密算法的DLL或库,只需要一个(我当然不希望安装程序有任何东西)。

我希望我在这里听起来不太挑剔,但我一直在谷歌搜索&尝试代码超过一周仍然找不到两个匹配的实现。我怀疑只有已经做过这件事的人才能帮助我...

提前致谢。


作为my previous post的后续,我仍然在寻找一些非常简单的代码,为什么我可以 - 用最少的努力 - 加密文件并在PC上的Delphi和C上的C之间进行交换Atmel UC3 u处理器。

理论上听起来很简单,但在实践中这是一场噩梦。 许多可能的候选人,我花了几天时间用Google搜索并试用它们 - 无济于事。

有些是humonous库,支持许多加密算法,我想要一些轻量级的东西(特别是在C / u处理器端)。

有些看起来很好,但是一组源只提供块操作,其他字符串(我更喜欢整个文件en / de-crypt)。

大多数文档似乎记录得很差,没有无意义的参数名称,也没有调用函数的示例代码。

在过去的周末(再加上几天),我已经烧掉了大量的XTEA,XXTEA和BlowFish实现,但是虽然我可以加密,但我无法逆转这个过程。

现在我在看AES-256。有谁知道C中的实现是一个AES.C文件? (当然还有AES.H)

坦率地说,我将采取任何可以在Delphi和C之间执行整个文件加/解的方法,但除非有人自己实际完成此操作,否则我希望只听到“符合标准的任何实现都应该这样做” - 其中是一个很好的理论,但不适合我: - (

C中有任何简单的AES-256吗?我有一些看起来很合理的Delphi代码,但直到我一起试用它们才能确定。

提前致谢...

6 个答案:

答案 0 :(得分:2)

我建议在辅助微控制器(例如Atmel SAM7X)上使用.NET Micro Framework作为加密协处理器。您可以在Netduino上对此进行测试,您可以以35美元/ 30英镑的价格购买。该框架包括System.Security.Cryptography命名空间内的AES实现,以及可能对您有用的各种其他加密函数。这样做的好处是,您可以通过类型安全的代码获得经过全面测试和工作的实施,并提高安全性。

如果需要更高的吞吐量,您可以使用SPI或I2C在两个微控制器之间进行通信,或者并行地在几条I / O线上对您自己的数据传输协议进行bit-bang。

我使用Arduino和Netduino完成了这项工作(使用Netduino来为硬件BitTorrent设备散列数据块),并使用通过SPI和中断机制在设备之间发送的各种命令实现了一个基本的异步系统。 p>

  • Arduino是SPI主设备,Netduino是SPI从设备。
  • Netduino上的GPIO引脚设置为输出,并绑定到另一个设置为输入的interrupt-enabled GPIO pin on the Arduino。这是中断引脚。
  • Arduino发送0xF1作为“hello”初始化消息。
  • Netduino将0xF2作为acknolwedgement发回。
  • 当Arduino想要散列一个块时,它会发送0x48(ASCII“H”),然后是数据。完成发送数据后,它会将CS设置为低。它必须发送整个字节;当接收到的位数不能被8整除时,将CS设置为低会导致错误。
  • Netduino接收数据,然后将接收到的字节数作为2字节无符号整数发送回0x68(ASCII'h')。如果发生错误,它会发回0x21(ASCII'!')。
  • 如果成功,Netduino会计算哈希值,然后将中断引脚设置为高电平。在计算期间,Arduino可以在等待期间继续工作。
  • Arduino发送0x52(ASCII“R”)来请求结果。
  • Netduino将中断引脚设置为低电平,然后发送0x72(ASCII'r')和原始哈希数据。

由于Arduino可以通过GPIO引脚服务中断,因此它允许我完全异步处理。 Arduino端的一个变量跟踪我们是否正在等待协处理器完成它的任务,所以我们不会尝试发送一个新块,而它仍在使用旧块。

您可以轻松地调整此方案以计算AES块。

答案 1 :(得分:2)

Ilya Levin的

Small C library for AES-256。实施简短,无需使用,简单易用。但不确定它对你当前的微CPU有什么用处。

[编辑]
您已经提到了一些delphi实现,但如果某些内容无法协同工作,请尝试thisthis
我也发现了使用Ilya库的arduino(avr-based)模块 - 所以它也适用于你的微CPU。

答案 2 :(得分:2)

你能从Delphi编译C代码(你可以从C ++ Builder编译Delphi代码,不确定VV)。或者也许使用Free Borland Command line C++ compiler甚至另一个C编译器。

我们的想法是在您的Windows应用程序中使用与在微处理器上使用相同的C代码。这样您就可以合理地确保代码可以在两个方向上运行。


[更新]见

http://www.drbob42.com/examines/examin92.htm
http://www.hflib.gov.cn/e_book/e_book_file/bcb/ch06.htm(在Delphi中使用C ++代码)
http://edn.embarcadero.com/article/10156#H11

看起来您需要使用DLL,但如果您不想分发它,可以静态链接它

答案 3 :(得分:1)

看起来更容易获得参考AES实现(使用块),并添加一些代码来处理CBC(或CTR加密)。 这需要你只需要添加~30-50行代码,如下所示(对于CBC):

aes_expand_key();

first_block = iv;

for (i = 0; i < filesize / 16; i++)
{
  data_block = read(file, 16);
  data_block = (data_block ^ iv);
  iv = encrypt_block(data_block);
  write(outputfile, iv);  
}

// if filesize % 16 != 0, then you also need to add some padding and encrypt the last block

答案 4 :(得分:1)

这是RC4代码。它非常轻巧。

C已在生产系统中使用了五年。

我添加了经过轻微测试的Delphi代码。 Pascal是一个逐行端口,unsigned char转到Byte。我只使用Delphi选项打开Free Pascal中的Pascal,而不是Delphi本身。 C和Pascal都有简单的文件处理器。

对密文进行加扰会使原来的明文恢复原状。

迄今没有报道错误。希望这能解决你的问题。

rc4.h

#ifndef RC4_H
#define RC4_H

/*
 * rc4.h -- Declarations for a simple rc4 encryption/decryption implementation.
 * The code was inspired by libtomcrypt.  See www.libtomcrypt.org.
 */
typedef struct TRC4State_s {
  int x, y;
  unsigned char buf[256];
} TRC4State;

/* rc4.c */
void init_rc4(TRC4State *state);
void setup_rc4(TRC4State *state, char *key, int keylen);
unsigned endecrypt_rc4(unsigned char *buf, unsigned len, TRC4State *state);

#endif

rc4.c

void init_rc4(TRC4State *state)
{
  int x;
  state->x = state->y = 0;
  for (x = 0; x < 256; x++)
    state->buf[x] = x;
}

void setup_rc4(TRC4State *state, char *key, int keylen)
{
  unsigned tmp;
  int x, y;

  // use only first 256 characters of key 
  if (keylen > 256) 
    keylen = 256;

  for (x = y = 0; x < 256; x++) {
    y = (y + state->buf[x] + key[x % keylen]) & 255;
    tmp = state->buf[x]; 
    state->buf[x] = state->buf[y]; 
    state->buf[y] = tmp;
  }
  state->x = 255;
  state->y = y;
}

unsigned endecrypt_rc4(unsigned char *buf, unsigned len, TRC4State *state)
{
  int x, y; 
  unsigned char *s, tmp;
  unsigned n;

  x = state->x;
  y = state->y;
  s = state->buf;
  n = len;
  while (n--) {
    x = (x + 1) & 255;
    y = (y + s[x]) & 255;
    tmp = s[x]; s[x] = s[y]; s[y] = tmp;
    tmp = (s[x] + s[y]) & 255;
    *buf++ ^= s[tmp];
  }
  state->x = x;
  state->y = y;
  return len;
}

int endecrypt_file(FILE *f_in, FILE *f_out, char *key)
{
  TRC4State state[1];
  unsigned char buf[4096];
  size_t n_read, n_written;

  init_rc4(state);
  setup_rc4(state, key, strlen(key));
  do {
    n_read = fread(buf, 1, sizeof buf, f_in);
    endecrypt_rc4(buf, n_read, state);
    n_written = fwrite(buf, 1, n_read, f_out);
  } while (n_read == sizeof buf && n_written == n_read);
  return (n_written == n_read) ? 0 : 1;
}

int endecrypt_file_at(char *f_in_name, char *f_out_name, char *key)
{
  int rtn;

  FILE *f_in = fopen(f_in_name, "rb");
  if (!f_in) {
    return 1;
  }
  FILE *f_out = fopen(f_out_name, "wb");
  if (!f_out) {
    close(f_in);
    return 2;
  }
  rtn = endecrypt_file(f_in, f_out, key);
  fclose(f_in);
  fclose(f_out);
  return rtn;
}

#ifdef TEST

// Simple test.
int main(void)
{
  char *key = "This is the key!";

  endecrypt_file_at("rc4.pas", "rc4-scrambled.c", key);
  endecrypt_file_at("rc4-scrambled.c", "rc4-unscrambled.c", key);
  return 0;
}
#endif

这是Pascal的轻度测试。我可以用C语言加扰源代码并用Pascal实现解密它。

type
  RC4State = record
    x, y : Integer;
    buf : array[0..255] of Byte;
  end;

  KeyString = String[255];

procedure initRC4(var state : RC4State);
var
  x : Integer;
begin
  state.x := 0;
  state.y := 0;
  for x := 0 to 255 do
    state.buf[x] := Byte(x);
end;

procedure setupRC4(var state : RC4State; var key : KeyString);
var
  tmp : Byte;
  x, y : Integer;
begin
  y := 0;
  for x := 0 to 255 do begin
    y := (y + state.buf[x] + Integer(key[1 + x mod Length(key)])) and 255;
    tmp := state.buf[x];
    state.buf[x] := state.buf[y];
    state.buf[y] := tmp;
  end;
  state.x := 255;
  state.y := y;
end;

procedure endecryptRC4(var buf : array of Byte; len : Integer; var state : RC4State);
var
  x, y, i : Integer;
  tmp : Byte;
begin
  x := state.x;
  y := state.y;
  for i := 0 to len - 1 do begin
    x := (x + 1) and 255;
    y := (y + state.buf[x]) and 255;
    tmp := state.buf[x];
    state.buf[x] := state.buf[y];
    state.buf[y] := tmp;
    tmp := (state.buf[x] + state.buf[y]) and 255;
    buf[i] := buf[i] xor state.buf[tmp]
  end;
  state.x := x;
  state.y := y;
end;

procedure endecryptFile(var fIn, fOut : File; key : KeyString);
var
  nRead, nWritten : Longword;
  buf : array[0..4095] of Byte;
  state : RC4State;
begin
  initRC4(state);
  setupRC4(state, key);
  repeat
    BlockRead(fIN, buf, sizeof(buf), nRead);
    endecryptRC4(buf, nRead, state);
    BlockWrite(fOut, buf, nRead, nWritten);
  until (nRead <> sizeof(buf)) or (nRead <> nWritten);
end;

procedure endecryptFileAt(fInName, fOutName, key : String);
var
  fIn, fOut : File;
begin
  Assign(fIn, fInName);
  Assign(fOut, fOutName);
  Reset(fIn, 1);
  Rewrite(fOut, 1);
  endecryptFile(fIn, fOut, key);
  Close(fIn);
  Close(fOut);
end;

{$IFDEF TEST}
// Very small test.
const
  key = 'This is the key!';
begin
  endecryptFileAt('rc4.pas', 'rc4-scrambled.pas', key);
  endecryptFileAt('rc4-scrambled.pas', 'rc4-unscrambled.pas', key);
end.
{$ENDIF}

答案 5 :(得分:1)

假设加密强度不是问题,就像满足组织的中国墙要求一样,非常简单的“Sawtooth”加密方案,为每个字节添加(i ++%modulo 256)到fgetc(),从文件的开头,可能工作正常。

将i声明为UCHAR将消除模数要求,因为单字节整数不得不循环通过其0-255范围。

代码非常简单,不值得发布。一点想象力,你会有一些装饰可以增加这个密码的力量。这个密码的主要漏洞是大块相同的字符。纠正这个是开始提高力量的好地方。

此cypher适用于所有可能的文件类型,如果您已经7Zip文件,则该cypher特别有效。

表现非常出色。你甚至都不知道代码在那里。完全I / O绑定。