By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,650 Members | 1,823 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,650 IT Pros & Developers. It's quick & easy.

How good an encryption algorithm is this?

P: n/a
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 "^n&leMagicBo"
The decrypted data is "@2"

which is disappointing.
Nov 16 '05 #1
Share this Question
Share on Google+
113 Replies


P: n/a
Bonj,

See inline:
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 "^n&leMagicBo"
The decrypted data is "@2"

which is disappointing.

Nov 16 '05 #2

P: n/a
> Do you mean that it will return the number of bytes it would take to
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:
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?


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.
I am wanting to do it in an unmanaged way...sorry, I should have pointed
that out.
I don't need compression.

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 "^n&leMagicBo"
The decrypted data is "@2"

which is disappointing.


Nov 16 '05 #3

P: n/a
"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?


.... 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
Nov 16 '05 #4

P: n/a
On Mon, 22 Nov 2004 15:02:33 -0500, "Nicholas Paldino [.NET/C# MVP]"
<mv*@spam.guard.caspershouse.com> wrote:
Bonj,

See inline:
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.


I agree with the first two sentences, but compression should be done
before encryption, since encrypted data does not usually compress
well.

--
Sev
Nov 16 '05 #5

P: n/a
Very well put Steve. To presume that you can even come close to the
encryption level of other popular methods is foolish...especially with a
simple iterative XOR algorithm (a common approach for fast, but not
terribly-secure, encryption). I highly recommend you use proven,
time-tested encryption methods if you want to prevent someone from accessing
your data. Just the knowledge of your software using its own proprietary
encryption method may, in fact, invite trouble.

Also note that any encryption method that _relies_ on hiding the algorithm
(or its keys) is inherently insecure. I mean, you don't store your housekey
in the keyhole of your front door do you?

I have a couple questions:
1) Exactly what are you trying to encrypt?
2) Why do you want to avoid using the framework encryption classes (which
are based on proven methods)?

ShaneB
... 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

Nov 16 '05 #6

P: n/a
"Severian" <se******@chlamydia-is-not-a-flower.com> wrote in message
On Mon, 22 Nov 2004 15:02:33 -0500, "Nicholas Paldino [.NET/C# MVP]"

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.


I agree with the first two sentences, but compression should be done
before encryption, since encrypted data does not usually compress
well.


Exactly. In fact, compressing the output of an encryptor is a low-grade
test for quality encryption. Well encrypted data is by definition not
compressible (it's indistiguishable from random noise).

More to the point, compressing the data before encryption increases the
entropy of the data. This in turn can only improve the quality of the
encryption.

-cd
Nov 16 '05 #7

P: n/a
"Bonj" <benjtaylor at hotpop d0t com> wrote in message
news:Ou**************@TK2MSFTNGP14.phx.gbl
My (unsuccessful) attempt to use the Win32 API is as follows:
BOOL GetData(_TCHAR* datain, long lendatain)
{
DWORD bytelen = (lendatain + 10) * sizeof(_TCHAR), databack = 0,
bytesback = 0;
BYTE* bData = new BYTE[bytelen];

memcpy(bData, datain, bytelen);
Note that you are reading 10*sizeof(TCHAR) bytes past the end of datain
buffer here. In the worst case, your program can crash. If it does not,
you will have garbage at the end of bData.
bSuccess &= CryptEncrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback, bytelen);
Here's your problem. bytesback is an [in, out] parameter. On input, it's
the number of bytes to encrypt. On output, it's the number of encrypted
bytes successfully written. You are passing 0 on input, asking to
encrypt zero bytes.

Oh, and you don't need to pass hCryptHash. It does not do what you seem
to think it does. It's harmless, but makes the API do the unnecessary
work.
memcpy(cryptdata, bData, bytesback);
_tprintf(_T("The encrypted data is \"%s\"\n"), cryptdata);
Encrypted data may very well contain NUL bytes inside, or it may not
contain any, not even at the end. Your printf output will either be
shortened, or will result in a buffer overrun and possibly a crash.
Encryption produces a binary byte stream, not a nice NUL-terminated
string.
bSuccess &= CryptDecrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback);
Again, you don't need to pass hCryptHash.
memcpy(decryptdata, bData, bytesback);
databack = (DWORD)(bytelen / sizeof(_TCHAR));
Note that you never change bytelen after it was initially calculated
from lendatain. You can simply write databack = lendatain + 10 (what is
this +10 doing here anyway? )
_tprintf(_T("The decrypted data is \"%s\"\n"), decryptdata);


When encrypting, you didn't include the terminating NUL character. So
decrypted data is not NUL-terminated either (if only accidentally).
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #8

P: n/a
Bonj... Inline.
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?<

The idea is that the best encryption algorithm is one that has been made
public for many years and no cryptographer can break it except by brute
force. The cost of breaking the data encrypted by a public algorithm
should
be greater than the value of the data.
I am wanting to do it in an unmanaged way...sorry, I should have

pointed
that out.<

I am using alleged RC4 source code in C, but RC4 is no longer
unconditionally
secure. You should be able to compile ARC4 for streams or char arrays of
fixed size, just don't use strlen on the encrypted array since it stops
at null.

Check out Applied Cryptography v2.0 by Schneier.

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #9

P: n/a
<"Bonj" <benjtaylor at hotpop d0t com>> wrote:
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.


I am wanting to do it in an unmanaged way...sorry, I should have pointed
that out.


If you want to do it in an unmanaged way, you shouldn't be looking at
C# to start with - all C# code is managed.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #10

P: n/a
> Note that you are reading 10*sizeof(TCHAR) bytes past the end of datain
buffer here. In the worst case, your program can crash. If it does not,
you will have garbage at the end of bData.
That is an issue, I meant to only use that to allocate the data. I don't
think it's the root cause of my woes, but it won't help!
bSuccess &= CryptEncrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback, bytelen);
Here's your problem. bytesback is an [in, out] parameter. On input, it's
the number of bytes to encrypt. On output, it's the number of encrypted
bytes successfully written. You are passing 0 on input, asking to
encrypt zero bytes.


Oh right....I thought the in parameter was the last parameter, that I'm
passing bytelen to - but it would appear not... thanks for that, I'll try it.

Oh, and you don't need to pass hCryptHash. It does not do what you seem
to think it does. It's harmless, but makes the API do the unnecessary
work.
What, pass NULL to it you mean? What would it not do that it previously
would have done if I'd passed hCryptHash?

memcpy(cryptdata, bData, bytesback);
_tprintf(_T("The encrypted data is \"%s\"\n"), cryptdata);
Encrypted data may very well contain NUL bytes inside, or it may not
contain any, not even at the end. Your printf output will either be
shortened, or will result in a buffer overrun and possibly a crash.
Encryption produces a binary byte stream, not a nice NUL-terminated
string.


Right, OK. I'll give the whole thing an overhaul taking into account your
suggestions with a view that the NULL terminator is just another character to
be encrypted...

Cheers
Note that you never change bytelen after it was initially calculated
from lendatain. You can simply write databack = lendatain + 10 (what is
this +10 doing here anyway? )
It was to make sure I'd allocated more bytes than I'd need.
_tprintf(_T("The decrypted data is \"%s\"\n"), decryptdata);


When encrypting, you didn't include the terminating NUL character. So
decrypted data is not NUL-terminated either (if only accidentally).
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925

Nov 16 '05 #11

P: n/a
Joe
Does always including a NULL terminator weaken an encryption in any
significant way?

Right, OK. I'll give the whole thing an overhaul taking into account your
suggestions with a view that the NULL terminator is just another character to be encrypted...

Cheers

Nov 16 '05 #12

P: n/a
> 1) Exactly what are you trying to encrypt?

User name / password combination
2) Why do you want to avoid using the framework encryption classes (which
are based on proven methods)?

Don't want to use managed code for the security of the main algorithm of the
program

Nov 16 '05 #13

P: n/a
> ... 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.
You appear to have repeated the assertion, instead of attempting to offer a
*reason* as to why this might be the case, as I requested.
Are you able to explain the *technical* reasons as to why someone could
crack my own algorithm, but couldn't crack "rot13" - i.e. what would they
actually physically have to do, and why they wouldn't be able to do this to a
rot13 algorithm. This is the bit I'm having trouble *understanding* - it's
not that I'm having trouble *believing* you and need convincing.
even minor amounts of crypto training
Such as?
can crack this
stuff. Some do it for sport.

Again, I'll repeat the request - *please* explain, if you are able, what
steps they would take to crack mine. I'm not asking you to crack it yourself
- just outline the steps someone would have to take... and point out to me
what bit would trip them up if I was using a professional algorithm.

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


Thanks for replying, however it does appear that you've answered the
question "Should I use my own encryption algorithm?" rather than what was
actually asked, which was "Why shouldn't I use my own encryption algorithm?".
Nov 16 '05 #14

P: n/a
> If you want to do it in an unmanaged way, you shouldn't be looking at
C# to start with - all C# code is managed.
Well, exactly. I'm not looking at writing it in C#, that was just used to
generate 256 random bytes to start with, but since that and because it was a
fairly algorithmic question in general I thought I'd post it here. Sorry if
that caused offence.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #15

P: n/a
Carl -
Is the comparison of the encrypted data with *actual* random noise the
beginning of one of the techniques used for cracking the encryption?
If so, how does it progress?
(see also reply to Steve Friedl)

"Carl Daniel [VC++ MVP]" wrote:
"Severian" <se******@chlamydia-is-not-a-flower.com> wrote in message
On Mon, 22 Nov 2004 15:02:33 -0500, "Nicholas Paldino [.NET/C# MVP]"

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.


I agree with the first two sentences, but compression should be done
before encryption, since encrypted data does not usually compress
well.


Exactly. In fact, compressing the output of an encryptor is a low-grade
test for quality encryption. Well encrypted data is by definition not
compressible (it's indistiguishable from random noise).

More to the point, compressing the data before encryption increases the
entropy of the data. This in turn can only improve the quality of the
encryption.

-cd

Nov 16 '05 #16

P: n/a
Well obviously, because they know what byte zero encrypts to, so they know
what bytes were originally zero, by just comparing which ones are the same as
the last byte. But whether this matters, I don't know... you could perhaps
rearrange the order of the bytes?
"Joe" wrote:
Does always including a NULL terminator weaken an encryption in any
significant way?

Right, OK. I'll give the whole thing an overhaul taking into account your
suggestions with a view that the NULL terminator is just another character

to
be encrypted...

Cheers


Nov 16 '05 #17

P: n/a
Bonj <Bo**@discussions.microsoft.com> wrote:
If you want to do it in an unmanaged way, you shouldn't be looking at
C# to start with - all C# code is managed.


Well, exactly. I'm not looking at writing it in C#, that was just used to
generate 256 random bytes to start with, but since that and because it was a
fairly algorithmic question in general I thought I'd post it here. Sorry if
that caused offence.


No offence taken, but it does seem to be a less appropriate newsgroup
than, say, a newsgroup about security. (comp.security.misc?)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #18

P: n/a
Bonj <Bo**@discussions.microsoft.com> wrote:
... 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.


You appear to have repeated the assertion, instead of attempting to
offer a *reason* as to why this might be the case, as I requested.
Are you able to explain the *technical* reasons as to why someone
could crack my own algorithm, but couldn't crack "rot13" - i.e. what
would they actually physically have to do, and why they wouldn't be
able to do this to a rot13 algorithm. This is the bit I'm having
trouble *understanding* - it's not that I'm having trouble
*believing* you and need convincing.


The reason is that very, very clever people who have a *lot* of
experience in encryption still need to look very carefully at
encryption algorithms before being willing to say how secure they are.
Basically, it's not a field where amateur attempts are likely to be
successful.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #19

P: n/a
Cryptography is a mathematical discipline. New cryptographic algorithms are pretty rare and go through a huge exercise in peer review amongst academics as they try to break the algorithm. Many very well respected mathematicians have come up with new algorithms only to have them broken - sometimes spectacularly quickly by their peers.

You've done the right thing in publishing your algorithm because trying to keep the algorithm secret is no guarantee of cryptographic strength. But I will wager alot of money that your algorithm is very easy to break by a cryptographer (of which I'm not one) unless you are a mathematical genius and have actually come up with a new powerful crypto technique.

This is not meant to trivialise your efforts rather than to point out how tortuously complex it is writing an industrial strength crypto algorithm. If you don't want to use managed code you can use CAPICOM library to use one of the standard algorithms.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Bonj <Bo**@discussions.microsoft.com> wrote:
... 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.


You appear to have repeated the assertion, instead of attempting to
offer a *reason* as to why this might be the case, as I requested.
Are you able to explain the *technical* reasons as to why someone
could crack my own algorithm, but couldn't crack "rot13" - i.e. what
would they actually physically have to do, and why they wouldn't be
able to do this to a rot13 algorithm. This is the bit I'm having
trouble *understanding* - it's not that I'm having trouble
*believing* you and need convincing.


The reason is that very, very clever people who have a *lot* of
experience in encryption still need to look very carefully at
encryption algorithms before being willing to say how secure they are.
Basically, it's not a field where amateur attempts are likely to be
successful.

Nov 16 '05 #20

P: n/a
Bonj wrote:
Carl -
Is the comparison of the encrypted data with *actual* random noise the
beginning of one of the techniques used for cracking the encryption?
If so, how does it progress?
(see also reply to Steve Friedl)


It certainly could be. I would expect a cyptologist to run some high
powered statistics on the ciphertext, if there's enough of it, to discern if
patterns known to exist in various source texts appear. For example, ASCII
text written in the English language will have certain frequency
distribution characteristics. Any kind of seuqnetial XOR operation will
retain that frequency distribution, it'll just be scrambled up.

-cd
Nov 16 '05 #21

P: n/a
Joe wrote:
Does always including a NULL terminator weaken an encryption in any
significant way?


Having a common prefix or suffix on a group of messages may help an attacker
break a series of encyrpted messages. With good encryption techniques, this
is not an issue, but it's an Achilles heel of many home-grown encryption
techniques.

-cd
Nov 16 '05 #22

P: n/a
Bonj wrote:
1) Exactly what are you trying to encrypt?


User name / password combination


You should never (or almost never) store passwords with reversible
encryption. Instead, store the username in plaintext and store the password
as a one-way hash. Typically MD5 or SHA(1) are used for this purpose.

Incidentally, another resource you might check out is Crypto++. This is a
C++ class library with implementations of many high-quality crypto
algorithms that you can use to build crypto systems if you don't want to use
the native CryptoAPI. See http://www.eskimo.com/~weidai/cryptlib.html.

-cd
Nov 16 '05 #23

P: n/a
"Joe" <ff***********@hotmail-spammers-paradise.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl
Does always including a NULL terminator weaken an encryption in any
significant way?


Probably not. It does give the advantage of known plaintext, but knowing
just one byte of the input is unlikely to help the attacker all that
much. A lot of the data being encrypted has well-known fragments - e.g.
all GIFs begin with GIF89a, all EXEs with MZ and so on. Good encryption
algorithms are designed to withstand known-plaintext attacks.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #24

P: n/a
"Bonj" <Bo**@discussions.microsoft.com> wrote in message
news:C9**********************************@microsof t.com
Well obviously, because they know what byte zero encrypts to, so they
know what bytes were originally zero, by just comparing which ones
are the same as the last byte.


No encryption algorithm worth its salt would consistently encrypt the
same byte to the same value. First, such an algorithm would be trivially
easy to break (e.g. using frequency of occurrence of different letters
in an average English text). Second, it does not hide patterns in the
input - e.g. a long run of the same byte in the input would produce a
long run in the output. This information may be important in and of
itself. Finally, such an algorithm is subject to substitution attacks,
where an attacker can modify one byte of ciphertext to affect one
character of plaintext (imagine replacing No with Yes under a contract
or a purchase order or something). In a strong alorithm, modifying one
bit of ciphertext results in the decoded plaintext being a random
meaningless jumble from the point of modification onward, so the
tampering is hard to miss.

See

http://en.wikipedia.org/wiki/Block_c...s_of_operation

It shows an example of a picture encrypted with an algorithm you
describe (the one that simply performs byte substitution) as well as a
good strong encryption algorithm. Behold the difference.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #25

P: n/a
Yes, I had considered this, BUT:
I do not control the part of the software that decides whether the
re-entered (or "decrypted") password is valid or not. That is SQL Server!
Hence, I *do* need to actually reverse the process.
Like I say, I don't need it to be *absolutely 100%* secure, but I was just
wondering how secure it was - like I've already said, I was conscious that it
wasn't quite as good as a professional API based solution, but I was
wondering *why* it wasn't as good.
I'm never sure how much detailed explanation I need to give as to *why* I
want to do exactly what I want to do, and to what extent I need to persuade,
incite, cajole, or beg people to tell me the information that *I* want to
know, and in order not to be lectured at as to how I 'should' do it - most of
the time it's great, people seem to almost know what I want before I do...
but other times it seems I am bashing my head against a brick wall .... is
there something about my OP that screams out "tell me to use API functions
and don't explain why" ?

"Carl Daniel [VC++ MVP]" wrote:
Bonj wrote:
1) Exactly what are you trying to encrypt?


User name / password combination


You should never (or almost never) store passwords with reversible
encryption. Instead, store the username in plaintext and store the password
as a one-way hash. Typically MD5 or SHA(1) are used for this purpose.

Incidentally, another resource you might check out is Crypto++. This is a
C++ class library with implementations of many high-quality crypto
algorithms that you can use to build crypto systems if you don't want to use
the native CryptoAPI. See http://www.eskimo.com/~weidai/cryptlib.html.

-cd

Nov 16 '05 #26

P: n/a
> The reason is that very, very clever people who have a *lot* of
experience in encryption still need to look very carefully at
encryption algorithms before being willing to say how secure they are.
Basically, it's not a field where amateur attempts are likely to be
successful.
Jon - I don't get it. Are you either saying that YOU, Jon Skeet, are someone
who is a "very very clever person who has a lot of experience in encryption"
and that you personally have decided that you're not *willing* to give me an
brief evaluation of the effectiveness of my routine because you want to
remain comparatively clever at encryption, OR, are you thinking "if we keep
repeating the same answer over and over again, eventually he'll get the
impression he doesn't need to know the answer to this" ? If information on
how to encrypt should indeed itself be encrypted, then damnit, give a wrong
answer rather than no answer at all!
Or is it that you can't see why it wouldn't be effective, but you don't want
to tell me this, because it would be unfair of me to put this algorithm to
successful use when lots of people have toiled for many times the number of
hours on "sophisticated" algorithms? (bearing in mind the fact that it
*isn't* likely to be the subject of prolonged attacks just for a single
encryption instance).

As an intelligent person, can you understand how frustrating it is to ask a
question, to be followed up by lots of willing, helpful respondents, who all
make the same general assertion, and when you ask any of them "yes, but why?"
they *all* simply repeat the assertion?
Can you understand how you could also be tempted, because of this, to be
lulled into believing that these people *aren't* in fact particularly
intelligent, when you know full well that they are?

(Thank god for Igor...)

Please don't take offence Jon, none is intended. You've answered a lot of
questions of mine so I know that you're an intelligent guy, but at the end of
the day, I think we're both aware that *you* know that *I* am fairly
intelligent, too - which is why I really, really don't understand why you
made the post you did.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #27

P: n/a
"Carl Daniel [VC++ MVP]"
<cp*****************************@mvps.org.nospam > wrote in message
news:O2**************@TK2MSFTNGP12.phx.gbl
Bonj wrote:
1) Exactly what are you trying to encrypt?


User name / password combination


You should never (or almost never) store passwords with reversible
encryption. Instead, store the username in plaintext and store the
password as a one-way hash. Typically MD5 or SHA(1) are used for
this purpose.


.... preferably with salting and stretching, to hinder dictionary
attacks.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #28

P: n/a
"Bonj" <Bo**@discussions.microsoft.com> wrote in message
news:61**********************************@microsof t.com
bSuccess &= CryptEncrypt(hCryptKey, hCryptHash, TRUE, 0, bData,
&bytesback, bytelen);


Here's your problem. bytesback is an [in, out] parameter. On input,
it's the number of bytes to encrypt. On output, it's the number of
encrypted bytes successfully written. You are passing 0 on input,
asking to encrypt zero bytes.


Oh right....I thought the in parameter was the last parameter, that
I'm passing bytelen to - but it would appear not... thanks for that,
I'll try it.


The last parameter is the size of the buffer, not the size of the data
to be encrypted. It is needed for those rare algorithms where ciphertext
may be larger than plaintext, so the buffer may need to be larger than
the input data it contains.
Oh, and you don't need to pass hCryptHash. It does not do what you
seem to think it does. It's harmless, but makes the API do the
unnecessary work.


What, pass NULL to it you mean? What would it not do that it
previously would have done if I'd passed hCryptHash?


Yes, pass NULL. You pass hCryptHash when you need to encrypt and hash
the data simultaneously (this is used in some digital signature
protocols). Since you don't use the hash value, it's a waste of time to
have the function calculate it.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #29

P: n/a
Bonj <Bo**@discussions.microsoft.com> wrote:
The reason is that very, very clever people who have a *lot* of
experience in encryption still need to look very carefully at
encryption algorithms before being willing to say how secure they are.
Basically, it's not a field where amateur attempts are likely to be
successful.
Jon - I don't get it. Are you either saying that YOU, Jon Skeet, are someone
who is a "very very clever person who has a lot of experience in encryption"
and that you personally have decided that you're not *willing* to give me an
brief evaluation of the effectiveness of my routine because you want to
remain comparatively clever at encryption,


Heck no.
OR, are you thinking "if we keep
repeating the same answer over and over again, eventually he'll get the
impression he doesn't need to know the answer to this" ? If information on
how to encrypt should indeed itself be encrypted, then damnit, give a wrong
answer rather than no answer at all!
I'm thinking that you still don't seem to "get" that other people have
done the thinking for you. They've designed plenty of crypto algorithms
already. Information on how to encrypt is readily available on the web
- there are plenty of samples around.
Or is it that you can't see why it wouldn't be effective, but you don't want
to tell me this, because it would be unfair of me to put this algorithm to
successful use when lots of people have toiled for many times the number of
hours on "sophisticated" algorithms? (bearing in mind the fact that it
*isn't* likely to be the subject of prolonged attacks just for a single
encryption instance).
I haven't looked at your algorithm in detail, and frankly I don't have
the experience to say whether it's good or not. I could only give you
information about whether or not *I* could break it, and that's not
saying very much.
As an intelligent person, can you understand how frustrating it is to ask a
question, to be followed up by lots of willing, helpful respondents, who all
make the same general assertion, and when you ask any of them "yes, but why?"
they *all* simply repeat the assertion?
We've *given* you the "why" though - the "why" is "because you aren't
trained (as far as we know) in encryption, whereas other people who
designed standard crypto algorithms are". It's also "because lots of
very intelligent people who specialise in this kind of thing have
looked at the standard algorithms, but haven't looked at yours and are
unlikely to".

The way I see it, the assertion is "Use standard algorithms rather than
designing your own" and the reason (which has been posted several
times) is simply "Crypto is hard. You're very unlikely to get it right
- even very highly skilled people get it wrong, which is why there's
peer review. Standard algorithms have the advantage that they've
already been through peer review."

In what way is that simply repeating the assertion?
Can you understand how you could also be tempted, because of this, to be
lulled into believing that these people *aren't* in fact particularly
intelligent, when you know full well that they are?
Not really, to be honest. I think the responses on this thread have
been pretty reasonable.
(Thank god for Igor...)

Please don't take offence Jon, none is intended. You've answered a lot of
questions of mine so I know that you're an intelligent guy, but at the end of
the day, I think we're both aware that *you* know that *I* am fairly
intelligent, too - which is why I really, really don't understand why you
made the post you did.


I suggest you read it again then, along with the other posts. The
answer to your question is definitely there, plain and simple. I'm not
entirely sure which part of it you either don't understand or don't
want to accept.

I suspect no-one here is an expert in cryptography. However, it doesn't
take an expert in cryptography to know that you shouldn't trust an
algorithm which hasn't been vetted thoroughly by a group of experts in
cryptography, because it's very, very unlikely to be as good as the
ones which have been through peer review.

Making a critique of your particular algorithm would be a bit of a
waste of time, to be honest, because the best way to go about things
isn't to patch up whatever problems someone finds with your algorithm -
it's to use a standard algorithm in the first place.

I strongly recommend that instead of trying to get your own algorithm
working, you go back to looking at the crypto API and trying to get
that working instead. I'm sure you'll get a lot more of help on that
front if you post a short but complete program.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #30

P: n/a
> You've done the right thing in publishing your algorithm because trying to
keep the algorithm secret is no guarantee of cryptographic strength.

That was my thoughts exactly. The random bytes can be changed, and new
features can be introduced like "codepages" to make it so that the same
string will give a different byte string out every time, for instance, I
thought that, as it stands, a lot of the entries are going to be the
encryption of "Integrated Security=SSPI", so they're going to be the same.
Codepages would stop people seeing at a glance which SQL servers use windows
auth. and which use SQL auth....etc. etc. It's just common sense and
confusion as much as sticking to definitive mathematical theory.
But I will wager alot of money that your algorithm is very easy to break by a
cryptographer (of which I'm not one) unless you are a mathematical genius and
have actually come up with a new powerful crypto technique.
OK... I'm always one for a bet that involves skill, are you prepared to
honour that?
My basic terms are as follows:
1) The algorithm is not yet finished, but I must declare when it is, and
when I do so, I must make no further modifications.
2) I must distribute all compiled binaries necessary to run the encryption
(i.e. as a user would) but am not required to distribute any intermediate
data or software I have used to construct the actual source code for my
algorithm. Any "win" by the cryptographer shall be declared void should he
have obtained any of this secret media that wouldn't be distributed to a user
(such as my source code, intermediate data) via prior means, such as internet
hacking of my web server**.
3) The cryptographer must deliver a program capable of deciphering any
password encrypted by *any* release of my DLL*(see below)
4) You must name the cryptographer and time frame in which he is to complete
the task prior to the wager being agreed, but there are no limits on this (or
the number of cryptographers involved or the apparatus they use). If the time
frame is chosen to be more than a day, then the winnings shall not increase
by inflation or interest.
5) We both must provide the other with concrete proof that we have the
amount of money wagered.
6) Either party has the right to supervise the cryptographer during his
decipher attempts but must not impair him.
7) We must both undertake a gentleman's agreement to uphold the wager and
winnings to be delivered via PayPal.

* bear in mind that this is the only thing I'm worried about - laymen
downloading programs in order to be able to crack it. What use is any other
attempt to crack it? It's only going to be storing passwords in HKCU, and a
cryptographer isn't exactly going to want to crack his *own* password, is he?
He's going to want to profit / make a buzz for himself, from a program that
rubbishes my algorithm - the only way to do that is to make the crack
accessible to the layman. This is where the stipulation of the cryptographer
not having access to the actual release of the DLL used comes from, as each
one will be different and have a different key, etc... this won't impair the
functionality as the same one will always be used to decrypt as was used to
encrypt. Hell, it could even generate the random key on installation...

** not that it's in a web directory anyway so don't go trying...

At the end of the day, I'm not worried about an attack by a cryptographer,
I'm more worried about whether it could be cracked by a layman, possibly by
using a program written by a cryptographer. (And please don't simply say
"yes, it could" without explaining how...)
If you'd read my OP, you'd probably have got the gist of the question, which
was that I don't care about this. The question is more, how hard would it be
for a cryptographer to produce a *program* with which a layman (who may have
used the password remember feature) could leave his terminal unlocked for
long enough
for his rival to sneak on to his computer for long enough to run the program
that the "experienced cryptographer" had distributed (for free). Would the
experienced cryptographer be bothered to, or even know to?
And more to the point, how would such a program know which of my home grown
algorithms the data it set out to decipher had been encrypted by???
I could write ten like that... all in different DLLs scattered all over the
place disguised as something innocuous...


This is not meant to trivialise your efforts


See responses to others - do you see what I'm getting at?
Nov 16 '05 #31

P: n/a
oh right... yes, i suppose, that is an option -
how do you access comp.* newsgroups?
"Jon Skeet [C# MVP]" wrote:
Bonj <Bo**@discussions.microsoft.com> wrote:
If you want to do it in an unmanaged way, you shouldn't be looking at
C# to start with - all C# code is managed.


Well, exactly. I'm not looking at writing it in C#, that was just used to
generate 256 random bytes to start with, but since that and because it was a
fairly algorithmic question in general I thought I'd post it here. Sorry if
that caused offence.


No offence taken, but it does seem to be a less appropriate newsgroup
than, say, a newsgroup about security. (comp.security.misc?)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #32

P: n/a
Bonj wrote:
Jon - I don't get it. Are you either saying that YOU, Jon Skeet, are someone
who is a "very very clever person who has a lot of experience in encryption"
and that you personally have decided that you're not *willing* to give me an
brief evaluation of the effectiveness of my routine because you want to
remain comparatively clever at encryption, OR, are you thinking "if we keep
repeating the same answer over and over again, eventually he'll get the
impression he doesn't need to know the answer to this" ? If information on
how to encrypt should indeed itself be encrypted, then damnit, give a wrong
answer rather than no answer at all!
Or is it that you can't see why it wouldn't be effective, but you don't want
to tell me this, because it would be unfair of me to put this algorithm to
successful use when lots of people have toiled for many times the number of
hours on "sophisticated" algorithms? (bearing in mind the fact that it
*isn't* likely to be the subject of prolonged attacks just for a single
encryption instance).

As an intelligent person, can you understand how frustrating it is to ask a
question, to be followed up by lots of willing, helpful respondents, who all
make the same general assertion, and when you ask any of them "yes, but why?"
they *all* simply repeat the assertion?
Can you understand how you could also be tempted, because of this, to be
lulled into believing that these people *aren't* in fact particularly
intelligent, when you know full well that they are?

(Thank god for Igor...)

Please don't take offence Jon, none is intended. You've answered a lot of
questions of mine so I know that you're an intelligent guy, but at the end of
the day, I think we're both aware that *you* know that *I* am fairly
intelligent, too - which is why I really, really don't understand why you
made the post you did.


You need to read a book such as the following, which you can probably find
at your local library:

The Code Book: The Science of Secrecy from Ancient Egypt to Quantum
Cryptography
http://www.amazon.com/exec/obidos/tg...glance&s=books

This very readable book will demonstrate why those who tell you that you
won't invent strong encryption on your own are correct to do so, and it will
develop the subject far beyond what is reasonable to expect of newsgroup Q/A
sessions.

You might also want to check out the sci.crypt FAQ:

http://www.faqs.org/faqs/by-newsgrou...sci.crypt.html

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 16 '05 #33

P: n/a
Hey, we're getting somewhere, thanks Igor...
(inline)
No encryption algorithm worth its salt would consistently encrypt the
same byte to the same value.
Do you reckon that, albeit not the be all and end all, but that if I achieve
that, then it's a big step forward in the right direction?
First, such an algorithm would be trivially
easy to break (e.g. using frequency of occurrence of different letters
in an average English text). Second, it does not hide patterns in the
input - e.g. a long run of the same byte in the input would produce a
long run in the output.
Note that this wouldn't occur in my algorithm, because each byte undergoes a
number of XOR operations given by f(n), where n is the byte number. Hence,
each successive byte undergoes a different number of XOR operations than the
last aswell as different ones, so a string say "00000" will not necessarily
come out as the same byte repeated 5 times.
This information may be important in and of
itself. Finally, such an algorithm is subject to substitution attacks,
where an attacker can modify one byte of ciphertext to affect one
character of plaintext (imagine replacing No with Yes under a contract
or a purchase order or something). In a strong alorithm, modifying one
bit of ciphertext results in the decoded plaintext being a random
meaningless jumble from the point of modification onward, so the
tampering is hard to miss.


Eh? Hard to miss? wouldn't it be easy to miss, as you could just say from
what point the meaningless jumble started, and that's where the tampering
occurred...

And... you're saying that an important principle of a good algorithm is that
each byte affects all the others after it, not just itself?

Nov 16 '05 #34

P: n/a
That's a very interesting website, thanks I'll read it.
"Igor Tandetnik" wrote:
"Bonj" <Bo**@discussions.microsoft.com> wrote in message
news:C9**********************************@microsof t.com
Well obviously, because they know what byte zero encrypts to, so they
know what bytes were originally zero, by just comparing which ones
are the same as the last byte.


No encryption algorithm worth its salt would consistently encrypt the
same byte to the same value. First, such an algorithm would be trivially
easy to break (e.g. using frequency of occurrence of different letters
in an average English text). Second, it does not hide patterns in the
input - e.g. a long run of the same byte in the input would produce a
long run in the output. This information may be important in and of
itself. Finally, such an algorithm is subject to substitution attacks,
where an attacker can modify one byte of ciphertext to affect one
character of plaintext (imagine replacing No with Yes under a contract
or a purchase order or something). In a strong alorithm, modifying one
bit of ciphertext results in the decoded plaintext being a random
meaningless jumble from the point of modification onward, so the
tampering is hard to miss.

See

http://en.wikipedia.org/wiki/Block_c...s_of_operation

It shows an example of a picture encrypted with an algorithm you
describe (the one that simply performs byte substitution) as well as a
good strong encryption algorithm. Behold the difference.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925

Nov 16 '05 #35

P: n/a
"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:8n********************************@4ax.com
You might also want to check out the sci.crypt FAQ:

http://www.faqs.org/faqs/by-newsgrou...sci.crypt.html


.... especially this one

http://www.faqs.org/faqs/cryptography-faq/snake-oil/

--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #36

P: n/a
Bonj <Bo**@discussions.microsoft.com> wrote:
oh right... yes, i suppose, that is an option -
how do you access comp.* newsgroups?


Use whatever news-server your ISP provides.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #37

P: n/a
Bonj <Bo**@discussions.microsoft.com> wrote:
My basic terms are as follows:
<snip>
2) I must distribute all compiled binaries necessary to run the encryption
(i.e. as a user would) but am not required to distribute any intermediate
data or software I have used to construct the actual source code for my
algorithm. Any "win" by the cryptographer shall be declared void should he
have obtained any of this secret media that wouldn't be distributed to a user
(such as my source code, intermediate data) via prior means, such as internet
hacking of my web server**.


<snip>

It sounds like you're a fan of security through obscurity, which is
another "no-no". Basically, although the *key* should be kept private,
if an algorithm is secure, it shouldn't matter who knows the algorithm
itself. This is important, as given enough time, any software can be
reverse engineered. In other words, the process used to transform
key + encrypted data into plaintext cannot be considered to be secret.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #38

P: n/a
OK, thanks I might check it out.
"Doug Harrison [MVP]" wrote:
Bonj wrote:
Jon - I don't get it. Are you either saying that YOU, Jon Skeet, are someone
who is a "very very clever person who has a lot of experience in encryption"
and that you personally have decided that you're not *willing* to give me an
brief evaluation of the effectiveness of my routine because you want to
remain comparatively clever at encryption, OR, are you thinking "if we keep
repeating the same answer over and over again, eventually he'll get the
impression he doesn't need to know the answer to this" ? If information on
how to encrypt should indeed itself be encrypted, then damnit, give a wrong
answer rather than no answer at all!
Or is it that you can't see why it wouldn't be effective, but you don't want
to tell me this, because it would be unfair of me to put this algorithm to
successful use when lots of people have toiled for many times the number of
hours on "sophisticated" algorithms? (bearing in mind the fact that it
*isn't* likely to be the subject of prolonged attacks just for a single
encryption instance).

As an intelligent person, can you understand how frustrating it is to ask a
question, to be followed up by lots of willing, helpful respondents, who all
make the same general assertion, and when you ask any of them "yes, but why?"
they *all* simply repeat the assertion?
Can you understand how you could also be tempted, because of this, to be
lulled into believing that these people *aren't* in fact particularly
intelligent, when you know full well that they are?

(Thank god for Igor...)

Please don't take offence Jon, none is intended. You've answered a lot of
questions of mine so I know that you're an intelligent guy, but at the end of
the day, I think we're both aware that *you* know that *I* am fairly
intelligent, too - which is why I really, really don't understand why you
made the post you did.


You need to read a book such as the following, which you can probably find
at your local library:

The Code Book: The Science of Secrecy from Ancient Egypt to Quantum
Cryptography
http://www.amazon.com/exec/obidos/tg...glance&s=books

This very readable book will demonstrate why those who tell you that you
won't invent strong encryption on your own are correct to do so, and it will
develop the subject far beyond what is reasonable to expect of newsgroup Q/A
sessions.

You might also want to check out the sci.crypt FAQ:

http://www.faqs.org/faqs/by-newsgrou...sci.crypt.html

--
Doug Harrison
Microsoft MVP - Visual C++

Nov 16 '05 #39

P: n/a
Right, OK. I see what you're saying.
See also inline.
I'm thinking that you still don't seem to "get" that other people have
done the thinking for you. They've designed plenty of crypto algorithms
already. Information on how to encrypt is readily available on the web
- there are plenty of samples around.
Not plenty of good ones, though. Check how many home-grown "XOR" ones there
are on planetsourcecode compared to good, robust, CryptoAPI examples...more
the former than the latter definitely.
We've *given* you the "why" though - the "why" is "because you aren't
trained (as far as we know) in encryption
But that's just it - *as far as you know*. You don't know. How did anyone
get good at encryption, how did the people that do the "training" get good at
it? They have ideas, and put them into practice.
What's more, how do the crackers get good at their skill? Probably by
looking up to other crackers, and analysing how they do their stuff... and
those higher up crackers are probably more into breaking standard algorithms
than mine...I'm merely citing the old adage that the small child who plays
chess against a grandmaster, might just win - due to the fact that he plays
SO badly, none of the grandmaster's standard theories and gameplans work,
because they're all designed to work against other gameplans (which the young
child has no concept of), but still.....
but haven't looked at yours and are
unlikely to".
Again, weak as it is, the point comes back - if they're not likely to look
at it, how do they crack it?

The way I see it, the assertion is "Use standard algorithms rather than
designing your own" and the reason (which has been posted several
times) is simply "Crypto is hard. You're very unlikely to get it right
- even very highly skilled people get it wrong, which is why there's
peer review. Standard algorithms have the advantage that they've
already been through peer review."
The reason for originally posting was that I had tried to get the standard
algorithm working, *and failed*. I did try several times on that first. I
knew my design choice wasn't a good one, but I persisted with it because at
the time it seemed like my *only* choice, and I had thought that I had
explained the fact that I couldn't get the CryptoAPI working sufficient. Igor
has very kindly addressed that, and at the end of the day that's probably
what I'll go with, but since I started out on this tack and spent all of a
whole hour writing the damn thing, I'll finish.

In what way is that simply repeating the assertion?


Well, no - in light of the above paragraph, it possibly just seemed like
that - but you have explained yourself sufficiently now and I thank you for
that.
Nov 16 '05 #40

P: n/a
Bonj <Bo**@discussions.microsoft.com> wrote:
Right, OK. I see what you're saying.
See also inline.
I'm thinking that you still don't seem to "get" that other people have
done the thinking for you. They've designed plenty of crypto algorithms
already. Information on how to encrypt is readily available on the web
- there are plenty of samples around.
Not plenty of good ones, though. Check how many home-grown "XOR" ones there
are on planetsourcecode compared to good, robust, CryptoAPI examples...more
the former than the latter definitely.


But surely there are enough CryptoAPI examples to help you out, aren't
there?
We've *given* you the "why" though - the "why" is "because you aren't
trained (as far as we know) in encryption


But that's just it - *as far as you know*.


True, but I suspect most people who *were* trained in encryption would
have understood the reasons given for not trying to come up with your
own algorithm to start with.
You don't know. How did anyone get good at encryption, how did the
people that do the "training" get good at it? They have ideas, and
put them into practice.
I suspect the first thing is to have a very strong mathematical
background, actually - a PhD in discreet maths would be a good starting
point, for instance.

They'd then no doubt read several books on cryptology and cryptography,
and study the standard algorithms, including old ones which have been
broken, in order to see where weaknesses have previously been
discovered.

Using "I think I'll design my own crypto algorithm" is a bad starting
point, IMO.
What's more, how do the crackers get good at their skill? Probably by
looking up to other crackers, and analysing how they do their stuff... and
those higher up crackers are probably more into breaking standard algorithms
than mine...I'm merely citing the old adage that the small child who plays
chess against a grandmaster, might just win - due to the fact that he plays
SO badly, none of the grandmaster's standard theories and gameplans work,
because they're all designed to work against other gameplans (which the young
child has no concept of), but still.....
That's really not a good argument in favour of creating your own
algorithm. Just because someone hasn't already studied yours in an
attempt to crack it doesn't mean it's more secure than one which many
highly skilled people *have* studied and failed to find significant
problems with. It just means they haven't looked at yours yet.
but haven't looked at yours and are
unlikely to".


Again, weak as it is, the point comes back - if they're not likely to look
at it, how do they crack it?


They crack it when it's worth cracking, rather than now. Do you really
want to only find out whether your algorithm is strong enough when it's
already deployed in the field, and is protecting real-world data?
The way I see it, the assertion is "Use standard algorithms rather than
designing your own" and the reason (which has been posted several
times) is simply "Crypto is hard. You're very unlikely to get it right
- even very highly skilled people get it wrong, which is why there's
peer review. Standard algorithms have the advantage that they've
already been through peer review."


The reason for originally posting was that I had tried to get the standard
algorithm working, *and failed*. I did try several times on that first. I
knew my design choice wasn't a good one, but I persisted with it because at
the time it seemed like my *only* choice, and I had thought that I had
explained the fact that I couldn't get the CryptoAPI working sufficient.


But why did you wait until you'd made what you could see was a bad
choice before posting, rather than just asking for help with the
CryptoAPI in the first place? It's like starting to design your own
string class because you can't get Substring working - you're far more
likely to get help on standard stuff than you are to get genuinely
expert opinions on your own custom algorithms.
Igor has very kindly addressed that, and at the end of the day that's
probably what I'll go with, but since I started out on this tack and
spent all of a whole hour writing the damn thing, I'll finish.


No-one can stop you, of course - but I'd urge you not to make the
mistake of deciding to actually *use* it at any point, just because
you'll then have it.
In what way is that simply repeating the assertion?


Well, no - in light of the above paragraph, it possibly just seemed
like that - but you have explained yourself sufficiently now and I
thank you for that.


Goodo - I'm glad we understood each other in the end.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #41

P: n/a
If you just need to save a secret, why not simply use
CryptProtectData/CryptUnprotectData?

"Bonj" <Bo**@discussions.microsoft.com> wrote in message
news:B4**********************************@microsof t.com...
Yes, I had considered this, BUT:
I do not control the part of the software that decides whether the
re-entered (or "decrypted") password is valid or not. That is SQL Server!
Hence, I *do* need to actually reverse the process.
Like I say, I don't need it to be *absolutely 100%* secure, but I was just
wondering how secure it was - like I've already said, I was conscious that
it
wasn't quite as good as a professional API based solution, but I was
wondering *why* it wasn't as good.
I'm never sure how much detailed explanation I need to give as to *why* I
want to do exactly what I want to do, and to what extent I need to
persuade,
incite, cajole, or beg people to tell me the information that *I* want to
know, and in order not to be lectured at as to how I 'should' do it - most
of
the time it's great, people seem to almost know what I want before I do...
but other times it seems I am bashing my head against a brick wall .... is
there something about my OP that screams out "tell me to use API functions
and don't explain why" ?

"Carl Daniel [VC++ MVP]" wrote:
Bonj wrote:
>> 1) Exactly what are you trying to encrypt?
>
> User name / password combination


You should never (or almost never) store passwords with reversible
encryption. Instead, store the username in plaintext and store the
password
as a one-way hash. Typically MD5 or SHA(1) are used for this purpose.

Incidentally, another resource you might check out is Crypto++. This is
a
C++ class library with implementations of many high-quality crypto
algorithms that you can use to build crypto systems if you don't want to
use
the native CryptoAPI. See http://www.eskimo.com/~weidai/cryptlib.html.

-cd

Nov 16 '05 #42

P: n/a
I completely agree with your statement that "the process used to transform
key + encrypted data into plaintext cannot be considered to be secret". But,
well, that leads me to the question - how does using a standard algorithm
make it any easier to "secure" the key than using my own algorithm? There
always has to be a key, whatever algorithm I use...
I can't see any way round using the same key every time - and that means it
has to be stored as data within the executable file or a DLL, either in
global namespace memory or a binary resource. Which means someone could
easily find it out. Doesn't it?

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Bonj <Bo**@discussions.microsoft.com> wrote:
My basic terms are as follows:


<snip>
2) I must distribute all compiled binaries necessary to run the
encryption
(i.e. as a user would) but am not required to distribute any intermediate
data or software I have used to construct the actual source code for my
algorithm. Any "win" by the cryptographer shall be declared void should
he
have obtained any of this secret media that wouldn't be distributed to a
user
(such as my source code, intermediate data) via prior means, such as
internet
hacking of my web server**.


<snip>

It sounds like you're a fan of security through obscurity, which is
another "no-no". Basically, although the *key* should be kept private,
if an algorithm is secure, it shouldn't matter who knows the algorithm
itself. This is important, as given enough time, any software can be
reverse engineered. In other words, the process used to transform
key + encrypted data into plaintext cannot be considered to be secret.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #43

P: n/a
"Bonj" <benjtaylor at hotpop d0t com> wrote in message
news:Ou**************@TK2MSFTNGP14.phx.gbl
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].


Note two facts. First, XOR is associative and commutative, that is, a
sequence of XOR's can be executed in any order without changing the
result. Second, x XOR x == 0 for any x, and x XOR 0 == x for any x.

Suppose key2[n] happens to be even. Let the data byte at position n be
x. Then your inner loop, the one that loops 'levels' times, XOR's x with
itself an even number of times (the result is 0), then XORs some key
material on top of that. The result _does not_ depend on x _at all_.
Which means, there's no way to recover plain text from ciphertext - the
data is irretrievably lost in encryption.

Let's assume you fix it by simply XOR'ing x (the data byte) once. Now,
the operations of the inner loop don't depend on x at all. You can
represent an operation on byte x at position n as (x XOR K(n) ), where
K(n) depends only on n and key material (the bytes of key1 and key2).
You can as well precalculate K(n) and do a simple XOR without any loop,
and it won't change the result.

Thus, this modification of your algorithm is equivalent to a naive XOR
cipher - XORing the input data with a fixed key. If I happen to know
both a plaintext and a ciphertext for some message (known-plaintext
attack), I'll just XOR them together and get the key (note that the
attacker often has access to at least some bytes of plaintext, since
many messages contain known signatures in fixed places, like protocol
headers and such). Even if I don't, a simple XOR cipher is a particular
case of polyalphabetic aka Vigenere cipher - all the rage in 16-17th
centuries until broken in 1863.

http://www.trincoll.edu/depts/cpsc/c.../vigenere.html

--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #44

P: n/a
"Bonj" <Bo**@discussions.microsoft.com> wrote in message
news:13**********************************@microsof t.com
Hey, we're getting somewhere, thanks Igor...
(inline)
No encryption algorithm worth its salt would consistently encrypt the
same byte to the same value.
Do you reckon that, albeit not the be all and end all, but that if I
achieve that, then it's a big step forward in the right direction?


No offence intended, but perhaps reading a cryptology textbook should be
your first step in the right direction? After all, you don't start
designing car engines without first studying to be a mechanical
engineer. Why do you think you can design an encryption algorithm
without studying the field first? At least you should first become a
proficient cryptanalyst (cryptanalysis is a science of breaking
encryption), just so you know what an encryption algorithm should look
out for and protect against.
First, such an algorithm would be trivially
easy to break (e.g. using frequency of occurrence of different
letters in an average English text). Second, it does not hide
patterns in the input - e.g. a long run of the same byte in the
input would produce a long run in the output.


Note that this wouldn't occur in my algorithm, because each byte
undergoes a number of XOR operations given by f(n), where n is the
byte number.


Yours is equivalent to a simple XOR with a fixed key - see my other
message. Do you seriously believe this to be strong encryption?
This information may be important in and of
itself. Finally, such an algorithm is subject to substitution
attacks, where an attacker can modify one byte of ciphertext to
affect one character of plaintext (imagine replacing No with Yes
under a contract or a purchase order or something). In a strong
alorithm, modifying one bit of ciphertext results in the decoded
plaintext being a random meaningless jumble from the point of
modification onward, so the tampering is hard to miss.


Eh? Hard to miss? wouldn't it be easy to miss, as you could just say
from what point the meaningless jumble started, and that's where the
tampering occurred...


It is obvious that the message has been tampered with, and not to be
trusted. It does not matter what the original data was, or what the
modification attempt was. The message is discared, alarms are sounded,
and the investigation starts. It's like those tamper-proof medicine
bottles - if the packaging is broken, you don't much care (at least, not
immediately) what exactly happened to the medicine, who did it or for
what reason. It's often enough to know that the medicine is no good
anymore.
And... you're saying that an important principle of a good algorithm
is that each byte affects all the others after it, not just itself?


It's generally a very good idea, yes. Usually every byte affects all the
subsequent bytes, as most encryption algorithms work in one pass so it
is hard to retroactively affect preceding bytes. The algorithms need to
be fast, and also they often need to be implemented in a hardware device
with a limited amount of memory that encrypts a large data stream as it
moves past it, so going back to previous bytes is not feasible.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Nov 16 '05 #45

P: n/a
<"Bonj" <benjtaylor at hotpop d0t com>> wrote:
I completely agree with your statement that "the process used to transform
key + encrypted data into plaintext cannot be considered to be secret". But,
well, that leads me to the question - how does using a standard algorithm
make it any easier to "secure" the key than using my own algorithm? There
always has to be a key, whatever algorithm I use...
I can't see any way round using the same key every time - and that means it
has to be stored as data within the executable file or a DLL, either in
global namespace memory or a binary resource. Which means someone could
easily find it out. Doesn't it?


Securing the key is a difficult problem, and one which in some ways
can't be solved satisfactorily. Of course in a public/private key
system, there are different benefits, but I don't know exactly what
you're doing, so can't really comment on whether that would be better.

I believe there is a Windows API which lets you get/set data which only
the current user has access to, encrypting it with (presumably)
something to do with their Windows password - I don't know much about
it, but I expect others reading this thread will. You could use that to
secure the key in some respects - as long as the user's account isn't
broken into, the key is safe. (It does mean a single weak point,
however.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #46

P: n/a
"=?Utf-8?B?Qm9uag==?=" <Bo**@discussions.microsoft.com> wrote in
news:B4**********************************@microsof t.com:
Yes, I had considered this, BUT:
I do not control the part of the software that decides whether the
re-entered (or "decrypted") password is valid or not. That is SQL
Server! Hence, I *do* need to actually reverse the process.

If you're using ODBC to communicate with SQL Server, you probably
pass the password to SQLConnect, so whoever has access to the
computer and curious enough can just look what your application
passes.

And if you're concerned about somebody intercepting the packets in
the transit, your encryption won't matter. Hopefully, SQL server is
using a decent encryption for the transmitted packets.

Alex.
Nov 16 '05 #47

P: n/a
On Tue, 23 Nov 2004 19:30:24 -0000, Jon Skeet [C# MVP]
<sk***@pobox.com> wrote:

I believe there is a Windows API which lets you get/set data which only
the current user has access to, encrypting it with (presumably)
something to do with their Windows password - I don't know much about
it, but I expect others reading this thread will. You could use that to
secure the key in some respects - as long as the user's account isn't
broken into, the key is safe. (It does mean a single weak point,
however.)

There is the Data Protection API. DAPI can access a user store or a
machine store (the latter if you are running in a service). If you
want to keep a secret on a machine, Bonj, this probably the best
you'll get unless you go with a hardware approach (smart cards /
dongles).

DPAPI is a layer over the CrytoAPI. There is some wrapper code on MSDN
to make it easier getting started from C#:

http://msdn.microsoft.com/library/de...l/secmod21.asp

--
Scott
http://www.OdeToCode.com/blogs/scott/
Nov 16 '05 #48

P: n/a
If you're using ODBC to communicate with SQL Server, you probably
pass the password to SQLConnect, so whoever has access to the
computer and curious enough can just look what your application
passes.


But surely they'd need to understand how to disassemble machine language
into assembly and understand where the "pass" takes place in order to do
that?
Thus wouldn't be able to be done by a layman...
At the end of the day, if Bloke A's rival, Bloke B, were to sneak onto Bloke
A's computer at lunch time, he could technically run whatever SQL he liked
just by starting up my program (that the password encryption security is a
minor part of), and running it on the server through the application's
interface. But, the crux is, Bloke A would return from lunch, discover Bloke
B had done something, and immediately change his password, and make sure he
locked his terminal in future - the real question is could Bloke B download
a program from the internet, load it onto Bloke A's computer, point it at
the registry and my program's application directory, and hey presto, he
actually *discovers* the password, to use at his own leisure, from his own
computer. That's the only boundary that I'm trying to get the right side of,
if you see what I mean....
I generally tend to assume that the average layman won't understand how to
disassemble assembly language into machine code. However, I don't like to
assume that they don't understand XOR encryption or how to generally browse
around the internet for some cracking program someone else has written.
Nov 16 '05 #49

P: n/a
Yours is equivalent to a simple XOR with a fixed key - see my other
message. Do you seriously believe this to be strong encryption?
No, I don't believe this at all. We've already established that the
algorithm itself shouldn't need to be secret, right?
So discovering the *key* that I use for the encryption and decryption is the
only thing that's going to need to be done to crack it, right?

*So, how does the CryptoAPI help me protect the secrecy of the key any
better than my own algorithm would?*

I'm talking about the DATA that is used for the key - the CODE that is used
to do the equation "key + encrypted => decrypted" is unimportant compared to
this, this is a principle I now accept...
This information may be important in and of
itself. Finally, such an algorithm is subject to substitution
attacks, where an attacker can modify one byte of ciphertext to
affect one character of plaintext (imagine replacing No with Yes
under a contract or a purchase order or something). In a strong
alorithm, modifying one bit of ciphertext results in the decoded
plaintext being a random meaningless jumble from the point of
modification onward, so the tampering is hard to miss.


Eh? Hard to miss? wouldn't it be easy to miss, as you could just say
from what point the meaningless jumble started, and that's where the
tampering occurred...


It is obvious that the message has been tampered with, and not to be
trusted. It does not matter what the original data was, or what the
modification attempt was. The message is discared, alarms are sounded, and
the investigation starts. It's like those tamper-proof medicine bottles -
if the packaging is broken, you don't much care (at least, not
immediately) what exactly happened to the medicine, who did it or for what
reason. It's often enough to know that the medicine is no good anymore.
And... you're saying that an important principle of a good algorithm
is that each byte affects all the others after it, not just itself?


It's generally a very good idea, yes. Usually every byte affects all the
subsequent bytes, as most encryption algorithms work in one pass so it is
hard to retroactively affect preceding bytes. The algorithms need to be
fast, and also they often need to be implemented in a hardware device with
a limited amount of memory that encrypts a large data stream as it moves
past it, so going back to previous bytes is not feasible.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925

Nov 16 '05 #50

113 Replies

This discussion thread is closed

Replies have been disabled for this discussion.