Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Q]Symmetric Encryption problem with Java and Crypto API

74 views
Skip to first unread message

Omer Hasret

unread,
Nov 28, 2001, 7:04:02 AM11/28/01
to
I am trying to send symmetrically encrypted information from Java to
C++. However, Crypto API cannot decrypt the message. I am certain that
I use the same keys on both sides.

I tried to encrypt the same value on both sides to see whether I get
the same encrypted bytes. This also did not work. I use Sun JCE1.2 on
Java side with algorithm "DES/EBC/PKCS5Padding" On C++ side, I use
CryptEncrypt function with CALG_DES symmetric key which I import into
the CSP using a private key of exponent one. (Thus I know I have the
same keys. It is; 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 - 8 bytes of
0x01)

Is there anybody that could help me with this problem?

Thanks in advance.

Vitaly Korovinsky

unread,
Nov 28, 2001, 11:20:32 AM11/28/01
to
Omer,

What Windows platform are you using? Also if you post your code it would be
easier to find the problem.

"Omer Hasret" <has...@uekae.tubitak.gov.tr> wrote in message
news:b58a1c1e.01112...@posting.google.com...

Omer Hasret

unread,
Nov 29, 2001, 3:14:23 AM11/29/01
to
OK, here is the code I use in Win32 Crypto API. (Windows 2000);


HCRYPTKEY hPubPrivKey = 0;
HCRYPTKEY hSessionKey = 0;
LPBYTE pbKeyMaterial = NULL;
DWORD dwKeyMaterial ;
int n;



HCRYPTPROV hCryptProv;


if(CryptAcquireContext(
&hCryptProv, // Handle to the CSP
"OMER", // Container name
MS_ENHANCED_PROV, // Provider name
PROV_RSA_FULL, // Provider type
0)) // Flag values
{
printf("A crypto context with the %s key container \n", "OMER");
printf("has been acquired.\n\n");
}

// Create Exponent of One private key

if (!(CreatePrivateExponentOneKey(MS_ENHANCED_PROV, PROV_RSA_FULL,
"OMER", AT_KEYEXCHANGE,
&hCryptProv, &hPubPrivKey)))
{
printf("CreatePrivateExponentOneKey failed with %x\n",
GetLastError());
}

// Here I am setting the session key - 8 bytes of 0x43 (the Char 'C')

pbKeyMaterial = (LPBYTE)LocalAlloc(LPTR, 64/8);
for (n = 0; n < 64/8; n++) pbKeyMaterial[n] = 0x43;
dwKeyMaterial = 64/8;


if (!ImportPlainSessionBlob(hCryptProv, hPubPrivKey, CALG_DES,
pbKeyMaterial, dwKeyMaterial, &hSessionKey))
{
printf("ImportPlainSessionBlob failed with %x\n",
GetLastError());
}

LocalFree(pbKeyMaterial);
pbKeyMaterial = NULL;

//CryptGenKey(hCryptProv,CALG_RC2,NULL,&hSessionKey);
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------

// Here I export the session key I imported above just for checking.
// I use a private key of exponent one.


if (!(ExportPlainSessionBlob(hPubPrivKey, hSessionKey,
&pbKeyMaterial , &dwKeyMaterial
)))
{
printf("ExportPlainSessionBlob failed with %x\n",
GetLastError());
}

// Print Key material
printf("3DES session key:\n");
for (n = 0; n < dwKeyMaterial; n++)
{
if (n%8 == 0) printf(" ");
printf("%02x", pbKeyMaterial[n]);
}
printf("\n");

//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------

DWORD dwCount=8;
BYTE *input;
input = (BYTE*)malloc(8);

for (n=0;n<dwCount;n++)
input[n]=0x43;


// Encrypt data.
if(!CryptEncrypt(
hSessionKey,
0,
1,
0,
NULL,
&dwCount,
8))
{
printf("Error during CryptEncrypt. \n");
}

input = (BYTE *)malloc(dwCount);

if(!CryptEncrypt(
hSessionKey,
0,
1,
0,
input,
&dwCount,
24))
{
printf("Error during CryptEncrypt2. \n");
}

for (n=0;n<dwCount;n++)
printf(" %02x",input[n]);

printf("\n");
//--------------------------------------------------------------------

// Everything goes fine however what I get from C++ is different than
what I
// get from Java Sun JCE.

//--------------------------------------------------------------------
//--------------------------------------------------------------------

Thanks for your reply.


Omer.
PS: For the java code, it is a simple
Cipher cp = Cipher.getInstance("DES/ECB/PKCS5Padding");
cp.doFinal()


"Vitaly Korovinsky" <nospam....@sympatico.ca> wrote in message news:<Nb8N7.14965$Vm5.2...@news20.bellglobal.com>...

Thomas Maslen

unread,
Nov 29, 2001, 5:16:05 AM11/29/01
to

I'm not familiar with the C crypto API you're using, only with the Java one,
but I think you're mixing up two completely different things:

In the Java code you are (correctly, I think) using DES, which is
a block cipher and uses a symmetric key (or "secret key"), i.e.
both the sender and the receiver use the same key.

In the C code it looks to me as though you are using RSA encryption,
where there is a key pair (a private key and corresponding public key).

In other words, I think your Java code is correct and your C code is wrong --
you need to find the part of the C API that deals with symmetric ciphers like
DES and use that instead.

Thomas Maslen
tma...@wedgetail.com

Vitaly Korovinsky

unread,
Nov 29, 2001, 5:00:44 PM11/29/01
to
Omer,

Here is a sample where java code and C code produce identical results. I
could not get the first call to CryptEncrypt working. The one which supposed
to return the size of encrypted data block. I bet your code wasn't working
for the same reason. If anyone figures out how to do it let me know.

// ------------------------------
JAVA -----------------------------------------------
public static void main(String[] args) {
try {
// Add security provider
Security.addProvider( new com.sun.crypto.provider.SunJCE() );
// hash the password
MessageDigest md = MessageDigest.getInstance("MD5");
md.update("password".getBytes());
// create key
DESKeySpec key = new DESKeySpec (md.digest());
SecretKeySpec DESKey = new SecretKeySpec (key.getKey(), "DES");
// create cipher
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, DESKey);
// encrypt info
byte[] cipherEncryptText = cipher.doFinal("Hello World!".getBytes());
// print encrypted message
for (int i=0; i<cipherEncryptText.length; ++i)
{
System.out.print(Integer.toHexString(cipherEncryptText[i]));
System.out.print(" ");
}
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
}

// ------------------------------ C CRYPTO
API -----------------------------------------------
void main()
{
BOOL bResult=false;
HCRYPTPROV hProv=0;

// Attempt to acquire a handle to the default key container.
bResult = CryptAcquireContext(
&hProv, // Variable to hold returned handle.
NULL, // Use default key container.
MS_ENHANCED_PROV_A, // Use enhanced CSP.
PROV_RSA_FULL, // Type of provider to acquire.
0); // No special action.

// Create hash object
HCRYPTHASH hHash=0;
bResult=CryptCreateHash(
hProv, // CSP handle
CALG_MD5, // hash algorith ID
0, // Key not used
0, // flags not used
&hHash // handle to the hash object
);

// hash password
char sPassword[]="password";
bResult=CryptHashData(
hHash, // hash handle
(unsigned char*) sPassword,// pointer to the data buffer
strlen(sPassword), // data length
0 // flags not used
);

// Create key from hash
HCRYPTKEY hKey=0;
bResult=CryptDeriveKey(
hProv, // CSP handle
CALG_DES, // algorithm id
hHash, // hash object
0, // flags are not used
&hKey // key handle
);

// set encryption mode to ECB
DWORD dwParam=CRYPT_MODE_ECB;
bResult=CryptSetKeyParam(
hKey, // key handle
KP_MODE, // set key mode flag
(unsigned char*) &dwParam, // new mode value
0 // flags not used
);

// set padding mode to PKCS5
dwParam=PKCS5_PADDING;
bResult=CryptSetKeyParam(
hKey, // key handle
KP_PADDING, // set key mode flag
(unsigned char*) &dwParam, // new mode value
0 // flags not used
);


// create big buffer
char sSrcData[]="Hello World!"; // source data
DWORD dwDataLen=strlen(sSrcData); // size of the source data
DWORD dwSize=dwDataLen; // size of the encrypted data

/* THIS DOESN'T WORK.
1. Does not update dwSize value
2. Affects (screws up) encrypted data
3. Am I using it the wrong way?????
// Get the size of the encrypted block
bResult = CryptEncrypt(
hKey, // Key obtained earlier
0, // No hashing of data
FALSE, // Final or only buffer of data
0, // Must be zero
0, // No data this time
&dwSize, // length of the source data
0 // Size of block
);
// allocate and intialize the buffer
char* sDestData=new char[dwSize];
strcpy(sDestData, sSrcData);
*/

// Allocate big buffer
dwSize=200;
char* sDestData=new char[dwSize];
strcpy(sDestData, sSrcData);

// Now encrypt the data
bResult = CryptEncrypt(
hKey, // Key obtained earlier
0, // No hashing of data
TRUE, // Final or only buffer of data
0, // Must be zero
(unsigned char*)sDestData, // Data buffer
&dwDataLen, // Size of data
dwSize // Size of block
);

// print out encrypted data
for (unsigned int i=0; i<dwDataLen; ++i)
{
printf("%2x ",unsigned char(sDestData[i]));
}

// cleanup
if(hHash != 0) CryptDestroyHash(hHash);
if(hKey != 0) CryptDestroyKey(hKey);
if(hProv != 0) CryptReleaseContext(hProv,0);

}

Best regards,
Vitaly Korovinsky
Brainbench MVP for Internet Security
http://www.brainbench.com

0 new messages