2012-11-28 12 views
1

繼OpenSSL的消化在C不同的是,這是我啓用日誌記錄SOAP呼叫和提取其摘要中被計算SHA-256形式的字符串的DigitalSigning處理程序相比的java

final String NAMESPACEURI_WSSECURITY_WSU= 
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; 
final String NAMESPACEURI_WSSECURITY_WSSE = 
     "http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-secext- 
     1.0.xsd"; 
final String NAMESPACEURI_XMLSIGNATURE_DS = "http://www.w3.org/2000/09/xmldsig#"; 
final String ATTRIBUTENAME_X509TOKEN = 
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile 
    -1.0#X509v3"; 
final String ENCODINGTYPE_BASE64 = 
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message- 
    security-1.0#Base64Binary"; 

SOAPHeaderElement securityElement = header 
    .addHeaderElement(new QName(
      NAMESPACEURI_WSSECURITY_WSSE, "Security", 
          "wsse")); 
//securityElement.setMustUnderstand(true); 
securityElement.addNamespaceDeclaration("wsu", 
        NAMESPACEURI_WSSECURITY_WSU); 
securityElement.addNamespaceDeclaration("ds", 
        NAMESPACEURI_XMLSIGNATURE_DS); 
SOAPBody body = envelope.getBody(); 
String bodyIdRef = "Id-1-BD-1"; 
body.addAttribute(new QName(NAMESPACEURI_WSSECURITY_WSU, "Id", 
        "wsu"), bodyIdRef); 
// Prepare security token element 
SOAPElement binarySecurityTokenElement = securityElement 
.addChildElement("BinarySecurityToken", "wsse"); 

String tokenIdRef = "Id-1-TK-1"; 
binarySecurityTokenElement.addAttribute(new QName(
      NAMESPACEURI_WSSECURITY_WSU, "Id", "wsu"), tokenIdRef); 
binarySecurityTokenElement.addAttribute(new QName("ValueType"), 
        ATTRIBUTENAME_X509TOKEN); 
binarySecurityTokenElement.addAttribute(new QName(
    "EncodingType"), ENCODINGTYPE_BASE64); 
// Open keystore and insert encoded certificate 
KeyStore store = KeyStore.getInstance("PKCS12"); //default is "JKS" 
store.load(new FileInputStream(new File(KEYSTORE_LOC)), 
     KEYSTORE_STOREPASS.toCharArray()); 
KEYSTORE_KEYALIAS = (String)store.aliases().nextElement(); 
Certificate certificate = store 
     .getCertificate(KEYSTORE_KEYALIAS); 
binarySecurityTokenElement.addTextNode(new String(Base64Coder 
     .encode(certificate.getEncoded()))); 


// Prepare digest for Signature generation 
XMLSignatureFactory signFactory = XMLSignatureFactory 
    .getInstance("DOM"); 
C14NMethodParameterSpec spec1 = null; 
CanonicalizationMethod c14nMethod = signFactory 
    .newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE, spec1); 
DigestMethod digestMethod = signFactory.newDigestMethod(
      DigestMethod.SHA256, null); 
String methodNS = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; 
SignatureMethod signMethod = signFactory.newSignatureMethod(
        methodNS, null); 
TransformParameterSpec spec2 = null; 
Transform transform = signFactory.newTransform(
     CanonicalizationMethod.EXCLUSIVE, spec2); 
List<Transform> transformList = Collections 
     .singletonList(transform); 
List<Reference> referenceList = new ArrayList<Reference>(); 
Reference reference1 = signFactory.newReference(
    "#" + bodyIdRef, digestMethod, transformList, null, 
        null); 
referenceList.add(reference1); 
SignedInfo signInfo = signFactory.newSignedInfo(c14nMethod, 
       signMethod, referenceList); 
// Get Private key 
Key privateKey = store.getKey(KEYSTORE_KEYALIAS, 
       KEYSTORE_KEYPASSWORD.toCharArray()); 
// Create <SignatureValue> 
DOMSignContext dsc = new DOMSignContext(privateKey, 
        securityElement); 
dsc.setDefaultNamespacePrefix("ds"); 
XMLSignature signature = signFactory.newXMLSignature(signInfo, 
        null); 
signature.sign(dsc); 
// Prepare key info element 
SOAPElement signatureElement = (SOAPElement) securityElement 
        .getLastChild(); 
SOAPElement keyInfoElement = signatureElement 
        .addChildElement(new QName(
NAMESPACEURI_XMLSIGNATURE_DS, "KeyInfo", "ds")); 
      SOAPElement 

securityTokenReferenceElement = keyInfoElement.addChildElement(
        "SecurityTokenReference", "wsse"); 
SOAPElement referenceElement = securityTokenReferenceElement 
       .addChildElement("Reference", "wsse"); 
referenceElement.setAttribute("URI", "#" + tokenIdRef); 
referenceElement.setAttribute("ValueType", 
       ATTRIBUTENAME_X509TOKEN); 

部分的代碼。我使用相同的字符串來計算c中的摘要。以下是C++中用於計算的代碼。這兩個值都不同。

#include <openssl/sha.h> 
    #include <openssl/evp.h> 
    #include <string> 
    #define std::string String 

    String conString = "String from logs "; 
    unsigned char md[SHA256_DIGEST_LENGTH]; 
    unsigned int size = 0; 
    EVP_Digest(conString.c_str(), conString.size(), md, &size, EVP_sha256(), 
     NULL); 

在這方面的任何幫助將有所幫助。謝謝

+0

看起來像Java是生成簽名X509,這將是與RSA加密的哈希值。另外一個似乎是base64編碼,而另一個沒有。 – lynks

+0

Java代碼不只是計算SHA256--它是[XML數字簽名](http://www.xml.com/pub/a/2001/08/08/xmldsig.html)。這與OpenSSL片段非常不同,後者試圖生成一個簡單的SHA256摘要。 – willglynn

+0

我知道它首先對它進行規範化,然後計算sha256,因爲我從正在傳遞給摘要函數的日誌中提取字符串,所以摘要應該是相同的。 –

回答

0

非常奇怪,但下面的代碼來計算SHA256生成匹配的Java輸出正確的散列。

String sha256(const String& string) 
{ 

    unsigned char hash[SHA256_DIGEST_LENGTH]; 
    SHA256_CTX sha256; 
    SHA256_Init(&sha256); 
    SHA256_Update(&sha256, string.c_str(), string.size()); 
    SHA256_Final(hash, &sha256); 
    const char* digest = mcommons::util::base64(&hash[0], SHA256_DIGEST_LENGTH); 
    String conString = digest; 
    free((char*) digest); 
    return conString; 
} 

:)