Link to home
Start Free TrialLog in
Avatar of SweatCoder
SweatCoderFlag for United States of America

asked on

VB6 - crypto api advapi.dll - doesn't work in japanese?

I have a vb6 crypto module that works great on a standard American windows 2003 server. but when i run it on a Japanese Windows 2003, all the crypto strings get mangled.

How can I resolve this?

Here's a partial example of the top portion of my component:

Private Const lngALG_CLASS_DATA_ENCRYPT                 As Long = 24576&
Private Const lngALG_CLASS_HASH                         As Long = 32768
Private Const lngALG_SID_MD5                            As Long = 3&
Private Const lngALG_SID_RC4                            As Long = 1&
Private Const lngALG_TYPE_ANY                           As Long = 0&
Private Const lngALG_TYPE_STREAM                        As Long = 2048&
Private Const lngCALG_MD5                               As Long = ((lngALG_CLASS_HASH Or lngALG_TYPE_ANY) Or lngALG_SID_MD5)
Private Const lngCALG_RC4                               As Long = ((lngALG_CLASS_DATA_ENCRYPT Or lngALG_TYPE_STREAM) Or lngALG_SID_RC4)
Private Const lngCRYPT_NEWKEYSET                        As Long = 8&
Private Const lngENCRYPT_ALGORITHM                      As Long = lngCALG_RC4
Private Const lngPROV_RSA_FULL                          As Long = 1&
Private Const strKEY_CONTAINER                          As String = "TestString"
Private Const strSERVICE_PROVIDER                       As String = "Microsoft Base Cryptographic Provider v1.0"
Private Const strMODULE_NAME                            As String = "clsCryptography"
Private Const lngERR_NUMBER_SUCCESS                     As Long = 0
Private Const strEncryptionPassword                     As String = "[removed]"

Private Declare Function CryptAcquireContext Lib "advapi32.dll" _
   Alias "CryptAcquireContextA" ( _
   ByRef phProv As Long, _
   ByVal pszContainer As String, _
   ByVal pszProvider As String, _
   ByVal dwProvType As ProviderType, _
   ByVal dwFlags As AquireContextFlags) As Long

                         
Private Declare Function CryptCreateHash Lib "advapi32.dll" _
    (ByVal hProv As Long, _
     ByVal Algid As Long, _
     ByVal hKey As Long, _
     ByVal dwFlags As Long, _
     ByRef phHash As Long) As Long
                         
Private Declare Function CryptHashData Lib "advapi32.dll" _
    (ByVal hHash As Long, _
     ByVal pbData As String, _
     ByVal dwDataLen As Long, _
     ByVal dwFlags As Long) As Long

[. . .much more]
ASKER CERTIFIED SOLUTION
Avatar of nffvrxqgrcfqvvc
nffvrxqgrcfqvvc

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of SweatCoder

ASKER

I haven't tried StrConv, but I will. I'm a little unsure where exactly I should call this function. In each place where a string is referenced in the encryption code? Just at the beginning of the call stack? Just on the end result?

Any ideas here? I was just going to experiment, but if you know the answer it could really save me some time.

I was also wondering if the crypto api that ships with windows is fundamentally different between english os and japanese os. If so, I got problems. If not, maybe the StrConv will solve the problem. . .
If your passing hardcoded english strings in your application and you pass them on a japenese machine the characters are not the same. You need to use the japanese language to pass it correctly.
the only hardcoded string in the dll is my encryption password. i'm not sure if i'm using the right term, but it's the password used to generate an encryption algorithm and also to decrypt that encrypted string.

but what you say puzzles me, because all ascii characters are the same between english and japanese, right? the first 256 characters are universal i thought. so when i'm sending plain english ascii strings to be encrypted on a japanese os it should handle it just fine, shouldn't it?
Yes in your scenario that is correct.

Let me just ask you what exactly is going on:
Private Const strEncryptionPassword                     As String = "[removed]" <-- is this the password your tryng to set?

Are you just trying to secure a password in the registry so no prying eyes can read it?
my password is actually hardcoded in there. i put [removed] on the EE post. that's not literally what i have in the vb class. only the dll is deployed with our app, not the source code, so presumably there's no way someone could pick that password out of the compiled dll. or if there is, let me know a better way. it seems it would be easier to steal it out of the registry than from inside a dll.
Alright. If you want to secure somethingin in the registry then try using my DLL (RSEC)
'Not sure if this meets your needs Note: This is a standard DLL which can be called by API just drop DLL into system32 directory.
http://www.geocities.com/egl1044/regSecure.zip
my bad this is the link not he above link:
http://www.geocities.com/egl1044/RSEC_API.zip
egl, i have been experimenting ad nauseum with StrConv(MyString,vbWide), all to no avail. I installed VB6 on my Japanese Win2003 and I've been stepping through code and debugging. I tried putting the StrConv prior to the encryption, during, afterward, prior to decryption, during, afterward. . .and about every combination of these, and in every case, the decrypted string either ends up looking like japanese symbols, or else they come out in english, but the last few characters are missing.

I see you have posted a zip, but will this specifically solve my japanese problems? I want to emphasize that I am happy with my current encryption class, and it works great for me in english. I don't want to switch just so I can store password in registry. I would be happy to switch to your class if it will work correctly on JP and English.

So please let me know, or give me some other ideas to try with StrConv.

thanks.
I have no way to test it on a jap machine but you could test it and see if it works. The difference between your encryption and my rsec.dll is that anyone who actually finds the key won't be able to delete it when you pass the Deny_registry_permission function also they won't even be able to read whats inside the folder so it is very secure. Just give it a test and see what it returns back to you.

After you drop the dll into system32 then try the following.
Example:
'Add the line below to 1 command button
Write_Reg "SOFTWARE\TEST\TESTING", "pw", "mypassword"

'Add this line to another command button
MsgBox Get_Reg("SOFTWARE\TEST\TESTING", "pw")

See what it returns back on your jap machine.
all your code seems to be aimed at reading and writing to/from the registry. . .I see no declares for encryption and decryption. where are these, and what's the sample usage?
There is no need for encryption because when we pass the Deny_Registry_permission function nobody can access the information nor delete the information it is invisible to anyone.

Just try this and tell me what it returns on your jap machine:

New standard.exe

Add 4 command buttons to a form
Copy and paste the below  code into the form
Make sure you copy the RSEC.DLL to system32 directory. (You can delete it later if your not satasfied.)

First just click command button 1 then click command button 2 and tell me what it returns.
Now click command3 then look in the registry with regedit under (HKEY_LOCAL_MACHINE\SOFTWARE\TEST)
Try and delete it you can't and you can't see your password either.

Now click command4 button, then go back to the registry and look. Now you will see that it reveals everyting.
'**********************
'add code to form
'**********************

Option Explicit

Private Declare Function Get_Reg Lib "RSEC.DLL" (ByVal regSubkey As String, ByVal regDataString As String)
Private Declare Sub Delete_Reg_Key Lib "RSEC.DLL" (ByVal regMainKey As String, ByVal regSubkey As String)
Private Declare Sub Write_Reg Lib "RSEC.DLL" (ByVal regPath As String, ByVal regValue As String, ByVal regData As String)
Private Declare Sub Allow_Registry_Permission Lib "RSEC.DLL" (ByVal regSubkey As String)
Private Declare Sub Deny_Registry_Permission Lib "RSEC.DLL" (ByVal regSubkey As String)

Private Sub Command1_Click()
Write_Reg "SOFTWARE\TEST\TESTING", "pw", "mypassword"
End Sub

Private Sub Command2_Click()
MsgBox Get_Reg("SOFTWARE\TEST\TESTING", "pw")
End Sub

Private Sub Command3_Click()
Deny_Registry_Permission "SOFTWARE\TEST"
End Sub

Private Sub Command4_Click()
Allow_Registry_Permission "SOFTWARE\TEST"
End Sub

Private Sub Form_Load()

Command1.Caption = "save password"
Command2.Caption = "get password"
Command3.Caption = "deny permisson"
Command4.Caption = "allow permission"

End Sub
ahhhhhhh! by your statement "there is no need for encryption" I see you have completely misunderstood the reason for my original post.

our web app USES encryption. for all kinds of things. encrypting passwords in the DB. encrypting database credentials so we don't have to store these credentials in plain text in global.asa or elsewhere. encrypting querystring values that pass from page to page so they can't be tampered with.

My whole point in posting this, which I thought was clear in my original post, is that our encryption algorithms DON'T WORK on a japanese machine, and I need to get them to work. So now I see that all you are offering is a way to store a single value in the registry. I'm sure this is cool and all, but it doesn't help me at all.

Thanks for trying to help anyway. I'm going to request that this question be closed, and I'm going to post a new question that is hopefully more clear. Sorry for inconvenience.
My Bad. I thought you were just trying to encrypt some strings in the registry. Sorry for taking up your time. However I would overlook your code. You might need to create a larger string buffer. Also include all the information you just said above in the next question as it wasn't as clear as it would be with that extra crucial information.
I understand, thank you. Your hint about StrConv() was actually valid, and may end up saving me if i can implement it right. So i'm just going to go ahead and accept that answer.
Have you tried StrConv with vbFromUnicode or vbUnicode?
no, but i'll try.