这个加密算法有多好? [英] How good an encryption algorithm is this?

查看:75
本文介绍了这个加密算法有多好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个加密算法来满足以下要求:

1)必须能够将字符串加密到一个字节数组,然后再次删除

相同的字符串

2)必须使用相同的算法处理字符串,可能是也可能不是

unicode

3)返回的字节数必须是< = _BCHARs的数量*

sizeof(_TCHAR),或者输出大小和输入大小之间的关系可以简单地计算为
。必须考虑到结尾的空终结符

的字符串。

4)加密算法还必须返回
$的确切字节数b $ b加密数据

我很难让CryptoAPI工作,CALG_RC4根本没有加密b $ b加密,而CALG_RC2没有加密完全解密(声称

都成功了,但是对于前者,加密的字符串与输入完全相同,而后者则是解密后的字符串正好与加密字符串相同的

- 而且我认为我做的一切都是正确的(如果你认为你可以找到我没有的地方,那么底部是

。 ..)


所以我决定发明我自己的算法,我只是想要任何人的意见

如何安全可以与Win32 API版本。

首先,一个C#程序生成一个256字节的数组,如下所示:

使用System;

使用System .Security.Cryptography;

class Class1

{

[STAThread]

static void Main()

{

byte [] b_raw = new byte [256];

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

rng.GetBytes(b_raw);

Console.Write(" const BYTE b [] = {");

for(int i = 0;我< 256; i + = 8)

{

Console.WriteLine(" 0x {0:x},0x {1:x},0x {2:x},0x {3:x},0x {4:x},0x {5:x},

0x {6:x},0x {7:x},",

b_raw [i],b_raw [i + 1],b_raw [i + 2],b_raw [i + 3],b_raw [i + 4],b_raw [i + 5],

b_raw [i + 6],b_raw [i + 7]);

}

}

}

运行两次,所以我有两个256字节的数组,比如key1和key2。

然后将这些数组硬编码到C ++加密算法中。

然后,C ++加密算法如下:

它将_TCHAR数组memcp到一个字节数组,然后循环遍历

这个数组的每个字节。

For每个字节,它获取key1 [n]的值(其中n是字节数),

并调用这个''b_current_indir''(起始''间接级别'')。 />
然后,它得到key2 [n]的值并调用这个''levels'' -

间接级别的数量。

然后,内循环运行''水平''次 - 并且在每个循环中发生以下

:要加密的数据的当前字节(由外部

循环决定)与key2 [b_current_indir]进行异或,然后是THEN ,b_current_indir是

重新分配以获取key2 [b_current_indir]的值。


整个C ++算法定义如下:

void Decrypt(BYTE * orig,long bytelen,_TCHAR * dataout)

{

BYTE * b_temp = new BYTE [bytelen];

#ifdef _DEBUG

ZeroMemory(b_temp,bytelen);

#endif

for(long bytenum = 0; bytenum< bytelen; bytenum ++)

{

BYTE等级= b [bytenum%256],

b_current_indir = b2 [bytenum%256]; //总是开始相同

b_temp [(long)bytenum] = orig [(long)bytenum];

for(long level = 0; level< levels;等级++)

{

b_temp [(long)bytenum] ^ = b_current_indir;

b_current_indir = b2 [(long)b_current_indir];

}

}

memcpy(dataout,b_temp,bytelen);

delete [] b_temp;

}


无效加密(_TCHAR * orig,长文本,BYTE *数据输出)

{

long bytelen = textlen * sizeof(_TCHAR);

BYTE * b_temp = new BYTE [bytelen];

#ifdef _DEBUG

ZeroMemory(b_temp,bytelen );;

#endif

memcpy(b_temp,orig,bytelen);

for(long bytenum = 0; bytenum< bytelen; bytenum ++ )

{

BYTE等级= b [(长)(bytenum%256)],

b_current_indir = b2 [(长)(bytenum) %256)];

for(long level = 0; level< levels; level ++)

{

b_temp [(long)bytenum ] ^ = b_current_indir;

b_current_indir = b2 [(long)b_current_indir];

}

}

memcpy(dataout,b_temp,bytelen);

删除[] b_temp;

}


int main()

{

LPTSTR testtext = _T(" TheMagicBonj");

long textlen = _tcslen(testtext)+ 1;

BYTE * b_enc = new BYTE [textlen * sizeof(_TCHAR)];

#ifdef _DEBUG

ZeroMemory(b_enc,textlen * sizeof(_TCHAR));

#endif

加密(testtext,textlen,b_enc);

_TCHAR * t_enc = new _TCHAR [textlen];

ZeroMemory(t_enc,textlen * sizeof(_TCHAR) );

memcpy(t_enc,b_enc,textlen * sizeof(_TCHAR));

_tprintf(_T("加密文本是\"%s \ " \ n"),t_enc);

delete [] t_enc;


_TCHAR * t_dec = new _TCHAR [textlen];

Decrypt(b_enc,textlen * sizeof(_TCHAR),t_dec);

_tprintf(_T("解密文本是\"%s \" ; \ n"),t_dec);

delete [] t_dec;


}


似乎为了我的眼睛工作,但它是一堆垃圾吗?


我最初的想法是有人可以通过将

机器代码拆解成装配来破解它语言,发现DLL文件的全局命名空间位于哪里,并从中导出key1和key2,然后

只需将它们插回算法,不一定

从汇编语言中理解算法。但是比这更简单,如果他们发现它可能是*这个* DLL创建了* b $ b * *加密数据,所以如果我发现如何调用DLL,我可以解密

it。为了解决这个问题,我可以非常轻松地将密钥放在应用程序中。

但这有帮助吗?具有汇编语言知识的人能够以合理的准确度猜测PE文件中的一些数据是否可能是加密算法的关键?

如果我编写了一个使用Win32 API加密函数的DLL,对于那些想要破解它的人来说,这样做是不是很容易?

如果没有,为什么

不是?私钥加密的有效性和

一样好,你可以隐藏密钥吗?


请尽可能多的想法...


我的(不成功)尝试使用Win32 API如下:

BOOL GetData(_TCHAR * datain,long lendatain)

{

HCRYPTPROV hCryptProv;

HCRYPTHASH hCryptHash;

HCRYPTKEY hCryptKey;

DWORD bytelen =(lendatain + 10 )* sizeof(_TCHAR),databack = 0,bytesback

= 0;

BYTE * bData = new BYTE [bytelen];

_TCHAR * cryptdata = new _TCHAR [lendatain],

* decryptdata = new _TCHAR [lendatain];


BOOL bSuccess = CryptAcquireContext(& hCryptProv,keysetname,NULL ,

PROV_RSA_FULL,CRYPT_NEWKEYSET);

if(!bSuccess)bSuccess | = CryptAcquireContext(& hCryptProv,keysetname,

NULL,PROV_RSA_FULL, 0);

memcpy(bData,datain,bytelen);

bSuccess& = CryptCr eateHash(hCryptProv,CALG_MD5,0,0和& hCryptHash);

bSuccess& = CryptHashData(hCryptHash,(BYTE *)textkey,_tcslen(textkey),0);

bSuccess& = CryptDeriveKey(hCryptProv,CALG_RC2,hCryptHash,0,

& hCryptKey);

bSuccess& = CryptEncrypt(hCryptKey,hCryptHash,TRUE, 0,bData,& bytesback,

bytelen);

CryptDestroyKey(hCryptKey);

CryptDestroyHash(hCryptHash);

CryptReleaseContext(hCryptProv,0);

memcpy(cryptdata,bData,bytesback);

_tprintf(_T("加密数据是\,%) s \" \ n"),cryptdata);

bSuccess = CryptAcquireContext(& hCryptProv,keysetname,NULL,

PROV_RSA_FULL,CRYPT_NEWKEYSET);

if(!bSuccess)bSuccess | = CryptAcquireContext(& hCryptProv,keysetname,

NULL,PROV_RSA_FULL,0);

bSuccess& = CryptCreateHash( hCryptProv,CALG_MD5,0,0和& hCryptHash);

bSuccess & = CryptHashData(hCryptHash,(BYTE *)textkey,_tcslen(textkey),0);

bSuccess& = CryptDeriveKey(hCryptProv,CALG_RC2,hCryptHash,0,

& hCryptKey);

bSuccess& = CryptDecrypt(hCryptKey,hCryptHash,TRUE,0,bData,

& bytesback);

memcpy(decryptdata,bData,bytesback);

databack =(DWORD)(bytelen / sizeof(_TCHAR));

_tprintf(_T("解密数据是\"%s \" \ n"),decryptdata);


CryptDestroyKey(hCryptKey);

CryptDestroyHash(hCryptHash);

CryptReleaseContext(hCryptProv,0);


delete [] bData;

delete [] cryptdata;

delete [] decryptdata;

CryptDestroyKey(hCryptKey);

CryptDestroyHash(hCryptHash);

CryptReleaseContext(hCryptProv,0);


返回bSuccess;

}


无效测试(_TCHAR *字符串)

{

GetData(string,_tcslen(s。) tring));

}


int _tmain()

{

test(_T( TheMagicBonj));

返回0;

}

输出结果为:


加密数据是^ení& l ?? eMagicBo?

解密数据是@?2


这是令人失望的。

I was in need of an encryption algorithm to the following requirements:
1) Must be capable of encrypting strings to a byte array, and decyrpting
back again to the same string
2) Must have the same algorithm work with strings that may or may not be
unicode
3) Number of bytes back must either be <= number of _TCHARs in *
sizeof(_TCHAR), or the relation between output size and input size can be
calculated simply. Has to take into account the null terminator on the end
of the string.
4) Encryption algorithm must also return the exact number of bytes of the
encrypted data
I was struggling to get the CryptoAPI to work, with CALG_RC4 it didn''t
encrypt at all, and with CALG_RC2 it didn''t decrypt at all (both claimed to
have succeeded, but with the former, the encrypted string was exactly the
same as the input, and with the latter, the decrypted string was exactly the
same as the encrypted string) - and I thought I''d done everything right (at
the bottom if you reckon you can spot where I havent...)

So I decided to invent my own algorithm, and I just wanted anybody''s opinion
on how secure this could be compared to the Win32 API version.
First, a C# program generates an array of 256 bytes, as such:
using System;
using System.Security.Cryptography;
class Class1
{
[STAThread]
static void Main()
{
byte[] b_raw = new byte[256];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(b_raw);
Console.Write("const BYTE b[] = {");
for(int i = 0; i < 256; i += 8)
{
Console.WriteLine("0x{0:x}, 0x{1:x}, 0x{2:x}, 0x{3:x}, 0x{4:x}, 0x{5:x},
0x{6:x}, 0x{7:x},",
b_raw[i], b_raw[i+1], b_raw[i+2], b_raw[i+3], b_raw[i+4], b_raw[i+5],
b_raw[i+6], b_raw[i+7]);
}
}
}
This is run twice, so I have two arrays of 256 bytes, say key1 and key2.
These are then hardcoded into the C++ encryption algorithm.
Then, the C++ encryption algorithm goes as such:
It memcpys the _TCHAR array to a byte array, then loops round each byte of
this array.
For each byte, it gets the value of key1[n] (where n is the byte number),
and calls this ''b_current_indir'' (the starting ''indirection level'').
Then, it gets the value of key2[n] and calls this ''levels'' - the number of
indirection levels.
Then, an inner loop runs ''levels'' times - and on each loop the following
happens: the current byte of the data to be encrypted (dictated by the outer
loop) is XORed with key2[b_current_indir], and THEN, b_current_indir is
reassigned to take on the value of key2[b_current_indir].

The whole C++ algorithm is defined as such:
void Decrypt(BYTE* orig, long bytelen, _TCHAR* dataout)
{
BYTE* b_temp = new BYTE[bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp, bytelen);
#endif
for(long bytenum = 0; bytenum < bytelen; bytenum++)
{
BYTE levels = b[bytenum % 256],
b_current_indir = b2[bytenum % 256]; //always starts the same
b_temp[(long)bytenum] = orig[(long)bytenum];
for(long level = 0; level < levels; level++)
{
b_temp[(long)bytenum] ^= b_current_indir;
b_current_indir = b2[(long)b_current_indir];
}
}
memcpy(dataout, b_temp, bytelen);
delete[] b_temp;
}

void Encrypt(_TCHAR* orig, long textlen, BYTE* dataout)
{
long bytelen = textlen * sizeof(_TCHAR);
BYTE* b_temp = new BYTE[bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp, bytelen);
#endif
memcpy(b_temp, orig, bytelen);
for(long bytenum = 0; bytenum < bytelen; bytenum++)
{
BYTE levels = b[(long)(bytenum % 256)],
b_current_indir = b2[(long)(bytenum % 256)];
for(long level = 0; level < levels; level++)
{
b_temp[(long)bytenum] ^= b_current_indir;
b_current_indir = b2[(long)b_current_indir];
}
}
memcpy(dataout, b_temp, bytelen);
delete[] b_temp;
}

int main()
{
LPTSTR testtext = _T("TheMagicBonj");
long textlen = _tcslen(testtext) + 1;
BYTE* b_enc = new BYTE[textlen * sizeof(_TCHAR)];
#ifdef _DEBUG
ZeroMemory(b_enc, textlen * sizeof(_TCHAR));
#endif
Encrypt(testtext, textlen, b_enc);
_TCHAR* t_enc = new _TCHAR[textlen];
ZeroMemory(t_enc, textlen * sizeof(_TCHAR));
memcpy(t_enc, b_enc, textlen * sizeof(_TCHAR));
_tprintf(_T("The encrypted text is \"%s\"\n"), t_enc);
delete[] t_enc;

_TCHAR* t_dec = new _TCHAR[textlen];
Decrypt(b_enc, textlen * sizeof(_TCHAR), t_dec);
_tprintf(_T("The decrypted text is \"%s\"\n"), t_dec);
delete[] t_dec;

}

It seems to work to my eyes, but is it a pile of rubbish?

My initial thoughts were that somebody could crack it by disassembling the
machine code into assembly language, discovering where the global namespace
section of the DLL file was and deriving key1 and key2 from that, and then
just plugging them back through the algorithm, without necessarily
understanding the algorithm from the assembly language. But even simpler
than that, if they discovered that "it was probably *this* DLL that created
*that* encrypted data, so if I find out how to call the DLL, I can decrypt
it". To counter that, I could put the key in the application very easily.
But does this help? Could someone with a knowledge of assembly language
guess with a reasonable degree of accuracy which bit of data in a PE file
was likely to be a key to an encryption algorithm?
Wouldn''t it be just as easy for someone wanting to crack it to still do that
if I had written a DLL that used the Win32 API Crypto functions? If not, why
not? Is the effectiveness of private key cryptography only as good as how
well you can hide the key?

Please give as many thoughts as possible...

My (unsuccessful) attempt to use the Win32 API is as follows:
BOOL GetData(_TCHAR* datain, long lendatain)
{
HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;
DWORD bytelen = (lendatain + 10) * sizeof(_TCHAR), databack = 0, bytesback
= 0;
BYTE* bData = new BYTE[bytelen];
_TCHAR* cryptdata = new _TCHAR[lendatain],
* decryptdata = new _TCHAR[lendatain];

BOOL bSuccess = CryptAcquireContext(&hCryptProv, keysetname, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!bSuccess) bSuccess |= CryptAcquireContext(&hCryptProv, keysetname,
NULL, PROV_RSA_FULL, 0);
memcpy(bData, datain, bytelen);
bSuccess &= CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash);
bSuccess &= CryptHashData(hCryptHash, (BYTE*)textkey, _tcslen(textkey), 0);
bSuccess &= CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0,
&hCryptKey);
bSuccess &= CryptEncrypt(hCryptKey, hCryptHash, TRUE, 0, bData, &bytesback,
bytelen);
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);
memcpy(cryptdata, bData, bytesback);
_tprintf(_T("The encrypted data is \"%s\"\n"), cryptdata);
bSuccess = CryptAcquireContext(&hCryptProv, keysetname, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!bSuccess) bSuccess |= CryptAcquireContext(&hCryptProv, keysetname,
NULL, PROV_RSA_FULL, 0);
bSuccess &= CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash);
bSuccess &= CryptHashData(hCryptHash, (BYTE*)textkey, _tcslen(textkey), 0);
bSuccess &= CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0,
&hCryptKey);
bSuccess &= CryptDecrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback);
memcpy(decryptdata, bData, bytesback);
databack = (DWORD)(bytelen / sizeof(_TCHAR));
_tprintf(_T("The decrypted data is \"%s\"\n"), decryptdata);

CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

delete[] bData;
delete[] cryptdata;
delete[] decryptdata;
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

return bSuccess;
}

void test(_TCHAR* string)
{
GetData(string, _tcslen(string));
}

int _tmain()
{
test(_T("TheMagicBonj"));
return 0;
}
The output is:

The encrypted data is "^ení&l?eMagicBo"
The decrypted data is "@2"

which is disappointing.

推荐答案

Bonj,


见内联:
Bonj,

See inline:
1)必须能够将字符串加密到字节数组,并且再次将decyrpting返回到相同的字符串


所有加密算法都会执行此操作。如果你不能解密,那么

它将是一个哈希。

2)必须使用相同的算法处理字符串,可能是也可能不是
unicode


这应该不是问题。加密适用于字节流,而不是
字符串。只要字符串可以转换为字节流/从字节流转换,你就不会有问题。

3)返回的字节数必须是< ; = * sizeof(_TCHAR)中_TCHAR的数量,或者可以简单地计算输出大小和输入大小之间的关系。必须考虑字符串末尾的null终止符。


字符串末尾的空终止符只是另一个字节。如果你加价b $ b加密它,它会占用空间。如果你不需要它,不要用它

然后。至于输出大小,我认为它与输入

大小相同。

4)加密算法还必须返回

你的意思是它会返回它需要多少字节才能加密数据?由于大多数算法返回相同的大小,这不会是一个问题。


我建议不要滚动加密。相反,你应该使用System.Security.Cryptography命名空间中的一个类来使用
。如果

你也需要压缩,那么你可以在加密后申请。


希望这会有所帮助。

-

- Nicholas Paldino [.NET / C#MVP]

- mv * @ spam .guard.caspershouse.com

我很难让CryptoAPI工作,CALG_RC4它根本没有加密,而且CALG_RC2它没有''' t解密(两者都声称已经成功,但是对于前者,加密的字符串与输入完全相同,而对于后者,解密的字符串完全是
和加密的字符串相同) - 我以为我已经做好了一切正确(如果你认为你可以找到我在哪里,那就在底部......)

所以我决定发明自己的算法,我只是想要任何人对Win32 API版本的安全性的看法。
首先,C#程序生成一个256字节的数组,作为如:
使用System;
使用System.Security.Cryptography;
类Class1
{
[STAThread]
static void Main()
{
byte [] b_raw = new byte [256];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(b_raw);
Console.Write(" const BYTE b [] = {");
for(int i = 0;我< 256; i + = 8)
{
Console.WriteLine(" 0x {0:x},0x {1:x},0x {2:x},0x {3:x},0x { 4:x},0x {5:x},
0x {6:x},0x {7:x},",
b_raw [i],b_raw [i + 1],b_raw [i + 2],b_raw [i + 3],b_raw [i + 4],b_raw [i + 5],
b_raw [i + 6],b_raw [i + 7]);
这是运行两次,所以我有两个256字节的数组,比如key1和key2。
然后将这些数组硬编码到C ++加密算法中。
它将_TCHAR数组存储到一个字节数组,然后遍历该数组的每个字节。
对于每个字节,它得到key1 [n]的值(其中n是字节数),
并调用这个''b_current_indir''(起始''间接级别'')。
然后,它获取key2的值[n]并称之为级别 -
间接级别的数量。
然后,内部循环运行''级别''次 - 并且在每个循环中发生以下
:数据的当前字节为e ncrypted(由
外循环决定)与key2 [b_current_indir]进行异或,然后重新分配,以获取key2 [b_current_indir]的值。

整个C ++算法定义如下:
void Decrypt(BYTE * orig,long bytelen,_TCHAR * dataout)
{BYCH * b_temp = new BYTE [bytelen];
# ifdef _DEBUG
ZeroMemory(b_temp,bytelen);
#endif
for(long bytenum = 0; bytenum< bytelen; bytenum ++)
{
BYTE等级= b [bytenum%256],
b_current_indir = b2 [bytenum%256]; //总是开始相同的
b_temp [(long)bytenum] = orig [(long)bytenum];
for(long level = 0; level< levels; level ++)
{
b_temp [(long)bytenum] ^ = b_current_indir;
b_current_indir = b2 [(long)b_current_indir];
}
}
memcpy(dataout,b_temp,bytelen) ;
删除[] b_temp;
}
无效加密(_TCHAR * orig,长文本,BYTE *数据输出)
{/ / long longlen = textlen * sizeof(_TCHAR);
BYTE * b_temp = new BYTE [bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp,bytelen);
#endif
memcpy( b_temp,orig,bytelen);
for(long bytenum = 0; bytenum< bytelen; bytenum ++)
{
BYTE levels = b [(long)(bytenum%256)],
b_current_indir = b2 [(long)(bytenum%256)];
for(long level = 0; level< levels; level ++)
{
b_temp [(long)bytenum ] ^ = b_current_indir;
b_current_indir = b2 [(long)b_current_indir];
}
}
memcpy(dataout,b_temp,bytelen);
d elete [] b_temp;
}
int main()
{
LPTSTR testtext = _T(TheMagicBonj);
long textlen = _tcslen (testtext)+ 1;
BYTE * b_enc = new BYTE [textlen * sizeof(_TCHAR)];
#ifdef _DEBUG
ZeroMemory(b_enc,textlen * sizeof(_TCHAR));
#endif
加密(testtext,textlen,b_enc);
_TCHAR * t_enc = new _TCHAR [textlen];
ZeroMemory(t_enc,textlen * sizeof(_TCHAR));
memcpy(t_enc,b_enc,textlen * sizeof(_TCHAR));
_tprintf(_T(加密文本为\%s \" \ n"),t_enc);
删除[] t_enc;

_TCHAR * t_dec = new _TCHAR [textlen];
解密(b_enc,textlen * sizeof(_TCHAR),t_dec);
_tprintf(_T (解密的文本是\%s \\ n"),t_dec);
删除[] t_dec;

}

我最初的想法是有人可以通过拆卸它来破解它。将机器代码编写成汇编语言,发现DLL文件的全局
命名空间部分,从
派生key1和key2,然后只需将它们插回算法,而不必理解汇编语言的算法。但是,如果他们发现可能是*这个*
DLL创建了*那个*加密数据,那么甚至比这更简单,所以如果我找到如何调用
DLL,我可以解密它。为了解决这个问题,我可以非常轻松地将密钥放在
应用程序中。但这有帮助吗?具有汇编语言知识的人是否能够以合理的准确度猜测PE文件中的哪些数据可能是加密算法的关键?
如果我编写了一个使用Win32 API加密函数的DLL,那对于那些想破解它的人来说难道不是那么容易吗?如果没有,为什么不呢?私钥密码学的有效性是否与隐藏密钥的能力一样好?

请尽可能多地提出想法...

我的(不成功)尝试使用Win32 API如下:
BOOL GetData(_TCHAR * datain,long lendatain)
{HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;
DWORD bytelen =(lendatain + 10)* sizeof(_TCHAR),databack = 0,bytesback
= 0;
BYTE * bData = new BYTE [bytelen];
_TCHAR * cryptdata = new _TCHAR [lendatain],
* decryptdata = new _TCHAR [lendatain];

BOOL bSuccess = CryptAcquireContext(& hCryptProv,keysetname,NULL,
PROV_RSA_FULL ,CRYPT_NEWKEYSET);
if(!bSuccess)bSuccess | = CryptAcquireContext(& hCryptProv,keysetname,
NULL,PROV_RSA_FULL,0);
memcpy(bData,datain,bytelen);
bSuccess& = CryptCreateHash(hCryptProv,CALG_MD5,0,0,& hCryptHash);
bSuccess& = CryptHashData(hCrypt Hash,(BYTE *)textkey,_tcslen(textkey),
0);
bSuccess& = CryptDeriveKey(hCryptProv,CALG_RC2,hCryptHash,0,
&hCryptKey);
bSuccess& = CryptEncrypt(hCryptKey,hCryptHash,TRUE,0,bData,
&bytes.dackback,bytelen);
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv,0);
memcpy(cryptdata,bData,bytesback);
_tprintf(_T(加密数据是\%s \\\n), cryptdata);

bSuccess = CryptAcquireContext(& hCryptProv,keysetname,NULL,
PROV_RSA_FULL,CRYPT_NEWKEYSET);
if(!bSuccess)bSuccess | = CryptAcquireContext(& hCryptProv, keysetname,
NULL,PROV_RSA_FULL,0);
bSuccess& = CryptCreateHash(hCryptProv,CALG_MD5,0,0,& hCryptHash);
bSuccess& = CryptHashData(hCryptHash,(BYTE) *)textkey,_tcslen(textkey),
0);
bSuccess& = CryptDeriveKey(hCryptProv,CALG_RC2,hCryptHash,0,
&h; CryptKey);
bSuccess& = CryptDecrypt(hCryptKey,hCryptHash,TRUE,0,bData,
&bytesback);
memcpy(decryptdata,bData,bytesback);
数据包=(DWORD)(bytelen / sizeof(_TCHAR));
_tprintf(_T(解密数据为\%s \&n),decryptdata);

CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv,0);

delete [] bData;
delete [] cryptdata ;
delete [] decryptdata;
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv,0);

返回bSuccess;
}

void test(_TCHAR * string)
{GetData(string,_tcslen(string));
}

int _tmain()
{
测试(_T(TheMagicBonj));
返回0;
}
输出结果为:

加密数据是^ení& l ?? eMagicBo?
解密数据是@?2

令人失望。
1) Must be capable of encrypting strings to a byte array, and decyrpting
back again to the same string
All encryption algorithms do this. If you couldn''t decrypt back, then
it would be a hash.
2) Must have the same algorithm work with strings that may or may not be
unicode
This should not be an issue. Encryption works on byte streams, not
strings. As long as the string can be converted to/from a byte stream, you
won''t have a problem.
3) Number of bytes back must either be <= number of _TCHARs in *
sizeof(_TCHAR), or the relation between output size and input size can be
calculated simply. Has to take into account the null terminator on the end
of the string.
The null terminator at the end of a string is just another byte. If you
encrypt it, it''s going to take up space. If you don''t need it, don''t use it
then. As for the output size, I believe that it is the same as the input
size.
4) Encryption algorithm must also return the exact number of bytes of the
encrypted data
Do you mean that it will return the number of bytes it would take to
encrypt the data? Since most algorithms return the same size, this won''t be
a problem.

I would recommend against rolling your encryption. Rather, you should
use one of the classes in the System.Security.Cryptography namespace. If
you need compression as well, then you can apply that after the encryption.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
I was struggling to get the CryptoAPI to work, with CALG_RC4 it didn''t
encrypt at all, and with CALG_RC2 it didn''t decrypt at all (both claimed
to have succeeded, but with the former, the encrypted string was exactly
the same as the input, and with the latter, the decrypted string was
exactly the same as the encrypted string) - and I thought I''d done
everything right (at the bottom if you reckon you can spot where I
havent...)

So I decided to invent my own algorithm, and I just wanted anybody''s
opinion on how secure this could be compared to the Win32 API version.
First, a C# program generates an array of 256 bytes, as such:
using System;
using System.Security.Cryptography;
class Class1
{
[STAThread]
static void Main()
{
byte[] b_raw = new byte[256];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(b_raw);
Console.Write("const BYTE b[] = {");
for(int i = 0; i < 256; i += 8)
{
Console.WriteLine("0x{0:x}, 0x{1:x}, 0x{2:x}, 0x{3:x}, 0x{4:x}, 0x{5:x},
0x{6:x}, 0x{7:x},",
b_raw[i], b_raw[i+1], b_raw[i+2], b_raw[i+3], b_raw[i+4], b_raw[i+5],
b_raw[i+6], b_raw[i+7]);
}
}
}
This is run twice, so I have two arrays of 256 bytes, say key1 and key2.
These are then hardcoded into the C++ encryption algorithm.
Then, the C++ encryption algorithm goes as such:
It memcpys the _TCHAR array to a byte array, then loops round each byte of
this array.
For each byte, it gets the value of key1[n] (where n is the byte number),
and calls this ''b_current_indir'' (the starting ''indirection level'').
Then, it gets the value of key2[n] and calls this ''levels'' - the number of
indirection levels.
Then, an inner loop runs ''levels'' times - and on each loop the following
happens: the current byte of the data to be encrypted (dictated by the
outer loop) is XORed with key2[b_current_indir], and THEN, b_current_indir
is reassigned to take on the value of key2[b_current_indir].

The whole C++ algorithm is defined as such:
void Decrypt(BYTE* orig, long bytelen, _TCHAR* dataout)
{
BYTE* b_temp = new BYTE[bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp, bytelen);
#endif
for(long bytenum = 0; bytenum < bytelen; bytenum++)
{
BYTE levels = b[bytenum % 256],
b_current_indir = b2[bytenum % 256]; //always starts the same
b_temp[(long)bytenum] = orig[(long)bytenum];
for(long level = 0; level < levels; level++)
{
b_temp[(long)bytenum] ^= b_current_indir;
b_current_indir = b2[(long)b_current_indir];
}
}
memcpy(dataout, b_temp, bytelen);
delete[] b_temp;
}

void Encrypt(_TCHAR* orig, long textlen, BYTE* dataout)
{
long bytelen = textlen * sizeof(_TCHAR);
BYTE* b_temp = new BYTE[bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp, bytelen);
#endif
memcpy(b_temp, orig, bytelen);
for(long bytenum = 0; bytenum < bytelen; bytenum++)
{
BYTE levels = b[(long)(bytenum % 256)],
b_current_indir = b2[(long)(bytenum % 256)];
for(long level = 0; level < levels; level++)
{
b_temp[(long)bytenum] ^= b_current_indir;
b_current_indir = b2[(long)b_current_indir];
}
}
memcpy(dataout, b_temp, bytelen);
delete[] b_temp;
}

int main()
{
LPTSTR testtext = _T("TheMagicBonj");
long textlen = _tcslen(testtext) + 1;
BYTE* b_enc = new BYTE[textlen * sizeof(_TCHAR)];
#ifdef _DEBUG
ZeroMemory(b_enc, textlen * sizeof(_TCHAR));
#endif
Encrypt(testtext, textlen, b_enc);
_TCHAR* t_enc = new _TCHAR[textlen];
ZeroMemory(t_enc, textlen * sizeof(_TCHAR));
memcpy(t_enc, b_enc, textlen * sizeof(_TCHAR));
_tprintf(_T("The encrypted text is \"%s\"\n"), t_enc);
delete[] t_enc;

_TCHAR* t_dec = new _TCHAR[textlen];
Decrypt(b_enc, textlen * sizeof(_TCHAR), t_dec);
_tprintf(_T("The decrypted text is \"%s\"\n"), t_dec);
delete[] t_dec;

}

It seems to work to my eyes, but is it a pile of rubbish?

My initial thoughts were that somebody could crack it by disassembling the
machine code into assembly language, discovering where the global
namespace section of the DLL file was and deriving key1 and key2 from
that, and then just plugging them back through the algorithm, without
necessarily understanding the algorithm from the assembly language. But
even simpler than that, if they discovered that "it was probably *this*
DLL that created *that* encrypted data, so if I find out how to call the
DLL, I can decrypt it". To counter that, I could put the key in the
application very easily. But does this help? Could someone with a
knowledge of assembly language guess with a reasonable degree of accuracy
which bit of data in a PE file was likely to be a key to an encryption
algorithm?
Wouldn''t it be just as easy for someone wanting to crack it to still do
that if I had written a DLL that used the Win32 API Crypto functions? If
not, why not? Is the effectiveness of private key cryptography only as
good as how well you can hide the key?

Please give as many thoughts as possible...

My (unsuccessful) attempt to use the Win32 API is as follows:
BOOL GetData(_TCHAR* datain, long lendatain)
{
HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;
DWORD bytelen = (lendatain + 10) * sizeof(_TCHAR), databack = 0, bytesback
= 0;
BYTE* bData = new BYTE[bytelen];
_TCHAR* cryptdata = new _TCHAR[lendatain],
* decryptdata = new _TCHAR[lendatain];

BOOL bSuccess = CryptAcquireContext(&hCryptProv, keysetname, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!bSuccess) bSuccess |= CryptAcquireContext(&hCryptProv, keysetname,
NULL, PROV_RSA_FULL, 0);
memcpy(bData, datain, bytelen);
bSuccess &= CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash);
bSuccess &= CryptHashData(hCryptHash, (BYTE*)textkey, _tcslen(textkey),
0);
bSuccess &= CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0,
&hCryptKey);
bSuccess &= CryptEncrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback, bytelen);
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);
memcpy(cryptdata, bData, bytesback);
_tprintf(_T("The encrypted data is \"%s\"\n"), cryptdata);
bSuccess = CryptAcquireContext(&hCryptProv, keysetname, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!bSuccess) bSuccess |= CryptAcquireContext(&hCryptProv, keysetname,
NULL, PROV_RSA_FULL, 0);
bSuccess &= CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash);
bSuccess &= CryptHashData(hCryptHash, (BYTE*)textkey, _tcslen(textkey),
0);
bSuccess &= CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0,
&hCryptKey);
bSuccess &= CryptDecrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback);
memcpy(decryptdata, bData, bytesback);
databack = (DWORD)(bytelen / sizeof(_TCHAR));
_tprintf(_T("The decrypted data is \"%s\"\n"), decryptdata);

CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

delete[] bData;
delete[] cryptdata;
delete[] decryptdata;
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

return bSuccess;
}

void test(_TCHAR* string)
{
GetData(string, _tcslen(string));
}

int _tmain()
{
test(_T("TheMagicBonj"));
return 0;
}
The output is:

The encrypted data is "^ení&l?eMagicBo"
The decrypted data is "@2"

which is disappointing.



>你的意思是它会返回
> Do you mean that it will return the number of bytes it would take to
加密数据所需的字节数吗?


加密数据的总长度(以字节为单位),是的。


由于大多数算法都返回相同的大小,因此不会一个问题。


这很好,这就是我所希望的。

我建议不要滚动你的加密。


是的,但为什么?为什么有人能够破解我自己的本土

加密,而他们无法破解使用

加密API的那个?

我的好奇心是:
encrypt the data?
The total length in bytes of the encrypted data, yes.

Since most algorithms return the same size, this won''t be a problem.
That''s fine them, this is what I was hoping.

I would recommend against rolling your encryption.
Yes, but why? Why would somebody be able to crack my own home-grown
encryption, whereas they wouldn''t be able to crack one that used a
Cryptographic API?
My main line of curiosity is this:
我最初的想法是有人可以通过将机器代码拆解成汇编语言来破解它,发现DLL文件的全局
命名空间部分,从
派生key1和key2,然后只需将它们插回算法,而不必从程序集中理解算法语言。但是,如果他们发现可能是*这个*
DLL创建了*那个*加密数据,那么甚至比这更简单,所以如果我找到如何调用
DLL,我可以解密它。为了解决这个问题,我可以非常轻松地将密钥放在
应用程序中。但这有帮助吗?具有汇编语言知识的人是否能够以合理的准确度猜测PE文件中的哪些数据可能是加密算法的关键?
如果我编写了一个使用Win32 API加密函数的DLL,那对于那些想破解它的人来说难道不是那么容易吗?如果没有,为什么不呢?私钥加密的有效性仅仅是因为你能隐藏密钥的好吗?
My initial thoughts were that somebody could crack it by disassembling
the machine code into assembly language, discovering where the global
namespace section of the DLL file was and deriving key1 and key2 from
that, and then just plugging them back through the algorithm, without
necessarily understanding the algorithm from the assembly language. But
even simpler than that, if they discovered that "it was probably *this*
DLL that created *that* encrypted data, so if I find out how to call the
DLL, I can decrypt it". To counter that, I could put the key in the
application very easily. But does this help? Could someone with a
knowledge of assembly language guess with a reasonable degree of accuracy
which bit of data in a PE file was likely to be a key to an encryption
algorithm?
Wouldn''t it be just as easy for someone wanting to crack it to still do
that if I had written a DLL that used the Win32 API Crypto functions? If
not, why not? Is the effectiveness of private key cryptography only as
good as how well you can hide the key?




相反,你应该使用其中一个
System.Security.Cryptography命名空间中的类。如果您还需要压缩,那么您可以在加密后应用它。


我想以无管理的方式做这件事...对不起,我应该指出

那个。

我不需要压缩。

希望这会有所帮助。

-
- Nicholas Paldino [.NET / C#MVP]
- < a href =mailto:mv*@spam.guard.caspershouse.com> mv*@spam.guard.caspershouse.com

我很难得到CryptoAPI工作,CALG_RC4根本没有加密,而CALG_RC2根本没有解密(两者都声称已经成功,但是对于前者,加密的字符串是与输入完全相同,对于后者,解密后的字符串与加密字符串完全相同) - 我以为我已经做好了一切正确(在如果你认为你可以找到我无法找到的地方... ...

所以我决定发明我自己的算法,我只是想要任何人对如何评价的意见确保这一点可以与Win32 API版本进行比较。
首先,C#程序生成一个256字节的数组,如下所示:
使用System;
使用System.Security.Cryptography;
class Class1
{
[STAThread]
static void Main()
{byte /] b_raw = new byte [256];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(b_raw);
Console.Write(" const BYTE b [] = {");
for(int i = 0;我< 256; i + = 8)
{
Console.WriteLine(" 0x {0:x},0x {1:x},0x {2:x},0x {3:x},0x { 4:x},
0x {5:x},0x {6:x},0x {7:x},",
b_raw [i],b_raw [i + 1],b_raw [i + 2],b_raw [i + 3],b_raw [i + 4],b_raw [i + 5],
b_raw [i + 6],b_raw [i + 7]);
这是运行两次,所以我有两个256字节的数组,比如key1和key2。
然后将这些数组硬编码到C ++加密算法中。
它将_TCHAR数组存储到一个字节数组,然后循环遍历该数组的每个字节。
对于每个字节,它获取key1 [n]的值(其中n是字节数),
并调用这个''b_current_indir''(起始''间接级别'')。
然后,它获取key2的值[n]并称之为''级别'' - 间接级别的数量。
然后,内循环运行''级别''次 - 并且在每个循环中发生以下
:数据的当前字节为e ncrypted(由
外循环决定)与key2 [b_current_indir]进行异或,然后,重新分配b_current_indir以取值
key2 [b_current_indir]。
<整个C ++算法定义如下:
void Decrypt(BYTE * orig,long bytelen,_TCHAR * dataout)
{BY / B_temp = new BYTE [bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp,bytelen);
#endif
for(long bytenum = 0; bytenum< bytelen; bytenum ++)
{
BYTE等级= b [bytenum%256],
b_current_indir = b2 [bytenum%256]; //总是开始相同的
b_temp [(long)bytenum] = orig [(long)bytenum];
for(long level = 0; level< levels; level ++)
{
b_temp [(long)bytenum] ^ = b_current_indir;
b_current_indir = b2 [(long)b_current_indir];
}
}
memcpy(dataout,b_temp,bytelen) ;
删除[] b_temp;
}
无效加密(_TCHAR * orig,长文本,BYTE *数据输出)
{/ / long longlen = textlen * sizeof(_TCHAR);
BYTE * b_temp = new BYTE [bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp,bytelen);
#endif
memcpy( b_temp,orig,bytelen);
for(long bytenum = 0; bytenum< bytelen; bytenum ++)
{
BYTE levels = b [(long)(bytenum%256)],
b_current_indir = b2 [(long)(bytenum%256)];
for(long level = 0; level< levels; level ++)
{
b_temp [(long)bytenum ] ^ = b_current_indir;
b_current_indir = b2 [(long)b_current_indir];
}
}
memcpy(dataout,b_temp,bytelen);
d elete [] b_temp;
}
int main()
{
LPTSTR testtext = _T(TheMagicBonj);
long textlen = _tcslen (testtext)+ 1;
BYTE * b_enc = new BYTE [textlen * sizeof(_TCHAR)];
#ifdef _DEBUG
ZeroMemory(b_enc,textlen * sizeof(_TCHAR));
#endif
加密(testtext,textlen,b_enc);
_TCHAR * t_enc = new _TCHAR [textlen];
ZeroMemory(t_enc,textlen * sizeof(_TCHAR));
memcpy(t_enc,b_enc,textlen * sizeof(_TCHAR));
_tprintf(_T(加密文本为\%s \" \ n"),t_enc);
删除[] t_enc;

_TCHAR * t_dec = new _TCHAR [textlen];
解密(b_enc,textlen * sizeof(_TCHAR),t_dec);
_tprintf(_T (解密的文本是\%s \\ n"),t_dec);
删除[] t_dec;

}

我最初的想法是有人可以通过拆解它来破解它将机器代码编写成汇编语言,发现DLL文件的全局
命名空间部分,从
派生key1和key2,然后只需将它们插回算法,而不必理解汇编语言的算法。但是,如果他们发现可能是*这个*
DLL创建了*那个*加密数据,那么甚至比这更简单,所以如果我找到如何调用
DLL,我可以解密它。为了解决这个问题,我可以非常轻松地将密钥放在
应用程序中。但这有帮助吗?具有汇编语言知识的人是否能够以合理的准确度猜测PE文件中的哪些数据可能是加密算法的关键?
如果我编写了一个使用Win32 API加密函数的DLL,那对于那些想破解它的人来说难道不是那么容易吗?如果没有,为什么不呢?私钥密码学的有效性是否与隐藏密钥的能力一样好?

请尽可能多地提出想法...

我的(不成功)尝试使用Win32 API如下:
BOOL GetData(_TCHAR * datain,long lendatain)
{HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;
DWORD bytelen =(lendatain + 10)* sizeof(_TCHAR),databack = 0,
bytesback = 0;
BYTE * bData = new BYTE [bytelen];
_TCHAR * cryptdata = new _TCHAR [lendatain],
* decryptdata = new _TCHAR [lendatain];

BOOL bSuccess = CryptAcquireContext(& hCryptProv,keysetname,NULL,
PROV_RSA_FULL ,CRYPT_NEWKEYSET);
if(!bSuccess)bSuccess | = CryptAcquireContext(& hCryptProv,keysetname,
NULL,PROV_RSA_FULL,0);
memcpy(bData,datain,bytelen);
bSuccess& = CryptCreateHash(hCryptProv,CALG_MD5,0,0,& hCryptHash);
bSuccess& = CryptHashData(hCrypt Hash,(BYTE *)textkey,_tcslen(textkey),
0);
bSuccess& = CryptDeriveKey(hCryptProv,CALG_RC2,hCryptHash,0,
&hCryptKey);
bSuccess& = CryptEncrypt(hCryptKey,hCryptHash,TRUE,0,bData,
&bytes.dackback,bytelen);
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv,0);
memcpy(cryptdata,bData,bytesback);
_tprintf(_T(加密数据是\%s \\\n), cryptdata);

bSuccess = CryptAcquireContext(& hCryptProv,keysetname,NULL,
PROV_RSA_FULL,CRYPT_NEWKEYSET);
if(!bSuccess)bSuccess | = CryptAcquireContext(& hCryptProv, keysetname,
NULL,PROV_RSA_FULL,0);
bSuccess& = CryptCreateHash(hCryptProv,CALG_MD5,0,0,& hCryptHash);
bSuccess& = CryptHashData(hCryptHash,(BYTE) *)textkey,_tcslen(textkey),
0);
bSuccess& = CryptDeriveKey(hCryptProv,CALG_RC2,hCryptHash,0,
&h; CryptKey);
bSuccess &= CryptDecrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback);
memcpy(decryptdata, bData, bytesback);
databack = (DWORD)(bytelen / sizeof(_TCHAR));
_tprintf(_T("The decrypted data is \"%s\"\n"), decryptdata);

CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

delete[] bData;
delete[] cryptdata;
delete[] decryptdata;
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

return bSuccess;
}

void test(_TCHAR* string)
{
GetData(string, _tcslen(string));
}

int _tmain()
{
test(_T("TheMagicBonj"));
return 0;
}
The output is:

The encrypted data is "^ení&l??eMagicBo?"
The decrypted data is "@?2"

which is disappointing.
I was struggling to get the CryptoAPI to work, with CALG_RC4 it didn''t
encrypt at all, and with CALG_RC2 it didn''t decrypt at all (both claimed
to have succeeded, but with the former, the encrypted string was exactly
the same as the input, and with the latter, the decrypted string was
exactly the same as the encrypted string) - and I thought I''d done
everything right (at the bottom if you reckon you can spot where I
havent...)

So I decided to invent my own algorithm, and I just wanted anybody''s
opinion on how secure this could be compared to the Win32 API version.
First, a C# program generates an array of 256 bytes, as such:
using System;
using System.Security.Cryptography;
class Class1
{
[STAThread]
static void Main()
{
byte[] b_raw = new byte[256];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(b_raw);
Console.Write("const BYTE b[] = {");
for(int i = 0; i < 256; i += 8)
{
Console.WriteLine("0x{0:x}, 0x{1:x}, 0x{2:x}, 0x{3:x}, 0x{4:x},
0x{5:x}, 0x{6:x}, 0x{7:x},",
b_raw[i], b_raw[i+1], b_raw[i+2], b_raw[i+3], b_raw[i+4], b_raw[i+5],
b_raw[i+6], b_raw[i+7]);
}
}
}
This is run twice, so I have two arrays of 256 bytes, say key1 and key2.
These are then hardcoded into the C++ encryption algorithm.
Then, the C++ encryption algorithm goes as such:
It memcpys the _TCHAR array to a byte array, then loops round each byte
of this array.
For each byte, it gets the value of key1[n] (where n is the byte number),
and calls this ''b_current_indir'' (the starting ''indirection level'').
Then, it gets the value of key2[n] and calls this ''levels'' - the number
of indirection levels.
Then, an inner loop runs ''levels'' times - and on each loop the following
happens: the current byte of the data to be encrypted (dictated by the
outer loop) is XORed with key2[b_current_indir], and THEN,
b_current_indir is reassigned to take on the value of
key2[b_current_indir].

The whole C++ algorithm is defined as such:
void Decrypt(BYTE* orig, long bytelen, _TCHAR* dataout)
{
BYTE* b_temp = new BYTE[bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp, bytelen);
#endif
for(long bytenum = 0; bytenum < bytelen; bytenum++)
{
BYTE levels = b[bytenum % 256],
b_current_indir = b2[bytenum % 256]; //always starts the same
b_temp[(long)bytenum] = orig[(long)bytenum];
for(long level = 0; level < levels; level++)
{
b_temp[(long)bytenum] ^= b_current_indir;
b_current_indir = b2[(long)b_current_indir];
}
}
memcpy(dataout, b_temp, bytelen);
delete[] b_temp;
}

void Encrypt(_TCHAR* orig, long textlen, BYTE* dataout)
{
long bytelen = textlen * sizeof(_TCHAR);
BYTE* b_temp = new BYTE[bytelen];
#ifdef _DEBUG
ZeroMemory(b_temp, bytelen);
#endif
memcpy(b_temp, orig, bytelen);
for(long bytenum = 0; bytenum < bytelen; bytenum++)
{
BYTE levels = b[(long)(bytenum % 256)],
b_current_indir = b2[(long)(bytenum % 256)];
for(long level = 0; level < levels; level++)
{
b_temp[(long)bytenum] ^= b_current_indir;
b_current_indir = b2[(long)b_current_indir];
}
}
memcpy(dataout, b_temp, bytelen);
delete[] b_temp;
}

int main()
{
LPTSTR testtext = _T("TheMagicBonj");
long textlen = _tcslen(testtext) + 1;
BYTE* b_enc = new BYTE[textlen * sizeof(_TCHAR)];
#ifdef _DEBUG
ZeroMemory(b_enc, textlen * sizeof(_TCHAR));
#endif
Encrypt(testtext, textlen, b_enc);
_TCHAR* t_enc = new _TCHAR[textlen];
ZeroMemory(t_enc, textlen * sizeof(_TCHAR));
memcpy(t_enc, b_enc, textlen * sizeof(_TCHAR));
_tprintf(_T("The encrypted text is \"%s\"\n"), t_enc);
delete[] t_enc;

_TCHAR* t_dec = new _TCHAR[textlen];
Decrypt(b_enc, textlen * sizeof(_TCHAR), t_dec);
_tprintf(_T("The decrypted text is \"%s\"\n"), t_dec);
delete[] t_dec;

}

It seems to work to my eyes, but is it a pile of rubbish?

My initial thoughts were that somebody could crack it by disassembling
the machine code into assembly language, discovering where the global
namespace section of the DLL file was and deriving key1 and key2 from
that, and then just plugging them back through the algorithm, without
necessarily understanding the algorithm from the assembly language. But
even simpler than that, if they discovered that "it was probably *this*
DLL that created *that* encrypted data, so if I find out how to call the
DLL, I can decrypt it". To counter that, I could put the key in the
application very easily. But does this help? Could someone with a
knowledge of assembly language guess with a reasonable degree of accuracy
which bit of data in a PE file was likely to be a key to an encryption
algorithm?
Wouldn''t it be just as easy for someone wanting to crack it to still do
that if I had written a DLL that used the Win32 API Crypto functions? If
not, why not? Is the effectiveness of private key cryptography only as
good as how well you can hide the key?

Please give as many thoughts as possible...

My (unsuccessful) attempt to use the Win32 API is as follows:
BOOL GetData(_TCHAR* datain, long lendatain)
{
HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;
DWORD bytelen = (lendatain + 10) * sizeof(_TCHAR), databack = 0,
bytesback = 0;
BYTE* bData = new BYTE[bytelen];
_TCHAR* cryptdata = new _TCHAR[lendatain],
* decryptdata = new _TCHAR[lendatain];

BOOL bSuccess = CryptAcquireContext(&hCryptProv, keysetname, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!bSuccess) bSuccess |= CryptAcquireContext(&hCryptProv, keysetname,
NULL, PROV_RSA_FULL, 0);
memcpy(bData, datain, bytelen);
bSuccess &= CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash);
bSuccess &= CryptHashData(hCryptHash, (BYTE*)textkey, _tcslen(textkey),
0);
bSuccess &= CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0,
&hCryptKey);
bSuccess &= CryptEncrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback, bytelen);
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);
memcpy(cryptdata, bData, bytesback);
_tprintf(_T("The encrypted data is \"%s\"\n"), cryptdata);
bSuccess = CryptAcquireContext(&hCryptProv, keysetname, NULL,
PROV_RSA_FULL, CRYPT_NEWKEYSET);
if(!bSuccess) bSuccess |= CryptAcquireContext(&hCryptProv, keysetname,
NULL, PROV_RSA_FULL, 0);
bSuccess &= CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hCryptHash);
bSuccess &= CryptHashData(hCryptHash, (BYTE*)textkey, _tcslen(textkey),
0);
bSuccess &= CryptDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0,
&hCryptKey);
bSuccess &= CryptDecrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback);
memcpy(decryptdata, bData, bytesback);
databack = (DWORD)(bytelen / sizeof(_TCHAR));
_tprintf(_T("The decrypted data is \"%s\"\n"), decryptdata);

CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

delete[] bData;
delete[] cryptdata;
delete[] decryptdata;
CryptDestroyKey(hCryptKey);
CryptDestroyHash(hCryptHash);
CryptReleaseContext(hCryptProv, 0);

return bSuccess;
}

void test(_TCHAR* string)
{
GetData(string, _tcslen(string));
}

int _tmain()
{
test(_T("TheMagicBonj"));
return 0;
}
The output is:

The encrypted data is "^ení&l?eMagicBo"
The decrypted data is "@2"

which is disappointing.




"Bonj" wrote:
"Bonj" wrote:
Yes, but why? Why would somebody be able to crack my own home-grown
encryption, whereas they wouldn’’t be able to crack one that used a
Cryptographic API?
Yes, but why? Why would somebody be able to crack my own home-grown
encryption, whereas they wouldn''t be able to crack one that used a
Cryptographic API?




.... because you have no chance - zero chance - of coming up on your own with

a crypto algorithm that will be much more secure than rot13. It’’s very easy

to create an encryption that you yourself cannot break, but this is a very

low standard. Lots of other people have done this and become laughingstocks

because anybody with even minor amounts of crypto training can crack this

stuff. Some do it for sport.


This is just a foolish, foolish idea: read some of Bruce Schneier’’s

"Crypto-Grams" to see others that have been in the Doghouse for this.


DO NOT ROLL YOUR OWN. Figure out how to use good algorithms.


Steve



.... because you have no chance - zero chance - of coming up on your own with
a crypto algorithm that will be much more secure than rot13. It''s very easy
to create an encryption that you yourself cannot break, but this is a very
low standard. Lots of other people have done this and become laughingstocks
because anybody with even minor amounts of crypto training can crack this
stuff. Some do it for sport.

This is just a foolish, foolish idea: read some of Bruce Schneier''s
"Crypto-Grams" to see others that have been in the Doghouse for this.

DO NOT ROLL YOUR OWN. Figure out how to use good algorithms.

Steve


这篇关于这个加密算法有多好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆