|
I'm basically searching for how you generate the RSA key pair, export to the public key, export a session key using that exported public key, then import that back to the owner of the public key. So it looks like you have it already exported to the file, how was that done and why is there a hard code private key?
|
|
|
|
|
Hello,
We want to use your code ideas in our program. Our purpose is to encrypt a key to create an activation code for a program to run. All this works fine in western character sets. But for Japanese character set, it does not. For example, in your sample program, if you enter a key in English and Japanese characters, the English ones are encrypted/decrypted but not Japanese characters. They are simple ignored (i.e. returned as blank). How can we achieve coding Japanese/Chinese character sets?
Thank you,
Athena
|
|
|
|
|
The problem comes because it is encrypted as characters. Western characters take one byte for each character while other such as Japaneese characters(?) might take two bytes for each character - and characters that are unknown are displayed as small squares or other "unknown" symbols.
The simplest approach that I currenly have in mind is to handle all characters as binary data. In that way you are encrypting a memory block i.e. use byte*, memcpy, malloc etc instead of char*, strncpy and other string functions.
Hth
--
Jess Nielsen, m. it (sw. dev.)
Software Architect
Blog
http://jessn.blogspot.com/
Support & help
https://groups.google.com/forum/#!forum/nielsen-tools-support
|
|
|
|
|
Hello Jess,
Thank you for your reply. I will look into your suggestion. MS Crypto API should have handled these problems t the frnt hand. It is universal isn’t it? Once the text boxes in which the string to be encoded are set to be in Japanese script, it should handle the characters in Unicode and encode them as, say, two byte strings, instead of one byte ASCII strings.
Sincerely,
Cem
Athena
|
|
|
|
|
Hi,
I am looking some good article, website or book which I can purchase for programming using windows digital certificate api. The MSDN doesn't seems to be of much help. Please advice me. Thank you.
Regards,
Daniel Ramnath.
Jesus saves
|
|
|
|
|
Hi there,
after I downloaded the code I ran it for a few times.....but later I tried to run it again then It just keep showing me the error message
"Error [0x%x]: CryptImportKey() failed"
could you please help me how can I fix this error.
thanx
|
|
|
|
|
I made the code some years ago, so I cannot remember it in details. However as far as I remember, I think you are getting the error because it fails to import the key. It creates AND stores the key in a file first time you execute the code. All other times it tries load the key as long as the file exists - you have to delete the file.
You can find the filename in the code.
Hth
Jess
BTW.: The persistence of the key is not properly tested, I did only test the encryption/decryption approach. Feel free to fix the persistence or use another mechanism to store the key.
--
Jess Nielsen, m. it (sw. dev.)
Software Architect
http://jessn.blogspot.com/
|
|
|
|
|
Hi ! I have been trying to use the crypto API to decript an AES_128 crypted file.
the key to decrypt this file is a SHA1 hash of a certain keyword, so I made a code that should work but doesn't ( you know the feeling ^^ )
so please if someone can help me out I would be very grateful.
the function that seems to crash is the last one the cryptdecript function.
The error message I get from my fonction is : "crypt decript failed : incorect data"
here is my full code :
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <windows.h><br />
#include <wincrypt.h><br />
<br />
<br />
#define buf_size 2048<br />
<br />
void ErrorExit(LPTSTR lpszFunction) <br />
{ <br />
<br />
LPVOID lpMsgBuf;<br />
LPVOID lpDisplayBuf;<br />
DWORD dw = GetLastError(); <br />
<br />
FormatMessage(<br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM |<br />
FORMAT_MESSAGE_IGNORE_INSERTS,<br />
NULL,<br />
dw,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br />
(LPTSTR) &lpMsgBuf,<br />
0, NULL );<br />
<br />
<br />
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, <br />
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); <br />
printf("%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf); <br />
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); <br />
<br />
LocalFree(lpMsgBuf);<br />
LocalFree(lpDisplayBuf);<br />
ExitProcess(dw); <br />
<br />
system("PAUSE");<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
printf("depart");<br />
<br />
char * texte[buf_size+1];<br />
char * texte2[buf_size+1];<br />
FILE* fd;<br />
int i=0,j=0,k=0;<br />
char value;<br />
<br />
char * buffer[buf_size+1]; <br />
<br />
if( (fd=fopen("C:\\Dev-Cpp\\projects\\decriptage\\1009369384.stream","rb")) == NULL )<br />
{<br />
perror("opening failed"); <br />
exit(0);<br />
}<br />
memset(buffer,0,2048);<br />
memset(texte,0,2048);<br />
memset(texte2,0,2048);<br />
<br />
system("PAUSE");<br />
i=0;<br />
while( fread(&texte,1,1*sizeof(char) ,fd)== 1 ){<br />
i++;<br />
strcat(texte2,texte);<br />
} <br />
<br />
<br />
<br />
<br />
printf("::::%d::::\n%s\nfin fichier crypté.\n\n",i,texte2); <br />
i=0;<br />
char * cle="ironboy007@hotmail.fr";<br />
HCRYPTPROV hProv = 0;<br />
HCRYPTHASH hHash = 0;<br />
HCRYPTKEY hKey = 0;<br />
DWORD Len_txt = (DWORD)strlen(texte);<br />
DWORD Len_txt2 = (DWORD)strlen(texte2);<br />
DWORD Len_cle = (DWORD)strlen(cle);<br />
DWORD ret;<br />
i=0;<br />
while(texte[i]!='\0')i++; <br />
while(texte2[j]!='\0')j++;<br />
while(cle[k]!='\0')k++;<br />
printf("texte:%d\n", i);<br />
printf("texte2:%d\n", j); <br />
printf("clé:%d\n", k);<br />
if ( !CryptAcquireContext (&hProv, NULL, NULL, PROV_RSA_AES, 0) )<br />
{<br />
ret = GetLastError();<br />
<br />
if (ret != NTE_BAD_KEYSET)<br />
{<br />
perror("1" );<br />
}<br />
else <br />
{<br />
if ( !CryptAcquireContext (&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_NEWKEYSET) )<br />
{<br />
perror("2" );<br />
}<br />
}<br />
}<br />
<br />
if ( !CryptCreateHash (hProv, CALG_SHA1, 0, 0, &hHash) )<br />
{ <br />
if (hProv) CryptReleaseContext(hProv, 0);<br />
perror("3" );<br />
}<br />
<br />
if ( !CryptHashData (hHash, cle, Len_cle, 0) )<br />
{<br />
if (hHash) CryptDestroyHash(hHash); <br />
if (hProv) CryptReleaseContext(hProv, 0);<br />
perror("4" );<br />
}<br />
<br />
if ( !CryptDeriveKey (hProv, CALG_AES_128, hHash, 0, &hKey) )<br />
{<br />
if (hHash) CryptDestroyHash(hHash); <br />
if (hProv) CryptReleaseContext(hProv, 0);<br />
perror( "5" );<br />
ErrorExit(TEXT("CryptDeriveKey"));<br />
ret = GetLastError();<br />
printf("%s", ret);<br />
}<br />
<br />
<br />
if ( !CryptDecrypt(hKey, 0, TRUE, 0, texte2, &Len_txt2) ) <br />
{<br />
ErrorExit(TEXT("CryptDecrypt"));<br />
ret = GetLastError();<br />
printf("%d", ret);<br />
ErrorExit(TEXT("CryptDecrypt"));<br />
system("PAUSE");<br />
<br />
ErrorExit(TEXT("CryptDecrypt"));<br />
system("PAUSE");<br />
if (hKey) CryptDestroyKey(hKey);<br />
if (hHash) CryptDestroyHash(hHash); <br />
if (hProv) CryptReleaseContext(hProv, 0); <br />
}<br />
<br />
printf("::::%d::::\n%s\nEnd of decrypted file.\n\n",strlen(texte2),texte2);<br />
<br />
if (hKey) <br />
CryptDestroyKey(hKey);<br />
<br />
if (hHash) <br />
CryptDestroyHash(hHash); <br />
<br />
if (hProv) <br />
CryptReleaseContext(hProv, 0);<br />
<br />
system("PAUSE");<br />
system("PAUSE"); <br />
return 0;<br />
<br />
}<br />
<br />
thanks in advance.
|
|
|
|
|
Hi Jessn,
Thanks a lot for this code, I am trying to use it on a small app I am creating but I was reading some of the comments and you mention that there are some bugs on the code and that you were going to correct them... Is the code diplayed here the fixed one? if not, which are the bugs you noticed so I can be aware?
Thanks!
|
|
|
|
|
Gonzalo Parra wrote: Hi Jessn,
Thanks a lot for this code, I am trying to use it on a small app I am creating but I was reading some of the comments and you mention that there are some bugs on the code and that you were going to correct them... Is the code diplayed here the fixed one? if not, which are the bugs you noticed so I can be aware?
Thanks!
I have pasted some code snippets in the threads with minor corrections to the codebase. These should be the corrections. What so ever please perform a test on your own, because the provided code/sample app is only a prototype.
Regards,
--
Jess Nielsen, b.sc.
Security Analyst
http://jessn.blogspot.com/
|
|
|
|
|
Hi Jess,
Thanks a lot for the fast response...
I was able to incorporate it into my app but but there is something that I would still like to fix and don't know how (sorry, I do not have that much experience with C++):
The Cipher text contains some extra characters at the end as somebody here pointed and you mentioned to null terminate a string to fix it... could you please help me with this? which string do I need to null terminate and how can I do that?
Thanks!
|
|
|
|
|
Gonzalo Parra wrote: Hi Jess,
Thanks a lot for the fast response...
I was able to incorporate it into my app but but there is something that I would still like to fix and don't know how (sorry, I do not have that much experience with C++):
The Cipher text contains some extra characters at the end as somebody here pointed and you mentioned to null terminate a string to fix it... could you please help me with this? which string do I need to null terminate and how can I do that?
Thanks!
When terminating a string you will have to set the last char to '\0'. This means for the string like "the man on the moon" the length will be the number of the characters plus one for the null-terminating character. This is important when allocating the memomry for the string. Always remember to allocate an extra than is reserved for the null-terminating character. Before usage of newly allocated it is normally initialized e.g memset(psz, 0, strlen(psz)). This sets all allocated characters to zero/null even the null-terminating character.
char * pSz = "....";
pSz[strlen(pSz)-1] = '\0'; // the last character will now be null
Hth
--
Jess Nielsen, b.sc.
Security Analyst
http://jessn.blogspot.com/
|
|
|
|
|
|
In your example, the output included non ascii characters. Is it possible to restrict the encrypted output to alphanumeric characters?
|
|
|
|
|
Angus Comber wrote: In your example, the output included non ascii characters. Is it possible to restrict the encrypted output to alphanumeric characters?
Instead of changing the output of the algoritm I will suggest that you perform a base64 encoding of the output. I have made a similar solution where the output should be used as a http get parameter and no data was lost or "obfuscated" doing base64 encoding.
Hth
--
Jess Nielsen, b.sc.
Security Analyst
http://jessn.blogspot.com/
|
|
|
|
|
Thanks for your great code.
However, I found that while encrypting/decrypting some specific combination of characters, it doesn't work right. I am not able to reproduce the problem because with different value of the key, the result are different. Have you experienced this and how may I solve it?
Thanks again.
Simon
|
|
|
|
|
nomicism wrote: Thanks for your great code.
However, I found that while encrypting/decrypting some specific combination of characters, it doesn't work right. I am not able to reproduce the problem because with different value of the key, the result are different. Have you experienced this and how may I solve it?
Thanks again.
Simon
It might be possible to fix it if you choose to use byte data instead of the char pointers. This means that you "just" take a part from the memory and encrypt it. A simple way of doing this is by having a pointer to where the data block starts and a long indicating the length of the data block. Copying of these blocks can be done with memcpy().
Anyhow this requires that you change the current implementation. The implementation is provided as is and it is *just* a prototype, so you are welcome to change it.
Hth
--
Jess Nielsen, b.sc.
Security Analyst
http://jessn.blogspot.com/
|
|
|
|
|
The origin of the key and more... can be found on external article (Year 2001):
PHD Computer Consultants Ltd. Setting the RC4 key in Windows CryptoAPI
Article Copyright © 2001,2003 PHD Computer Consultants Ltd.
http://www.phdcc.com/cryptorc4.htm
This old article is base on Microsoft Q228786:
How to export and import plain text session keys by using CryptoAPI
Article Copyright © ???? Microsoft.
http://support.microsoft.com/?scid=kb%3Ben-us%3B228786&x=24&y=10
...
|
|
|
|
|
Hi Jessn,
I was coding based on your codes, and I run into the problem of imports/exports. This is what I did.
I see that in the absence of key.txt, you generate a session key based on a hard-coded key in key.h. So I mimick that by doing
HCRYPTKEY pkey;
int res = CryptGenKey(m_prov, CALG_RC4, CRYPT_EXPORTABLE, &pkey);
res = CryptExportKey(pkey, 0, PUBLICKEYBLOB , 0, NULL, &size); // to get the size.
It miserably fails, saying that a bad key is provided.
Then I tried
HCRYPTKEY pkey;
int res = CryptGenKey(m_prov, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &pkey);
res = CryptExportKey(pkey, 0, PUBLICKEYBLOB , 0, NULL, &size); // to get the size.
And I get some hundred bytes for the key. Then I replaced the key in key.h with these bytes. It seems to be running perfectly okay on 1 PC. But then when I generate the session key on one pc, export it into a file, import it on another PC, and try to decrypt whatever that's been encrypted, I get a Bad Data error (NTE_BAD_DATA).
This problem doesn't occur when I use your key. What mistakes have I made in generating this key? How did you generate that key?
-- modified at 3:48 Tuesday 18th April, 2006
|
|
|
|
|
Hi Ray
I have noticed a few bugs in my sample code, which I'm going to correct soon. This means when my new laptop has been installed. During the easter my previous laptop just entered its period of retirement. I noticed this the hard way.
What so ever until the few bugs have been corrected and I have been looking into your problem pleace notice that that the keys are generated in the scope of your CSP. This can cause problems when tranferring between two PCs. I will try to help you with this when my home dev.enrivonment is up and running again. I expect it to be running at the end of this week. I have a few high priority meetings and tasks as well, which has to be done first that's why.
When you are using the AT_KEYEXCHANGE instead of the CALG_RC4 you are generating a public/private key pair.
-- snip --
In addition to generating session keys for symmetric algorithms, this function can also generate public/private key pairs. Each CryptoAPI client generally possesses two public/private key pairs. To generate one of these key pairs, set the Algid parameter to one of the following values.
-- snip --
Hth
Jess
--
Jess Nielsen
Security Analyst
C++ Programmer
|
|
|
|
|
Hi Jess,
Thank you very much for your help.
I have given it another shot, and I ran into the same problem where the
session key cannot be imported on the second PC. This time, it is bad key error during import.
These are the related bits of codes (where PKey is the BYTE* for the hard-coded key). May I have some quick suggestions as to where I have made the mistakes?
(for producing the hard-coded key)
if (!CryptAcquireContext(&m_prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
HCRYPTKEY pkey = 0;
DWORD size = 2048;
DWORD flag = CRYPT_EXPORTABLE;
flag |= 0x00010000 * size;
int res = CryptGenKey(m_prov, CALG_RSA_KEYX, flag, &pkey);
res = CryptExportKey(pkey, 0, PUBLICKEYBLOB, 0, NULL, &size);
BYTE *pk = new BYTE[size+1]; memset(pk, 0, sizeof(pk));
res = CryptExportKey(pkey, 0, PUBLICKEYBLOB, 0, pk, &size);
}
(then for generating the session key)
HCRYPTKEY pkey, key;
if (!CryptAcquireContext(&m_prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
int res = CryptImportKey(m_prov, PKey, sizeof(PKey), 0, 0, &pkey);
DWORD size = 128;
DWORD flag = (0x00010000 * size) |= CRYPT_EXPORTABLE;
if (CryptGenKey(m_prov, CALG_RC4, flag, &key))
{
int res = CryptExportKey(m_key, pkey, SIMPLEBLOB , 0, NULL, &size);
ret = new BYTE[size+1]; memset(ret, 0, (size+1)*sizeof(BYTE));
res = CryptExportKey(key, pkey, SIMPLEBLOB , 0, ret, &size);
}
}
(then for importing the session key on the second PC)
HCRYPTKEY pkey, key;
if (!CryptAcquireContext(&m_prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
int res = CryptImportKey(m_prov, PKey, sizeof(PKey), 0, 0, &pkey);
<big> int res = CryptImportKey(m_prov, pbBlob, cbBlob, pkey, CRYPT_EXPORTABLE, &key);</big> if (!res)
{
dwResult = GetLastError();
printf("Error: CryptImportKey() failed: %x %x.\n", res, dwResult);
}
}
|
|
|
|
|
Hi Ray,
Sorry for the late response, I have just been at bit tight up - more than expected. A thing that pops into my eyes is the container chosen. When aquiring the context you give a '0', which means it takes the default container for your CSP. I have had a few bad experiences with this (not particular in this approach), but i.e. when the security component is used from another context than the interactive user.
Do you think it is possible for you to make a small sample application (read: non-production code) and send it to me, I'll then take a look at it. (please find my email at my cv, the url is in my profile)
Hth
--
Jess Nielsen
Security Analyst
C++ Programmer
|
|
|
|
|
Hi Jess.
Thanks for your time and help. At the moment, I am stuck with a few other projects at work while the one with encryption is on hold. So I will need some spare time to prepare it.
Thanks again, and I hope I can get the sample application ready ASAP.
Regards
Ray
|
|
|
|
|
Hi Ray
That's OK, I'll be awaiting a mail from you.
The article at the following URL might have your interest. It is primary about building secure applications.
http://jess.heidrun.dk/cv/BuildingSecureApp.pdf[^]
Regards,
Jess
--
Jess Nielsen
Security Analyst
C++ Programmer
|
|
|
|
|
The publication at the link below might be interesting to some of you guys.
Building Secure Applications[^]
Take a look at it, I think it is worth reading!
--
Jess Nielsen
Systems Developer
C++ Programmer
|
|
|
|
|