Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
“的结果”;“Java实用程序”;与“不匹配”;C“效用”;签名数据时_Java_C#_Digital Signature - Fatal编程技术网

“的结果”;“Java实用程序”;与“不匹配”;C“效用”;签名数据时

“的结果”;“Java实用程序”;与“不匹配”;C“效用”;签名数据时,java,c#,digital-signature,Java,C#,Digital Signature,嗯,我陷入了使用Java实用程序对数据进行签名的过程中 我需要创建一个Java程序,该程序将根据作为输入数据提供的base64编码字符串对数据进行签名 在这里,我可以使用提供的特定证书生成签名数据,但问题是:签名数据时,“Java实用程序”的结果与“C#实用程序”不匹配 这是我的C#程序: //Get certificate based on given thumbprint X509Certificate2 certificate = GetCertificate(certThumbPrint

嗯,我陷入了使用Java实用程序对数据进行签名的过程中

我需要创建一个Java程序,该程序将根据作为输入数据提供的base64编码字符串对数据进行签名

在这里,我可以使用提供的特定证书生成签名数据,但问题是:签名数据时,“Java实用程序”的结果与“C#实用程序”不匹配

这是我的C#程序:

//Get certificate based on given thumbprint
X509Certificate2 certificate = GetCertificate(certThumbPrint);
ContentInfo contentInfo = new ContentInfo(Convert.FromBase64String(data));
SignedCms signedCms = new SignedCms(contentInfo, false);
CmsSigner cmsSigner = new CmsSigner(certificate);
signedCms.ComputeSignature(cmsSigner, false);

return Convert.ToBase64String(signedCms.Encode());
package com.test;

import java.math.BigInteger;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.util.DerOutputStream
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;

public class TestSignData {

    public static void main(String[] args) throws Exception {

        //First load the keystore object by providing the p12 file path
        KeyStore clientStore = KeyStore.getInstance("Windows-MY");
        //replace testPass with the p12 password/pin
        clientStore.load(null, null);

        Enumeration<String> aliases = clientStore.aliases();
        String aliaz = "";
        System.out.println(aliases.hasMoreElements());
        while(aliases.hasMoreElements()){
            aliaz = aliases.nextElement();
            System.out.println("aliaz::"+aliaz);
            if(clientStore.isKeyEntry(aliaz)){
                break;
            }
        }
        X509Certificate c = (X509Certificate)clientStore.getCertificate(aliaz);

        //Data to sign
        byte[] dataToSign = "QXNob2s=".getBytes();
        int nread = dataToSign.length;

        //compute signature:
        Signature signature = Signature.getInstance("Sha1WithRSA");
        signature.initSign((PrivateKey)clientStore.getKey(aliaz, null));
        signature.update(dataToSign, 0, nread);
        byte[] signedData = signature.sign();

        //load X500Name
        X500Name xName =  new X500Name(c.getSubjectX500Principal().getName());
        System.out.println("xName:::"+xName);

        //load serial number
        BigInteger serial   = c.getSerialNumber();
        //laod digest algorithm
        AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.SHA_oid);
        //load signing algorithm
        AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSAEncryption_oid);

        //Create SignerInfo:
        SignerInfo sInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, signedData);
        //Create ContentInfo:
        ContentInfo cInfo = new ContentInfo(ContentInfo.DIGESTED_DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
        //Create PKCS7 Signed data
        PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo,
                new java.security.cert.X509Certificate[] { c },
                new SignerInfo[] { sInfo });
        //Write PKCS7 to bYteArray
        DerOutputStream dOut = new DerOutputStream();
        p7.encodeSignedData(dOut);
        byte[] encodedPKCS7 = dOut.toByteArray();

        String base64SignatureData = org.apache.commons.codec.binary.Base64.encodeBase64String(encodedPKCS7);
        System.out.println(base64SignatureData);

    }
}
其中,
data
将是base64编码字符串,
certThumbPrint
将是特定证书的唯一值

这是我的Java程序:

//Get certificate based on given thumbprint
X509Certificate2 certificate = GetCertificate(certThumbPrint);
ContentInfo contentInfo = new ContentInfo(Convert.FromBase64String(data));
SignedCms signedCms = new SignedCms(contentInfo, false);
CmsSigner cmsSigner = new CmsSigner(certificate);
signedCms.ComputeSignature(cmsSigner, false);

return Convert.ToBase64String(signedCms.Encode());
package com.test;

import java.math.BigInteger;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.util.DerOutputStream
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;

public class TestSignData {

    public static void main(String[] args) throws Exception {

        //First load the keystore object by providing the p12 file path
        KeyStore clientStore = KeyStore.getInstance("Windows-MY");
        //replace testPass with the p12 password/pin
        clientStore.load(null, null);

        Enumeration<String> aliases = clientStore.aliases();
        String aliaz = "";
        System.out.println(aliases.hasMoreElements());
        while(aliases.hasMoreElements()){
            aliaz = aliases.nextElement();
            System.out.println("aliaz::"+aliaz);
            if(clientStore.isKeyEntry(aliaz)){
                break;
            }
        }
        X509Certificate c = (X509Certificate)clientStore.getCertificate(aliaz);

        //Data to sign
        byte[] dataToSign = "QXNob2s=".getBytes();
        int nread = dataToSign.length;

        //compute signature:
        Signature signature = Signature.getInstance("Sha1WithRSA");
        signature.initSign((PrivateKey)clientStore.getKey(aliaz, null));
        signature.update(dataToSign, 0, nread);
        byte[] signedData = signature.sign();

        //load X500Name
        X500Name xName =  new X500Name(c.getSubjectX500Principal().getName());
        System.out.println("xName:::"+xName);

        //load serial number
        BigInteger serial   = c.getSerialNumber();
        //laod digest algorithm
        AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.SHA_oid);
        //load signing algorithm
        AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSAEncryption_oid);

        //Create SignerInfo:
        SignerInfo sInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, signedData);
        //Create ContentInfo:
        ContentInfo cInfo = new ContentInfo(ContentInfo.DIGESTED_DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
        //Create PKCS7 Signed data
        PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo,
                new java.security.cert.X509Certificate[] { c },
                new SignerInfo[] { sInfo });
        //Write PKCS7 to bYteArray
        DerOutputStream dOut = new DerOutputStream();
        p7.encodeSignedData(dOut);
        byte[] encodedPKCS7 = dOut.toByteArray();

        String base64SignatureData = org.apache.commons.codec.binary.Base64.encodeBase64String(encodedPKCS7);
        System.out.println(base64SignatureData);

    }
}
package.com.test;
导入java.math.biginger;
导入java.security.KeyStore;
导入java.security.PrivateKey;
导入java.security.Signature;
导入java.security.cert.x509证书;
导入java.util.Enumeration;
导入sun.security.pkcs.ContentInfo;
导入sun.security.pkcs.PKCS7;
导入sun.security.pkcs.SignerInfo;
导入sun.security.util.DerOutputStream
导入sun.security.util.DerValue;
导入sun.security.x509.AlgorithmId;
导入sun.security.x509.X500Name;
公共类TestSignData{
公共静态void main(字符串[]args)引发异常{
//首先通过提供p12文件路径加载密钥库对象
KeyStore clientStore=KeyStore.getInstance(“Windows MY”);
//用p12密码/pin替换testPass
load(null,null);
枚举别名=clientStore.aliases();
字符串aliaz=“”;
System.out.println(别名.hasMoreElements());
while(别名.hasMoreElements()){
aliaz=别名.nextElement();
System.out.println(“aliaz::”+aliaz);
if(clientStore.isKeyEntry(aliaz)){
打破
}
}
X509Certificate c=(X509Certificate)clientStore.getCertificate(aliaz);
//要签名的数据
byte[]dataToSign=“QXNob2s=“.getBytes();
int nread=数据到符号长度;
//计算签名:
Signature-Signature=Signature.getInstance(“Sha1WithRSA”);
signature.initSign((PrivateKey)clientStore.getKey(aliaz,null));
签名。更新(dataToSign,0,nread);
字节[]signedData=signature.sign();
//加载X500Name
X500Name xName=新的X500Name(c.getSubjectX500Principal().getName());
System.out.println(“xName::”+xName);
//装载序列号
BigInteger serial=c.getSerialNumber();
//laod摘要算法
AlgorithmId digestAlgorithmId=新的AlgorithmId(AlgorithmId.SHA_oid);
//负载签名算法
AlgorithmId signAlgorithmId=新的AlgorithmId(AlgorithmId.rsaid);
//创建签名信息:
SignerInfo sInfo=新的SignerInfo(xName、serial、digestAlgorithmId、signAlgorithmId、signedData);
//创建内容信息:
ContentInfo cInfo=newcontentinfo(ContentInfo.DIGESTED_DATA_OID,new DerValue(DerValue.tag_OctetString,dataToSign));
//创建PKCS7签名数据
PKCS7 p7=新的PKCS7(新算法ID[]{digestAlgorithmId},cInfo,
新的java.security.cert.X509Certificate[]{c},
新签署人[]{sInfo});
//将PKCS7写入bYteArray
DerOutputStream dOut=新的DerOutputStream();
p7.编码签名数据(dOut);
字节[]encodedPKCS7=dOut.toByteArray();
String base64SignatureData=org.apache.commons.codec.binary.Base64.encodeBase64String(encodedPKCS7);
System.out.println(base64SignatureData);
}
}
有谁能指导我得到基于“C#”的实用程序返回的确切结果吗

注意:在本地检查此程序时,您可以将任何证书作为输入,但两个程序的结果应该相同,这是我的主要要求

如果有人能就此给我快速回复,我将不胜感激


谢谢大家!

首先,正如Artjom所评论的那样,数字签名并不总是确定的,同一数据中具有相同密钥的两个(或多个)签名很可能不同,并且都(或全部)有效。您不会通过将签名与新生成的、甚至是预先存在的签名进行比较来验证签名

你正在做一些肯定或可能错误的事情,需要纠正,以及其他可能不同但不一定错误的事情

明确:您的dotNET代码使用的是从base64解码后的数据,您的Java代码使用的是编码值(用于散列和发送)

半确定:在创建SignerInfo时使用证书主题和序列号,它应该是issuer和序列号。如果您的证书是自签名的,则颁发者和主题是相同的,这并不重要

明确:您正在使用(的OID)摘要数据作为数据的contentType,它应该是数据。(摘要数据是包含数据和摘要的摘要数据结构消息的类型,即)

很有可能:MSDN并没有说我可以找到(而且我也无法轻松测试)hash dotNET用于RSA签名的内容,但SHA1不再被认为是最佳实践,所以它可能会使用更好的方法。如果是这样的话,这是一个差异,即使实践不佳,也不一定是错误的

可能:类似地,我不知道dotNET是否使用SignedAttributes,但我认为这是可能的,因为这是一种良好的做法。你的Java代码绝对不会。如果是这样的话,这是一个区别,但并不是真的错

很可能:类似地,我不知道dotNET是否自动包含/添加链证书,这是明确推荐的良好做法。您的Java代码没有。如果您的证书是自签名的,则没有链证书,这无关紧要

PS:Java8正式拥有
java.util.Base64
并返回到6(在l