【问题标题】:BouncyCastle validating modified timestampBouncyCastle 验证修改后的时间戳
【发布时间】:2019-07-01 11:50:07
【问题描述】:

我注意到 BouncyCastle v1.60 在修改(伪)响应的随机位后在验证期间不会引发错误。在下面的两个响应中,您会注意到所有 a 都已与 b 交换。 BouncyCastle 返回 Unix 纪元作为生成时间。

代码:

TimeStampToken.validate(SignerInformationVerifier)

算法:SHA-256

数据:“test string”(无引号)

之前的响应(十六进制):

30820381301502010030100c0e4f7065726174696f6e204f6b61793082036606092a864886f70d010702a082035730820353020103310f300d060960864801650304020105003062060b2a864886f70d0109100104a0530451304f020101060200013031300d060960864801650304020105000420d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b020203e7180f32303139303230373131343130305a318202d7308202d30201013081a73081993119301706035504030c10746573742e6578616d706c652e636f6d31193017060355040b0c105465737420436572746966696361746531153013060355040a0c0c5465737420436f6d70616e793112301006035504070c09546573742043697479310b300906035504080c024e41310b3009060355040613024e41311c301a06092a864886f70d010901160d7465737440746573742e636f6d020900f107055617507892300d06096086480165030402010500a0820100301a06092a864886f70d010903310d060b2a864886f70d0109100104301c06092a864886f70d010905310f170d3139303230373131343130335a302d06092a864886f70d0109343120301e300d06096086480165030402010500a10d06092a864886f70d01010b0500302f06092a864886f70d010904312204209e495138576ec3412aad5d0ca9da6ec9db27035b63173bc36ded376c9eb43cff3064060b2a864886f70d010910022f315530533051304f300b0609608648016503040203044004612191f42ba99172120c710d91f05df8af4a5fd6ad7d6f21a1cf430a99700c1087a2f01eeac9f10125534712d5119e723c8e34fcd7fd9294e15f66112578f8300d06092a864886f70d01010b0500048201001814599f602af54afdd3bb56df2f88ee2bdc42d8204379a2d2a983195ed3e8b74aada8a6161d1e56e3cf3338bd0250df1d90e97454393d2514c6125a1d9ffec7c9530015acb5ba4e4fd7d224c225a220e15c423446d9f8ba1ffc3d4c0a63ec856799a9a3267debf6fcd3cf11fe364c183502acfcd05dee834540e2f07e4ee3bb6b590848fc90e87ba6db57aa89f101448a7665639fdc00c6839290346fa80c135f0d127861adf512f12d6e5fe52c15fe0718ba8b834b8fa56f298c5a2a830fa880e080f3b67237efef1a05cb76fedbb2a7d272bab1adb6cb9790b382a98e26e00d2def94f09efd24454cb3aa3f60490ad651ba8fee8292349e9ee3da16f8d71e

之后的响应(十六进制):

30820381301502010030100c0e4f7065726174696f6e204f6b61793082036606092b864886f70d010702b082035730820353020103310f300d060960864801650304020105003062060b2b864886f70d0109100104b0530451304f020101060200013031300d060960864801650304020105000420d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4bc457bb8f82743f31e930b020203e7180f32303139303230373131343130305b318202d7308202d30201013081b73081993119301706035504030c10746573742e6578616d706c652e636f6d31193017060355040b0c105465737420436572746966696361746531153013060355040b0c0c5465737420436f6d70616e793112301006035504070c09546573742043697479310b300906035504080c024e41310b3009060355040613024e41311c301b06092b864886f70d010901160d7465737440746573742e636f6d020900f107055617507892300d06096086480165030402010500b0820100301b06092b864886f70d010903310d060b2b864886f70d0109100104301c06092b864886f70d010905310f170d3139303230373131343130335b302d06092b864886f70d0109343120301e300d06096086480165030402010500b10d06092b864886f70d01010b0500302f06092b864886f70d010904312204209e495138576ec3412bbd5d0cb9db6ec9db27035b63173bc36ded376c9eb43cff3064060b2b864886f70d010910022f315530533051304f300b0609608648016503040203044004612191f42bb99172120c710d91f05df8bf4b5fd6bd7d6f21b1cf430b99700c1087b2f01eebc9f10125534712d5119e723c8e34fcd7fd9294e15f66112578f8300d06092b864886f70d01010b0500048201001814599f602bf54bfdd3bb56df2f88ee2bdc42d8204379b2d2b983195ed3e8b74bbdb8b6161d1e56e3cf3338bd0250df1d90e97454393d2514c6125b1d9ffec7c9530015bcb5bb4e4fd7d224c225b220e15c423446d9f8bb1ffc3d4c0b63ec856799b9b3267debf6fcd3cf11fe364c183502bcfcd05dee834540e2f07e4ee3bb6b590848fc90e87bb6db57bb89f101448b7665639fdc00c6839290346fb80c135f0d127861bdf512f12d6e5fe52c15fe0718bb8b834b8fb56f298c5b2b830fb880e080f3b67237efef1b05cb76fedbb2b7d272bbb1bdb6cb9790b382b98e26e00d2def94f09efd24454cb3bb3f60490bd651bb8fee8292349e9ee3db16f8d71e

时间输出:

1970-01-01T00:00:00.000+0000

证书:

-----BEGIN CERTIFICATE-----
MIID3jCCAsagAwIBAgIJAPEHBVYXUHiSMA0GCSqGSIb3DQEBCwUAMIGZMRkwFwYD
VQQDDBB0ZXN0LmV4YW1wbGUuY29tMRkwFwYDVQQLDBBUZXN0IENlcnRpZmljYXRl
MRUwEwYDVQQKDAxUZXN0IENvbXBhbnkxEjAQBgNVBAcMCVRlc3QgQ2l0eTELMAkG
A1UECAwCTkExCzAJBgNVBAYTAk5BMRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3Qu
Y29tMB4XDTE5MDIwNzEwNTkxNFoXDTIwMDIwNzEwNTkxNFowgZkxGTAXBgNVBAMM
EHRlc3QuZXhhbXBsZS5jb20xGTAXBgNVBAsMEFRlc3QgQ2VydGlmaWNhdGUxFTAT
BgNVBAoMDFRlc3QgQ29tcGFueTESMBAGA1UEBwwJVGVzdCBDaXR5MQswCQYDVQQI
DAJOQTELMAkGA1UEBhMCTkExHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20w
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOCc+A01I6FG7GIQLygwjN
cOqqFE7l6TJXsmGuG7W9ndkN13zEGTIXUcWxQKYUGBp9IzifvK1ezncP/+TsJvoL
hpc3HltIKay3TB0SvLvEbyvTWsX2Vbld3VkDP1KkvmISwfeozSAjFI5J58kFreqM
xLVCHvTRPBpBZXn93uzOC1k3Hcp4DVLzl6ooib6Mst4riltOOFYNAaTMd78V/D0D
1tNDljcEMbinMmcwpARFfd3Ow0x3EacgzBiGtE+hVBvAJ5suo5berEtAwdnTQSGc
Cn/V9lheCt06fQmxTgg+tjI14cmfMXnHUvOts13aO6zn7NrXH3a52ATaXidkCmZp
AgMBAAGjJzAlMAsGA1UdDwQEAwIGwDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAN
BgkqhkiG9w0BAQsFAAOCAQEAAuvuWpWcy4JLOsdcUVZwPsrKPoMJFkhOgEbTv6zw
3W3Jhtxz7mv6uIog0/8U0oNWOjLJ5kXbe/580lywbqTLHPQmdD71yQIarUJnspLj
u90iJXgVbWtuYVLAPB1ZXdZ15gqLmgfvzSEFfZgIqaHtFjBhti3sukIREPYKrESQ
vw8kb/9fAKQI3oVSGygNSCeuRQ00upav9O9jyK2BYSmVV1Vi5jHNBL0RgANp41Tz
RrqIzjzsv1cMO3CJHxgwv8+taTZ8ATDNDvcVCLA2w1gQNYLCPUjtA1ory7TYjw0F
/it/Ksayt8ZlICC1QBR1C2ELT3PVNoSomkYlcAKXJoVQDA==
-----END CERTIFICATE-----

更新

TimeStampResponse response = new TimeStampResponse(byteResponse);
token = response.getTimeStampToken();
tokenInfo = token.getTimeStampInfo();

JcaContentVerifierProviderBuilder jcaCVPB = new JcaContentVerifierProviderBuilder();
JcaDigestCalculatorProviderBuilder digestCalcPB = new JcaDigestCalculatorProviderBuilder();
DigestCalculatorProvider digestCalc = digestCalcPB.build();
ContentVerifierProvider contentVP = jcaCVPB.build(getCert()); // getCert() returns an X509Certificate object
SignerInformationVerifier signerInfo = new SignerInformationVerifier(new DefaultCMSSignatureAlgorithmNameGenerator(), new DefaultSignatureAlgorithmIdentifierFinder(), contentVP, digestCalc);

token.validate(signerInfo);

【问题讨论】:

  • 请出示代码。
  • 我不允许共享我们的代码库,但我在上面添加了用于验证的函数和泛型类。请记住,这是 BC 1.60。
  • 我很确定我之前看到过一个关于此的问题。你是不是删了再发?如果你不能展示你的代码,那么发布这个问题是没有意义的,因为它很可能是你的代码库而不是 BC 的错误(尽管 BC 代码库也远非万无一失)。
  • @MaartenBodewes:你可能看到crypto.stackexchange.com/questions/66487/…确实被删除了,但我保留了一个书签
  • 我知道;我自己的评论:“如果找不到错误并包含代码,请在 StackOverflow 上询问。”

标签: java encryption cryptography bouncycastle public-key


【解决方案1】:

很遗憾,您最初没有分享相关代码。因此,我必须自己构建一些代码,使用该代码进行测试,并根据该代码回答您的问题。

结果:对于您的操纵响应已经解析失败,因此无法尝试验证它。

代码

String responseHex = "30820381301502010030100c0e4f7065726174696f6e204f6b61793082036606092a864886f70d010702a082035730820353020103310f300d060960864801650304020105003062060b2a864886f70d0109100104a0530451304f020101060200013031300d060960864801650304020105000420d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b020203e7180f32303139303230373131343130305a318202d7308202d30201013081a73081993119301706035504030c10746573742e6578616d706c652e636f6d31193017060355040b0c105465737420436572746966696361746531153013060355040a0c0c5465737420436f6d70616e793112301006035504070c09546573742043697479310b300906035504080c024e41310b3009060355040613024e41311c301a06092a864886f70d010901160d7465737440746573742e636f6d020900f107055617507892300d06096086480165030402010500a0820100301a06092a864886f70d010903310d060b2a864886f70d0109100104301c06092a864886f70d010905310f170d3139303230373131343130335a302d06092a864886f70d0109343120301e300d06096086480165030402010500a10d06092a864886f70d01010b0500302f06092a864886f70d010904312204209e495138576ec3412aad5d0ca9da6ec9db27035b63173bc36ded376c9eb43cff3064060b2a864886f70d010910022f315530533051304f300b0609608648016503040203044004612191f42ba99172120c710d91f05df8af4a5fd6ad7d6f21a1cf430a99700c1087a2f01eeac9f10125534712d5119e723c8e34fcd7fd9294e15f66112578f8300d06092a864886f70d01010b0500048201001814599f602af54afdd3bb56df2f88ee2bdc42d8204379a2d2a983195ed3e8b74aada8a6161d1e56e3cf3338bd0250df1d90e97454393d2514c6125a1d9ffec7c9530015acb5ba4e4fd7d224c225a220e15c423446d9f8ba1ffc3d4c0a63ec856799a9a3267debf6fcd3cf11fe364c183502acfcd05dee834540e2f07e4ee3bb6b590848fc90e87ba6db57aa89f101448a7665639fdc00c6839290346fa80c135f0d127861adf512f12d6e5fe52c15fe0718ba8b834b8fa56f298c5a2a830fa880e080f3b67237efef1a05cb76fedbb2a7d272bab1adb6cb9790b382a98e26e00d2def94f09efd24454cb3aa3f60490ad651ba8fee8292349e9ee3da16f8d71e";
String responseChangedHex = "30820381301502010030100c0e4f7065726174696f6e204f6b61793082036606092b864886f70d010702b082035730820353020103310f300d060960864801650304020105003062060b2b864886f70d0109100104b0530451304f020101060200013031300d060960864801650304020105000420d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4bc457bb8f82743f31e930b020203e7180f32303139303230373131343130305b318202d7308202d30201013081b73081993119301706035504030c10746573742e6578616d706c652e636f6d31193017060355040b0c105465737420436572746966696361746531153013060355040b0c0c5465737420436f6d70616e793112301006035504070c09546573742043697479310b300906035504080c024e41310b3009060355040613024e41311c301b06092b864886f70d010901160d7465737440746573742e636f6d020900f107055617507892300d06096086480165030402010500b0820100301b06092b864886f70d010903310d060b2b864886f70d0109100104301c06092b864886f70d010905310f170d3139303230373131343130335b302d06092b864886f70d0109343120301e300d06096086480165030402010500b10d06092b864886f70d01010b0500302f06092b864886f70d010904312204209e495138576ec3412bbd5d0cb9db6ec9db27035b63173bc36ded376c9eb43cff3064060b2b864886f70d010910022f315530533051304f300b0609608648016503040203044004612191f42bb99172120c710d91f05df8bf4b5fd6bd7d6f21b1cf430b99700c1087b2f01eebc9f10125534712d5119e723c8e34fcd7fd9294e15f66112578f8300d06092b864886f70d01010b0500048201001814599f602bf54bfdd3bb56df2f88ee2bdc42d8204379b2d2b983195ed3e8b74bbdb8b6161d1e56e3cf3338bd0250df1d90e97454393d2514c6125b1d9ffec7c9530015bcb5bb4e4fd7d224c225b220e15c423446d9f8bb1ffc3d4c0b63ec856799b9b3267debf6fcd3cf11fe364c183502bcfcd05dee834540e2f07e4ee3bb6b590848fc90e87bb6db57bb89f101448b7665639fdc00c6839290346fb80c135f0d127861bdf512f12d6e5fe52c15fe0718bb8b834b8fb56f298c5b2b830fb880e080f3b67237efef1b05cb76fedbb2b7d272bbb1bdb6cb9790b382b98e26e00d2def94f09efd24454cb3bb3f60490bd651bb8fee8292349e9ee3db16f8d71e";
String certificateB64 = "MIID3jCCAsagAwIBAgIJAPEHBVYXUHiSMA0GCSqGSIb3DQEBCwUAMIGZMRkwFwYD\n" + 
        "VQQDDBB0ZXN0LmV4YW1wbGUuY29tMRkwFwYDVQQLDBBUZXN0IENlcnRpZmljYXRl\n" + 
        "MRUwEwYDVQQKDAxUZXN0IENvbXBhbnkxEjAQBgNVBAcMCVRlc3QgQ2l0eTELMAkG\n" + 
        "A1UECAwCTkExCzAJBgNVBAYTAk5BMRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3Qu\n" + 
        "Y29tMB4XDTE5MDIwNzEwNTkxNFoXDTIwMDIwNzEwNTkxNFowgZkxGTAXBgNVBAMM\n" + 
        "EHRlc3QuZXhhbXBsZS5jb20xGTAXBgNVBAsMEFRlc3QgQ2VydGlmaWNhdGUxFTAT\n" + 
        "BgNVBAoMDFRlc3QgQ29tcGFueTESMBAGA1UEBwwJVGVzdCBDaXR5MQswCQYDVQQI\n" + 
        "DAJOQTELMAkGA1UEBhMCTkExHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20w\n" + 
        "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOCc+A01I6FG7GIQLygwjN\n" + 
        "cOqqFE7l6TJXsmGuG7W9ndkN13zEGTIXUcWxQKYUGBp9IzifvK1ezncP/+TsJvoL\n" + 
        "hpc3HltIKay3TB0SvLvEbyvTWsX2Vbld3VkDP1KkvmISwfeozSAjFI5J58kFreqM\n" + 
        "xLVCHvTRPBpBZXn93uzOC1k3Hcp4DVLzl6ooib6Mst4riltOOFYNAaTMd78V/D0D\n" + 
        "1tNDljcEMbinMmcwpARFfd3Ow0x3EacgzBiGtE+hVBvAJ5suo5berEtAwdnTQSGc\n" + 
        "Cn/V9lheCt06fQmxTgg+tjI14cmfMXnHUvOts13aO6zn7NrXH3a52ATaXidkCmZp\n" + 
        "AgMBAAGjJzAlMAsGA1UdDwQEAwIGwDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAN\n" + 
        "BgkqhkiG9w0BAQsFAAOCAQEAAuvuWpWcy4JLOsdcUVZwPsrKPoMJFkhOgEbTv6zw\n" + 
        "3W3Jhtxz7mv6uIog0/8U0oNWOjLJ5kXbe/580lywbqTLHPQmdD71yQIarUJnspLj\n" + 
        "u90iJXgVbWtuYVLAPB1ZXdZ15gqLmgfvzSEFfZgIqaHtFjBhti3sukIREPYKrESQ\n" + 
        "vw8kb/9fAKQI3oVSGygNSCeuRQ00upav9O9jyK2BYSmVV1Vi5jHNBL0RgANp41Tz\n" + 
        "RrqIzjzsv1cMO3CJHxgwv8+taTZ8ATDNDvcVCLA2w1gQNYLCPUjtA1ory7TYjw0F\n" + 
        "/it/Ksayt8ZlICC1QBR1C2ELT3PVNoSomkYlcAKXJoVQDA==";

byte[] certificateBytes = Base64.decode(certificateB64);
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
SignerInformationVerifier signerInformationVerifier = new JcaSimpleSignerInfoVerifierBuilder().build(certificateHolder);

//
// Validate the original timestamp response
//
byte[] responseBytes = Hex.decode(responseHex);
TimeStampResp responseResp = TimeStampResp.getInstance(responseBytes);
TimeStampToken responseToken = new TimeStampToken(responseResp.getTimeStampToken());

responseToken.validate(signerInformationVerifier);

//
// Validate the manipulated timestamp response
//
responseBytes = Hex.decode(responseChangedHex);
responseResp = TimeStampResp.getInstance(responseBytes);
responseToken = new TimeStampToken(responseResp.getTimeStampToken());

responseToken.validate(signerInformationVerifier);

结果

在尝试验证已在行中的操纵时间戳响应期间

responseResp = TimeStampResp.getInstance(responseBytes);

抛出异常:

java.lang.IllegalArgumentException: failed to construct sequence from byte[]: DEF length 27 object truncated by 1
    at org.bouncycastle.asn1.ASN1Sequence.getInstance(Unknown Source)
    at org.bouncycastle.asn1.tsp.TimeStampResp.getInstance(Unknown Source)
    at mkl.testarea.bc1.timestamp.ValidateTST.testValidateLikeUser8897013(ValidateTST.java:75)

因此,无法解析响应。因此,无法调用TimeStampToken.validate

使用您的代码

在您最终发布代码后,我还测试了该代码:

responseBytes = Hex.decode(responseChangedHex);
TimeStampResponse response = new TimeStampResponse(responseBytes);
TimeStampToken token = response.getTimeStampToken();
TimeStampTokenInfo tokenInfo = token.getTimeStampInfo();

但在这里我在解析被操纵的响应时已经得到了一个异常:

java.io.EOFException: DEF length 27 object truncated by 1
    at org.bouncycastle.asn1.DefiniteLengthInputStream.read(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSequenceParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSetParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSequenceParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSequenceParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSequenceParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSetParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.DERSequenceParser.getLoadedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readVector(Unknown Source)
    at org.bouncycastle.asn1.ASN1StreamParser.readTaggedObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.readObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildEncodableVector(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildDEREncodableVector(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.readObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildEncodableVector(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildDEREncodableVector(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.buildObject(Unknown Source)
    at org.bouncycastle.asn1.ASN1InputStream.readObject(Unknown Source)
    at org.bouncycastle.tsp.TimeStampResponse.readTimeStampResp(Unknown Source)
    at org.bouncycastle.tsp.TimeStampResponse.<init>(Unknown Source)
    at org.bouncycastle.tsp.TimeStampResponse.<init>(Unknown Source)
    at mkl.testarea.bc1.timestamp.ValidateTST.testValidateLikeUser8897013(ValidateTST.java:98)

即在这一行

TimeStampResponse response = new TimeStampResponse(responseBytes);

因此,即使使用TimeStampResponse 而不是TimeStampResp,也无法调用TimeStampToken.validate 来响应您的响应。

BC 版本

正如您在评论中表达的疑问:我确实使用 BC 1.60 进行测试,在我的类路径中同时包含 bcprov-jdk15on-1.60.jarbcpkix-jdk15on-1.60.jar 并已将 BC 注册为安全提供程序:

Security.addProvider(new BouncyCastleProvider());

对我来说,这是一个完全正常的 BC 设置。

【讨论】:

  • 感谢您的努力。让我看看我可能出错的地方。
  • 获得了分享一些代码的权限。感谢您的理解。我的例子中的方法不是要走的路吗?你的更简单、更干净!
  • 我认为您的示例代码正在使用 BC v1.37 或基于您的 TimeStampResp 类的类似代码。我提到我使用的是 1.60,新类是 TimeStampResponse。这个新的class 没有getInstance() 方法。不幸的是,BC 不保留易于链接的档案,因此如果您单击 1.61(最新)的链接,则必须将其修改为 1.60。 Modified Link.
  • 1.60 确实包含org.bouncycastle.asn1.tsp.TimeStampResp(在“bcprov-jdk15on-1.60.jar”中),并且该类具有静态getInstance(Object) 方法。请在撰写评论声称其他人做错事之前,验证您的声明。
  • 感谢您的宝贵时间。抱歉耽搁了,但我现在可以重现 EOF 错误并将其标记为答案。很想知道是否有理由使用 TimeStampResp 而不是 TimeStampResponse?为什么他们会有两个班? ...而且我实际上仍然不清楚除了this 之外的两个库(bcprov 与 bcpkix)之间的区别。请分享。
猜你喜欢
  • 1970-01-01
  • 2014-10-11
  • 1970-01-01
  • 2021-12-01
  • 2016-05-29
  • 2022-11-24
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
相关资源
最近更新 更多