I am using CAPICOM
assembly with VBS
logic to encrypt some text
, this works good but the problem starts when trying to replicate the same using Java
.
This is my VBS code:
Option Explicit
Dim strToEncrypt: strToEncrypt = "Content-Type: plain/text; name=""C:\Users\Luigi\Desktop\hello.txt""" & vbCrLf & _
"Content-Disposition: attachment; filename=""C:\Users\Luigi\Desktop\hello.txt""" & vbCrLf & _
"test"
Dim encryptedStr: encryptedStr = CRYPTO_SHA1(strToEncrypt)
WScript.Echo encryptedStr
Private Function CRYPTO_SHA1(strData) 'As String
Const CAPICOM_HASH_ALGORITHM_SHA1 = 0
Dim hash: Set hash = CreateObject("CAPICOM.HashedData")
Dim util: Set util = CreateObject("CAPICOM.Utilities")
Dim stm: Set stm = CreateObject("ADODB.Stream")
stm.Open
stm.Type = 2 'adTypeText
stm.Charset = "us-ascii"
stm.WriteText strData
stm.Position = 0
stm.Type = 1 'adTypeBinary
hash.Algorithm = CAPICOM_HASH_ALGORITHM_SHA1
hash.Hash stm.Read
CRYPTO_SHA1 = util.Base64Encode(util.HexToBinary(hash.Value))
CRYPTO_SHA1 = Left(CRYPTO_SHA1, Len(CRYPTO_SHA1)-Len(vbCrLf))
stm.Close
Set stm = Nothing
Set util = Nothing
Set hash = Nothing
End Function
By debugging the above code, I can get the following:
Hash
object value is:
hash.Value = 636D0172D7FAC85AF9DB57FAE6C7D98B17DE5159
The final result as encryptedStr
is:
encryptedStr = Y20Bctf6yFr521f65sfZixfeUVk=
So, in Java
I am trying to replicate the same and I assume this can be done by...
Getting SHA1
hash of the String
or InputStream
(because at VBS
code there is an stm
object that represents a Stream
).
Use some HexToBinary
method (by implementing this because by default this method doesn't exist in Java
).
Use BASE64Encoder
for the binary String
from SHA1
hash.
Finally, use Left
method from org.apache.commons.lang.StringUtils
(replicate of the VBS
code) and then output encryptedStr
as base64
String
.
This is what I've tried so far in Java to at least generate the SHA1
hash (supposed to be the same as hash.Value
in VBS
:
package my.package;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
public class SHA1Encrypt {
public static void main(String[] args) throws Exception {
String str = "Content-Type: plain/text; name=\"C:\\Users\\Luigi\\Desktop\\hello.txt\"" + "\n" +
"Content-Disposition: attachment; filename=\"C:\\Users\\Luigi\\Desktop\\hello.txt\"" + "\n" +
"test";
String SHA1FromString = getSHA1FromString(str);
String SHA1FromIS = getSHA1FromIS(str);
System.out.println("SHA1 from String is: " + SHA1FromString.toUpperCase());
System.out.println("SHA1 from InputStream is: " + SHA1FromIS.toUpperCase());
}
public static String getSHA1FromString(String str) throws Exception {
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
sha1.update(str.getBytes());
byte[] digest = sha1.digest();
return byteArrayToHexString(digest);
}
public static String getSHA1FromIS(String str) throws Exception{
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
InputStream is = new ByteArrayInputStream(str.getBytes());
BufferedInputStream bis = new BufferedInputStream(is);
DigestInputStream dis = new DigestInputStream(bis, sha1);
while (dis.read() != -1);
byte[] digest = sha1.digest();
return byteArrayToHexString(digest);
}
public static String byteArrayToHexString(byte[] b) {
String result = "";
for (int i=0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
}
The above code will output the following:
SHA1 from String is: 825CA9AF2795F3CCD41EC3B756CC7514E490842F
SHA1 from InputStream is: 825CA9AF2795F3CCD41EC3B756CC7514E490842F
I am using the same String
to be encrypted in both cases (VBS
and Java
).
When I execute VBS
code I get this SHA1
hash value from CAPICOM
:
636D0172D7FAC85AF9DB57FAE6C7D98B17DE5159
When I execute Java
code I get this SHA1
hash value:
825CA9AF2795F3CCD41EC3B756CC7514E490842F
I won't never get the same base64
String
as encryptedStr
if SHA1
hash is not the same.
What I am doing wrong and why did SHA1
hash gets computed different in both cases. Can someone please explain what is happening or what is the correct way to implement this and get the same result in Java
?
Just to know, I found this link that helps a little and says that they can get the same hash
but doesn't fix the problem for my case:
http://us.generation-nt.com/answer/capicom-hasheddata-java-binary-files-help-44910362.html?page=2
If someone wants to install CAPICOM
and test VBS
code, you can do the following:
- Copy "capicom.dll" to "C:\WINDOWS\system32"
- Click on Start/Programs/Accessories/Command Prompt
- Type "C:"
- Type "cd C:\WINDOWS\system32"
- Type "regsvr32.exe capicom.dll"
- Click on the "OK" button.
- Type "exit"
And download the capicom.dll
yourself directly from Microsoft
at:
The correct way to express the String
is using this way:
String str = "Content-Type: plain/text; name=\"C:\\Users\\Luigi\\Desktop\\hello.txt\"" + "\r\n" +
"Content-Disposition: attachment; filename=\"C:\\Users\\Luigi\\Desktop\\hello.txt\"" + "\r\n" +
"test";
instead of \n
, we need to use \r\n
, then SHA1
hashes will be the same.
Thanks Ansgar Wiechers for exposing this.