by johnmunro >> Tue, 3 Dec 2002 11:33:55 GMT
I was very happy yesterday to have finally got Crypto API to work in Jade. I had been developing it separately in a single user dev environment to keep from messing up our main dev system. When it seemed to be working, I copied it from the single user to the multi-user (thin client) development environment, and guess what - it no longer works. I wondered whether anyone here has implemented Crypto API and whether there are any peculiarities to making it work thin client. If possible I would like it to all run on the App Server because the Microsoft Strong Crypto Provider (which allows us to have 128bit encryption) comes with win2k and not previous versions of windows (and the server will be running 2k whereas the clients may not).
The external functions I am using are:
cryptAcquireContext(
phProv : Integer io;
pszContainer : String;
pszProvider : String;
dwProvType : Integer;
dwFlags : Integer
) : Integer is CryptAcquireContextA in advapi32;
cryptCreateHash(
hProv : Integer;
algid : Integer;
hKey : Integer;
dwFlags : Integer;
phHash : Integer io
) : Integer is CryptCreateHash in advapi32;
cryptDecryptBinary(
hKey : Integer;
hHash : Integer;
final : Integer;
dwFlags : Integer;
pbData : Binary;
pdwDataLen : Integer io
) : Integer is CryptDecrypt in advapi32;
cryptDeriveKey(
hProv : Integer;
algid : Integer;
hBaseData : Integer;
dwFlags : Integer;
phKey : Integer io
) : Integer is CryptDeriveKey in advapi32;
cryptDestroyHash(
hHash : Integer
) : Integer is CryptDestroyHash in advapi32;
cryptDestroyKey(
hKey : Integer
) : Integer is CryptDestroyKey in advapi32;
cryptEncryptBinary(
hKey : Integer;
hHash : Integer;
final : Integer;
dwFlags : Integer;
pbData : Binary;
pdwDataLen : Integer io;
dwBufLen : Integer
) : Integer is CryptEncrypt in advapi32;
cryptHashData(
hHash : Integer;
pbData : String;
dwDataLen : Integer;
dwFlags : Integer
) : Integer is CryptHashData in advapi32;
cryptReleaseContext(
hProv : Integer;
dwFlags : Integer
) : Integer is CryptReleaseContext in advapi32;
and the encrypt method is on the primitive type Binary:
encryptAPI() : Binary;
constants
Password : String = "I am not a number!";
Container : String = "TestContainer";
MS_DEF_PROV : String = "Microsoft Base Cryptographic Provider v1.0";
MS_ENHANCED_PROV : String = "Microsoft Enhanced Cryptographic Provider"; MS_STRONG_PROV : String = "Microsoft Strong Cryptographic Provider";
PROV_RSA_FULL : Integer = 1;
CRYPT_NEWKEYSET : Integer = 8;
ALG_CLASS_DATA_ENCRYPT : Integer = 24576;
ALG_CLASS_HASH : Integer = 32768;
ALG_TYPE_ANY : Integer = 0;
ALG_TYPE_STREAM : Integer = 2048;
ALG_SID_RC4 : Integer = 1;
ALG_SID_MD5 : Integer = 3;
CALG_MD5 : Integer = 32771; //ALG_CLASS_HASH.bitOr(ALG_TYPE_ANY).bitOr(ALG_SID_MD5)
CALG_RC4 : Integer = 26625; //ALG_CLASS_DATA_ENCRYPT.bitOr(ALG_TYPE_STREAM).bitOr(ALG_SID_RC4);
ENCRYPT_ALGORITHM : Integer = CALG_RC4;
Key_Length : Integer = 8388608; // 128bit - 0x00800000
vars
hProv : Integer;
hHash : Integer;
hKey : Integer;
tmpBinary : Binary;
tmpLength : Integer;
begin
// connect to CSP
if call cryptAcquireContext(hProv, Container, MS_STRONG_PROV, PROV_RSA_FULL, 0) = 0 then // try to connect to an existing container with this name
if call cryptAcquireContext(hProv, Container, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) = 0 then // try to create a container with this name
app.assert(false, "Error during CryptAcquireContext for a new key container.");
endif;
endif;
// create a hash object
if call cryptCreateHash(hProv, CALG_MD5, 0, 0, hHash) = 0 then
app.assert(false, "Error during CryptCreateHash");
endif;
// hash the password
if call cryptHashData(hHash, Password, Password.length, 0) = 0 then
app.assert(false, "Error during CryptHashData");
endif;
// derive a session key from the hash object
if call cryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, Key_Length, hKey) = 0 then
app.assert(false, "Error during CryptDeriveKey");
endif;
// encrypt yourself and return the result
tmpBinary := self;
tmpLength := tmpBinary.length;
if call cryptEncryptBinary(hKey, 0, 1, 0, tmpBinary, tmpLength, tmpLength) = 0 then
app.assert(false, "Error during CryptEncrypt");
endif;
return tmpBinary[1 : tmpLength];
epilog
// destroy session key
if hKey <> 0 then
call cryptDestroyKey(hKey);
endif;
// destroy hash object
if hHash <> 0 then
call cryptDestroyHash(hHash);
endif;
// disconnect from CSP
if hProv <> 0 then
call cryptReleaseContext(hProv, 0);
endif;
end;
If I call this method on a Binary (for example "Hello".Binary or a Binary local variable) it just returns the original Binary. None of the error traps are triggered, so as far as the API is concerned, it has successfully encrypted...
John Munro
---
Synergist Limited - Home of FileVision
The Bioscience Innovation Centre
Cowley Road, Cambridge, UK
CB4 0DS
Telephone: +44 (0) 1223 478200
Fax: +44 (0) 1223 477969
Email: john.munro@filevision.com
Web: http://www.filevision.com
The contents of this communication are confidential and are only intended to be read by the addressee. We apologize if you receive this communication in error and ask that you contact Synergist Limited immediately to arrange for its return. The use of any information contained in this communication by an unauthorized person is strictly prohibited. Synergist Limited cannot accept responsibility for the accuracy or completeness of this communication as it is being transmitted over a public network. If you suspect this message may have been intercepted or amended, please inform Synergist Limited.