Capicom SHA1哈希在Java中的计算方式不同

时间:2013-05-16 17:40:13

标签: java windows vbscript sha1 capicom

我正在使用带有CAPICOM逻辑的VBS程序集来加密某些text,这很有效,但尝试使用Java复制时会出现问题。

这是我的VBS代码:

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

通过调试上面的代码,我可以得到以下内容:

Hash对象值为:

hash.Value = 636D0172D7FAC85AF9DB57FAE6C7D98B17DE5159

encryptedStr的最终结果是:

encryptedStr = Y20Bctf6yFr521f65sfZixfeUVk=

所以,在Java我试图复制相同的内容,我认为这可以通过...来完成...

  1. 获取SHA1String的{​​{1}}哈希值(因为在InputStream代码处有一个VBS对象代表{{1} }})。

  2. 使用一些stm方法(通过实现此方法,因为默认情况下Stream中不存在此方法。)

  3. 使用HexToBinary来自Java哈希的二进制BASE64Encoder

  4. 最后,使用String中的SHA1方法(Left代码的复制品),然后将org.apache.commons.lang.StringUtils输出为VBS {{1} }。

  5. 这就是我迄今为止在Java中尝试过至少生成encryptedStr哈希(假设与base64中的String相同:

    SHA1

    以上代码将输出以下内容:

    hash.Value

    问题:

    • 我在两种情况下使用相同的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; } } SHA1 from String is: 825CA9AF2795F3CCD41EC3B756CC7514E490842F SHA1 from InputStream is: 825CA9AF2795F3CCD41EC3B756CC7514E490842F )。

    • 当我执行String代码时,我从VBS获取此Java哈希值:

      636D0172D7FAC85AF9DB57FAE6C7D98B17DE5159

    • 当我执行VBS代码时,我得到这个SHA1哈希值:

      825CA9AF2795F3CCD41EC3B756CC7514E490842F

    • 如果CAPICOM哈希值不相同,我将永远不会像Java SHA1那样得到base64 String


    我的问题:

    我做错了什么以及为什么encryptedStr哈希在两种情况下的计算都不同。有人可以解释一下发生了什么或者实现这个的正确方法是什么,并在SHA1得到相同的结果?

    只是要知道,我发现这个链接有点帮助,并说他们可以得到相同的SHA1,但不能解决我的问题:

    http://us.generation-nt.com/answer/capicom-hasheddata-java-binary-files-help-44910362.html?page=2

    如果有人想安装Java并测试hash代码,您可以执行以下操作:

      
        
    1. 将“capicom.dll”复制到“C:\ WINDOWS \ system32”
    2.   
    3. 单击开始/程序/附件/命令提示符
    4.   
    5. 输入“C:”
    6.   
    7. 输入“cd C:\ WINDOWS \ system32”
    8.   
    9. 输入“regsvr32.exe capicom.dll”
    10.   
    11. 点击“确定”按钮。
    12.   
    13. 输入“exit”
    14.   

    直接从CAPICOM下载VBS

    http://www.microsoft.com/downloads/details.aspx?FamilyID=860EE43A-A843-462F-ABB5-FF88EA5896F6&displaylang=en

1 个答案:

答案 0 :(得分:0)

解决:

表达String的正确方法是使用这种方式:

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";

而不是\n,我们需要使用\r\n,然后SHA1哈希将是相同的。

感谢Ansgar Wiechers揭露这一点。