簡體   English   中英

Bouncycastle 簽名數據消息中的附加八位字節字符串

[英]Additional Octet String in Bouncycastle signed data message

我正在創建一個 CSCA 主列表簽名數據,但在成功創建它之后,我在簽名消息中看到兩個八位字節字符串而不是一個。 請檢查源代碼和 output 文件

使用 BC 的 CMS

// load master list signer key  
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(FileTools.readFiletoBuffer("CSCAFiles/MLS.key"));
        ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()));
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
        String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();

        PrivateKey MLSkey = KeyFactory.getInstance(algOid).generatePrivate(spec);

              // load master list signing cert
        X509Certificate MLSCert = CertTools.getCertfromByteArray(FileTools.readFiletoBuffer("CSCAFiles/MLSCert.der"),
                X509Certificate.class);

        // create master list
        X509CertificateHolder x509CertificateHolder = new X509CertificateHolder(MLSCert.getEncoded());

        String pubkeyAlgorithm = MLSCert.getPublicKey().getAlgorithm();
        String certAlgorithm = "";

        if (pubkeyAlgorithm.equals("RSA")) {
            certAlgorithm = "SHA256WITHRSA";
        } else if (pubkeyAlgorithm.equals("ECDSA")) {
            certAlgorithm = "SHA256WITHECDSA";
        } else if (pubkeyAlgorithm.equals("DSA")) {
            certAlgorithm = "SHA256WITHDSA";
        } else {
            certAlgorithm = "SHA256WITHRSA";
        }

        // csca cert
        X509Certificate cscaCert = CertTools.getCertfromByteArray(FileTools.readFiletoBuffer("CSCAFiles/CSCACert.der"),
                X509Certificate.class);

        // create master list content
        JcaX509CertificateHolder[] hollist = CertTools
                .convertToX509CertificateHolder(new X509Certificate[] { cscaCert });

        org.bouncycastle.asn1.x509.Certificate certList[] = new org.bouncycastle.asn1.x509.Certificate[1];
        certList[0] = hollist[0].toASN1Structure();
        //certList[1] = hollist[0].toASN1Structure();

        CscaMasterList ml = new CscaMasterList(certList);

        System.out.println(">>>>> encoded data : " + new java.math.BigInteger(1, ml.getEncoded()).toString(16));

        CMSTypedData message = new CMSProcessableByteArray(ICAOObjectIdentifiers.id_icao_cscaMasterList,
                ml.toASN1Primitive().getEncoded());   

        AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(certAlgorithm);

        AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
        AsymmetricKeyParameter privateKeyParameter = PrivateKeyFactory.createKey(MLSkey.getEncoded());

        BcContentSignerBuilder signBuilder = null;
        if (pubkeyAlgorithm.equals("RSA")) {
            signBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
        } else if (pubkeyAlgorithm.equals("EC")) {
            signBuilder = new BcECContentSignerBuilder(sigAlgId, digAlgId);
        } else if (pubkeyAlgorithm.equals("DSA")) {
            signBuilder = new BcDSAContentSignerBuilder(sigAlgId, digAlgId);
        } else {
            signBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
        }

        ContentSigner signer = signBuilder.build(privateKeyParameter);

        SignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new SignerInfoGeneratorBuilder(
                new BcDigestCalculatorProvider());
        SignerInfoGenerator infoGenerator = signerInfoGeneratorBuilder.build(signer, x509CertificateHolder);

        CMSSignedDataGenerator dataGenerator = new CMSSignedDataGenerator();
        dataGenerator.addSignerInfoGenerator(infoGenerator);

        dataGenerator.addCertificate(x509CertificateHolder);
        dataGenerator.addCertificate(new X509CertificateHolder(FileTools.readFiletoBuffer("CSCAFiles/CSCACert.der")));

        CMSSignedData signedData = dataGenerator.generate(message, true);

        System.out.println(">>>>> ML data : " + new java.math.BigInteger(1, signedData.getEncoded()).toString(16));     

>>>>> 編碼數據:

308202b2020100318202ab308202a730820210a003020102021024c2de802df5eb9a5ffc421546f39635300d06092a864886f70d01010b0500303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b52301e170d3139313033313032343830305a170d3334313032373032353830305a303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b5230819f300d06092a864886f70d010101050003818d0030818902818100b23a5a61e46f522c5d0e43325b9485065cabb6db0d88e32bb6ceb0d32ebb740485458e1e4e1cdfe317829e3d785f2de66d0f270120919f46d759a64e944c3579661cf850714af2fd2088f5dc91b1838571802f7d4d7b61219da296a8ae7f55362aa28836cea220635660b0b8c8f3cd596234bbe5ccb04873aa3e301c05f86eb70203010001a381a33081a0300f0603551d130101ff040530030101ff300e0603551d0f0101ff040403020106302b0603551d1004243022800f32303139313033313032353830305a810f32303234313033313032353830305a301d0603551d0e0416041456d7d0f4db824006e0dc864129ddd6991b36c467301f0603551d2304183016801456d7d0f4db824006e0dc864129ddd6991b36c46730100603551d200409300730050603290101300d06092a864886f70d01010b05000381810027ebd5fe0fd6e8df20e485d07f5b3420cb9719d2bad3dec7db5611cb690087d26f398b4849dd7d99a2abf3a2a71f7b108941a12df1a8a9c42a9c48a0750fded7a5ba38f692780cb6663febfb28d879bb53155113d773b8349e0c658c4ddc5c3d1ec7f8d35d4e72223efaacfdc53698e9157ac4590c708f91346c286d1b7e4fe4

>>>>> 機器學習數據:

308006092a864886f70d010702a0803080020103310f300d0609608648016503040201050030800606678108010102a0802480048202b6308202b2020100318202ab308202a730820210a003020102021024c2de802df5eb9a5ffc421546f39635300d06092a864886f70d01010b0500303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b52301e170d3139313033313032343830305a170d3334313032373032353830305a303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b5230819f300d06092a864886f70d010101050003818d0030818902818100b23a5a61e46f522c5d0e43325b9485065cabb6db0d88e32bb6ceb0d32ebb740485458e1e4e1cdfe317829e3d785f2de66d0f270120919f46d759a64e944c3579661cf850714af2fd2088f5dc91b1838571802f7d4d7b61219da296a8ae7f55362aa28836cea220635660b0b8c8f3cd596234bbe5ccb04873aa3e301c05f86eb70203010001a381a33081a0300f0603551d130101ff040530030101ff300e0603551d0f0101ff040403020106302b0603551d1004243022800f32303139313033313032353830305a810f32303234313033313032353830305a301d0603551d0e0416041456d7d0f4db824006e0dc864129ddd6991b36c467301f0603551d2304183016801456d7d0f4db824006e0dc864129ddd6991b36c46730100603551d200409300730050603290101300d06092a864886f70d01010b05000381810027ebd5fe0fd6e8df20e485d07f5b3420cb9719d2bad3dec7db5611cb690087d26f398b4849dd7d99a2abf3a2a71f7b108941a12df1a8a9c42a9c48a0750fded7a5ba38f692780cb6663febfb28d879bb53155113d773b8349e0c658c4ddc5c3d1ec7f8d35d4e72223efaacfdc53698e9157ac4590c708f91346c286d1b7e4fe4000000000000a0803082044c308203b5a00302010202142710e65ec4b56813da4e0e1e0223b7d485aa64d9300d06092a864886f70d01010b0500303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b52301e170d3139313033313032343830325a170d3239313032383032343830325a304f3121301f06035504030c184d61737465724c6973745369676e65724365727454657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b5230820122300d06092a864886f70d01010105000382010f003082010a0282010100cb4ef691bb600dd6f514569ed79853d56f053257ddcaf11cd7323824499d011d5cc7652e50789977922c76d8c0d937426ce81e74b5b4f52a419481aab713114916859c23a53ac3937ac22a73c1f31b281f74c5c31574ab2f5f270d31667ee3fe9f69d231957dd33a4c97a20c19c0cabcfddc467786c6be42c6fef962c00f44d17e5d50c39443a14d9f44baf89974e5b5620381e4c2096008e7994f4eb1ee70689fce105a22dc1316d4fea5753673c68cc1fc9b6636b088408672bc57ccbc3f2cd74855939c1ab6bf7cb9b7a56f9ace27c92abf431381659ce9d99326f8fd485a24306b7514b5c5903bf417f8a460aec2893f7913c184638641804891836844cb0203010001a38201af308201ab301f0603551d2304183016801456d7d0f4db824006e0dc864129ddd6991b36c46730818e06082b06010505070101048181307f302006082b060105050730028614687474703a2f2f6578616d706c652e636f6d2f30302006082b060105050730028614687474703a2f2f6578616d706c652e636f6d2f31303906082b06010505073001862d687474703a2f2f63612d646566696e65642e6f6373702e736572766963652e6c6f6361746f722e75726c2e7377302c0603551d110425302381214d61737465724c6973745369676e657243657274546573744064656d6f2e636f6d30140603551d250101ff040a3008060667810801010330570603551d1f0450304e3025a023a021861f687474703a2f2f7777772e64656d6f2e6f72672f6261722f6261722e63726c3025a023a021861f687474703a2f2f7777772e64656d6f2e6f72672f666f6f2f666f6f2e63726c301d0603551d0e041604148d2713fb3995e04b0dda8a02a1a3d9141ba01914302b0603551d1004243022800f32303139313033313032343830325a810f32303230303133313032343830325a300e0603551d0f0101ff040403020780300d06092a864886f70d01010b050003818100004f1211d31b962c3f7060ca29af5895593aaaecd4a0ec4657fc7e4e54d8f427771c0ff58db6ee5d11fe74074f0838cfbc541fd4a793d10baa4bd0b8b5a4aae8eb6eb330dafcae2f88f9f94981ccc8983565724365ea8dc793bf80b131ffa2f29e9aa4943597fcce72b0ddf2228c942ec4be3a3490935846cdef8664bf0bc5c1308202a730820210a003020102021024c2de802df5eb9a5ffc421546f39635300d06092a864886f70d01010b0500303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b52301e170d3139313033313032343830305a170d3334313032373032353830305a303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b5230819f300d06092a864886f70d010101050003818d0030818902818100b23a5a61e46f522c5d0e43325b9485065cabb6db0d88e32bb6ceb0d32ebb740485458e1e4e1cdfe317829e3d785f2de66d0f270120919f46d759a64e944c3579661cf850714af2fd2088f5dc91b1838571802f7d4d7b61219da296a8ae7f55362aa28836cea220635660b0b8c8f3cd596234bbe5ccb04873aa3e301c05f86eb70203010001a381a33081a0300f0603551d130101ff040530030101ff300e0603551d0f0101ff040403020106302b0603551d1004243022800f32303139313033313032353830305a810f32303234313033313032353830305a301d0603551d0e0416041456d7d0f4db824006e0dc864129ddd6991b36c467301f0603551d2304183016801456d7d0f4db824006e0dc864129ddd6991b36c46730100603551d200409300730050603290101300d06092a864886f70d01010b05000381810027ebd5fe0fd6e8df20e485d07f5b3420cb9719d2bad3dec7db5611cb690087d26f398b4849dd7d99a2abf3a2a71f7b108941a12df1a8a9c42a9c48a0750fded7a5ba38f692780cb6663febfb28d879bb53155113d773b8349e0c658c4ddc5c3d1ec7f8d35d4e72223efaacfdc53698e9157ac4590c708f91346c286d1b7e4fe400003182021a308202160201013057303f3111300f06035504030c084353434154657374310d300b060355040b0c0464656d6f310e300c060355040a0c05647265616d310b3009060355040613024b5202142710e65ec4b56813da4e0e1e0223b7d485aa64d9300d06096086480165030402010500a08195301506092a864886f70d01090331080606678108010102301c06092a864886f70d010905310f170d3139313130313030323033365a302d06092a864886f70d0109343120301e300d06096086480165030402010500a10d06092a864886f70d01010b0500302f06092a864886f70d010904312204202784558fbdeca49e7f905b161924b1b8306df980ed191907f1469ab46b379953300d06092a864886f70d01010b0500048201005d1ffa5ce0cef0304899b192eb873a8d9d656b28ed7fc1a4dfdeea9cc9325a9a228b9a7fb0962358c29d98f6a2b679e40fe5b918f615ecf12624764439c5e5b81665ceaca0c718e6b63bb57b8e8ea0b0579dc0b32923c9add0191b0864ff20b3245175ab7231e10c39d7867d7df1e712b81ba4cc4e0f300ede5c66ec73af6a6a3caf70358844a71c49d7b355d0e584d622c46dbdfc9ecb9a7fdea03a1a3e891f78c57420d2260b317c896312c982885d8f9438eddcef0c9ae19a775f0a7725440a6d4f0ad67daf2c8095e3b6668169e79f2e23b34876c2c8daf622bf0d0ec31cbd9259929dce951050564a7dcf92ad2f30d7945c2500f89653d3cfa2f4f7cc1a000000000000

錯誤的主列表(使用 BC)

毫升錯

預期的主列表(使用 sun.security.pkcs)

毫升正確

----PKCS#7 使用太陽----

    // load master list signer key
        /* Check to see if this is in an EncryptedPrivateKeyInfo structure. */
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(FileTools.readFiletoBuffer("CSCAFiles/MLS.key"));
        /*
         * Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm OID
         * and use that to construct a KeyFactory.
         */
        ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()));
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
        String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();

        PrivateKey MLSkey = KeyFactory.getInstance(algOid).generatePrivate(spec);

        X509Certificate MLSCert = CertTools.getCertfromByteArray(FileTools.readFiletoBuffer("CSCAFiles/MLSCert.der"),
                X509Certificate.class);

        // create the output stream
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        bOut.write(FileTools.readFiletoBuffer("CSCAFiles/CSCACert.der"));
        bOut.write(FileTools.readFiletoBuffer("CSCAFiles/DSCert.der"));
        bOut.write(FileTools.readFiletoBuffer("CSCAFiles/DLSCert.der"));

        bOut.close();

        // create ml
        // set up the generator
        ////////////////////////
        X509CertificateHolder x509CertificateHolder = new X509CertificateHolder(MLSCert.getEncoded());

        String pubkeyAlgorithm = MLSCert.getPublicKey().getAlgorithm();
        String certAlgorithm = "";

        if (pubkeyAlgorithm.equals("RSA")) {
            certAlgorithm = "SHA256WITHRSA";
        } else if (pubkeyAlgorithm.equals("ECDSA")) {
            certAlgorithm = "SHA256WITHECDSA";
        } else if (pubkeyAlgorithm.equals("DSA")) {
            certAlgorithm = "SHA256WITHDSA";
        } else {
            certAlgorithm = "SHA256WITHRSA";
        }

        // csca cert
        X509Certificate cscaCert = CertTools.getCertfromByteArray(FileTools.readFiletoBuffer("CSCAFiles/CSCACert.der"),
                X509Certificate.class);

        // create master list content
        JcaX509CertificateHolder[] hollist = CertTools
                .convertToX509CertificateHolder(new X509Certificate[] { cscaCert });

        org.bouncycastle.asn1.x509.Certificate certList[] = new org.bouncycastle.asn1.x509.Certificate[2];
        certList[0] = hollist[0].toASN1Structure();
        certList[1] = hollist[0].toASN1Structure();

        CscaMasterList ml = new CscaMasterList(certList);

        ///////////////////////

        // Data to sign
        byte[] dataToSign = ml.getEncoded();

        // compute signature:
        Signature signature = Signature.getInstance(certAlgorithm);
        signature.initSign(MLSkey);
        signature.update(dataToSign);
        byte[] signedData = signature.sign();

        // load X500Name
        sun.security.x509.X500Name xName = new sun.security.x509.X500Name(cscaCert.getSubjectDN().getName());
        // load serial number
        BigInteger serial = hollist[0].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(new ObjectIdentifier("2.23.136.1.1.2"),
                new DerValue(DerValue.tag_OctetString, dataToSign));
        // Create PKCS7 Signed data
        PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo,
                new java.security.cert.X509Certificate[] { cscaCert }, new SignerInfo[] { sInfo });
        // Write PKCS7 to bYteArray
        ByteArrayOutputStream bOut1 = new DerOutputStream();
        p7.encodeSignedData(bOut1);

        System.out.println(">>>>> ML data : " + new java.math.BigInteger(1, bOut1.toByteArray()).toString(16));         

更正! 雖然創建 PKCS7 和 CMS 的方式有所不同,但根據評論,這里的區別在於 Bouncy 使用了“構造”編碼(無限長度,盡管在這里不太重要),請參閱wikipedia ASN.1 中的“構造”項具有該項的一個標記長度前綴和一個或多個構成構造項的值的元素的附加標記長度前綴。

$ openssl asn1parse <58653210.cms -inform der -i
    0:d=0  hl=2 l=inf  cons: SEQUENCE
    2:d=1  hl=2 l=   9 prim:  OBJECT            :pkcs7-signedData
   13:d=1  hl=2 l=inf  cons:  cont [ 0 ]
   15:d=2  hl=2 l=inf  cons:   SEQUENCE
   17:d=3  hl=2 l=   1 prim:    INTEGER           :03
   20:d=3  hl=2 l=  15 cons:    SET
   22:d=4  hl=2 l=  13 cons:     SEQUENCE
   24:d=5  hl=2 l=   9 prim:      OBJECT            :sha256
   35:d=5  hl=2 l=   0 prim:      NULL
   37:d=3  hl=2 l=inf  cons:    SEQUENCE
   39:d=4  hl=2 l=   6 prim:     OBJECT            :2.23.136.1.1.2
   47:d=4  hl=2 l=inf  cons:     cont [ 0 ]
   49:d=5  hl=2 l=inf  cons:      OCTET STRING
   51:d=6  hl=4 l= 694 prim:       OCTET STRING      [HEX DUMP]:308202B202010031 
[snip rest of (correct) body]
  749:d=6  hl=2 l=   0 prim:       EOC
  751:d=5  hl=2 l=   0 prim:      EOC
  753:d=4  hl=2 l=   0 prim:     EOC
  755:d=3  hl=2 l=inf  cons:    cont [ 0 ]
  757:d=4  hl=4 l=1100 cons:     SEQUENCE 
[snip certificate]
 1861:d=4  hl=4 l= 679 cons:     SEQUENCE 
[snip certificate]
 2544:d=4  hl=2 l=   0 prim:     EOC
 2546:d=3  hl=4 l= 538 cons:    SET
 2550:d=4  hl=4 l= 534 cons:     SEQUENCE 
[snip SignerInfo]
 3088:d=3  hl=2 l=   0 prim:    EOC
 3090:d=2  hl=2 l=   0 prim:   EOC
 3092:d=1  hl=2 l=   0 prim:  EOC

如果我們查看偏移量 49(十六進制)處的實際字節,我們會發現

24 80 -- tag for OCTET STRING _constructed_, length indefinite
-- a constructed item contains (consists of) one or more following elements
04 82 02 B6 -- tag for OCTET STRING _primitive_, length 02B6
-- this is the only element within the constructed item

在 49+6+0x2b6=749 我們發現00 00是“內容結束”,終止構造的項目。 因此,外部構造的 OCTET STRING 實際上由一個元素組成,該元素是原始 OCTET STRING。

猜測一下,Bouncy 對內容和 encapContentInfo 以及包含它們的外部 SignedData 使用構造+無限,以允許它們大於 memory 的大小——在加密中通常稱為“在線”(對它來說是一個奇怪的術語)或者更明智的“流媒體”。 但它也將它用於證書和 signerInfos 組件,它們從來沒有這個問題——也許只是為了方便?

sun 類可能沒有這樣做,盡管您沒有發布數據來確認(或者可以查看使用的代碼)。

這實際上是 BER,原因有兩個; DER 不允許構造OCTET STRING 或不定長度。


(原始但不適用的答案供參考)

這是 PKCS7(RSALabs 原始版本)和 CMS(其 IETF 化的繼任者)之間的一個很小且很容易被忽略的區別。 它實際上是在 1999 年的 RFC 2630 中引入的,但直到 2002 年的RFC 3369 sec 5.2.1才明確記錄。請注意, version (SignedData 開頭的 Integer,即外部 Context-0 顯式序列)也不同; 在 Bouncy 創建的 CMS 版本中,它是 3,而在陽光下(您沒有顯示源代碼,但顯然是 PKCS7)它是 1。PKCS7 只定義了高達 1 的版本,所以任何(結構與)版本> 1 必須是 CMS。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM