2011-01-26 64 views
3

我已經爲Java web服務調用編寫了Java類的util類。我的util類創建Web服務調用所需的密碼摘要。此摘要密碼由以下內容組成:使用以下算法生成的摘要密碼:base64Encode(sha1Hash(<Nonce><TimeStamp><Secret>))在java util類中使用BASE64的SHA1不會生成正確的密碼

我生成的密碼不等於供應商使用相同算法的工具生成的密碼(我沒有訪問其密碼代碼,所以我不知道如何實現)。我不確定如果我做錯了什麼,有人可以查看我的代碼,看看我是否做了SHA1加密或Base64編碼的錯誤。謝謝你的幫助!下面是我的代碼:

import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.GregorianCalendar; 
import java.util.TimeZone; 
import java.util.UUID; 

import javax.xml.bind.DatatypeConverter; 
import org.apache.commons.codec.binary.Base64; 

public class OminitureWSUtil { 

private static MessageDigest SHA1; 

static { 
    try { 
     SHA1 = MessageDigest.getInstance("SHA1"); 

    } catch(NoSuchAlgorithmException nae) { 
     throw new RuntimeException(nae); 
    } 
} 

static class OmniturePasswordDigest { 
    private final String timestamp; 
    private final String nonce; 
    private final String secret; 

    private String password; 

    public OmniturePasswordDigest(String secret) { 
     Calendar c = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT+0")); 
     c.setTime(new Date()); 

     //timestamp = DatatypeConverter.printDateTime(c); 
     //nonce = UUID.randomUUID().toString().replace("-", ""); 

     timestamp = "2011-01-26T20:10:56Z"; 
     nonce = "MTkyMTYwZWMzMjIzZGJmYzNiYmE5M2E5"; 

     this.secret = secret; 
    } 

    public String getTimestamp() { 
     return timestamp; 
    } 

    public String getNonce() { 
     return nonce; 
    } 

    public String generatePassword() { 
     if(password == null) { 
      String beforeEncryption = nonce+timestamp+secret; 
      System.out.println("before encryption, encoding: " + beforeEncryption); 

      try { 
       SHA1.reset(); 
       byte[] toEncrypt = beforeEncryption.getBytes("UTF-8"); 
       //SHA1.update(toEncrypt, 0, toEncrypt.length); 
       SHA1.update(beforeEncryption.getBytes()); 
      } catch (UnsupportedEncodingException uee) { 
       throw new RuntimeException(uee); 
      } 

      byte[] encryptedRaw = SHA1.digest(); 
      byte[] encoded = Base64.encodeBase64(encryptedRaw); 

      try { 
       password = new String(encoded, "UTF-8"); 
      } catch (UnsupportedEncodingException uee) { 
       throw new RuntimeException(uee); 
      } 
     } 

     return password; 
    } 
} 


public static OmniturePasswordDigest generatePasswordDigest(String secret) { 
    return new OmniturePasswordDigest(secret); 
} 

public static void main(String[] args) { 
    OmniturePasswordDigest opd = generatePasswordDigest("1779ab07fb93a01e3d4a6ee174124b91"); 
    System.out.println("nonce: " + opd.getNonce()); 
    System.out.println("timestamp: " + opd.getTimestamp()); 
    System.out.println("password: " + opd.generatePassword()); 

    if("Lr+m+/6y3XUxvjd8Rtn75gqn/b4=".equals(opd.generatePassword())) { 
     System.out.println("all good"); 
    } else { 
     System.out.println("generated password is not the same, it should be: " + 
       "Lr+m+/6y3XUxvjd8Rtn75gqn/b4="); 
    } 

} 

}

回答

2

SHA1從數英里外可見。 更改代碼這樣的:

-SHA1.reset(); 
+MessageDigest SHA1= (MessageDigest) OminitureWSUtil.SHA1.clone(); 

復位僅僅是不是你所需要的東西;克隆是針對這種情況。

btw,在類中拋出任何異常init(static {})殺死類和部分引用該類的任何其他類(以至於整個[web]應用程序)。這是一個不好的做法,因爲異常(java.lang.ExceptionInInitializerError)可能會陷入某處。

+0

感謝您的指針。我已將其重寫,以便爲每個getPassword方法調用創建一個MessageDigest的新實例。克隆()會更快,然後通過MessageDigest.getInstance()每次實例化MessageDigest? – Marcin 2011-01-27 00:34:30

0

我猜這是對REST API對Omniture?那裏有一個工作示例。但是,您的代碼乍一看看起來很正確。

https://developer.omniture.com/java_rest_api

此外,我不知道你將如何使用這個類,但SHA1不是線程安全的,如果多一點調用generatePassword(),你會得到一些意外的行爲。

+0

謝謝!我能夠真正弄清楚這一點。它似乎是在xml消息中對Nonce進行編碼,這就是拋棄我的原因,因爲我從來沒有在消息中編碼我的隨機數。 – Marcin 2011-01-26 23:56:02