2012-11-28 10 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; 
} 

:)