BouncyCastle проверяет измененную временную метку - PullRequest
0 голосов
/ 07 февраля 2019

Я заметил, что 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);

1 Ответ

0 голосов
/ 07 февраля 2019

К сожалению, вы изначально не поделились соответствующим кодом.Таким образом, мне пришлось самому создать некоторый код, протестировать его и ответить на ваш вопрос на основе этого кода.

Результат: для вашего манипулируемого ответа уже не выполняется синтаксический анализ, поэтому нет способа попробовать и проверитьit.

Код

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);

anвыдается исключение:

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);

Как следствие, TimeStampToken.validate не может быть вызван для вашего ответа дажеесли кто-то использует TimeStampResponse вместо TimeStampResp.

версии BC

Как вы выразили сомнения в комментарии: я использую BC 1.60 для теста, имеющего bcprov-jdk15on-1.60.jar и bcpkix-jdk15on-1.60.jar в моем classpath и после регистрации BC в качестве поставщика безопасности:

Security.addProvider(new BouncyCastleProvider());

Для меня это абсолютно нормальная настройка BC.

...