diff options
author | Adam Vartanian <flooey@google.com> | 2017-03-24 18:16:48 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-03-24 18:16:48 +0000 |
commit | 1fcf477c640d5cd25514e9d261035a70fce3ad99 (patch) | |
tree | da15f3c49b06a255595c0f3381c641249f24853e | |
parent | b18ddaff10013b068327a3aa468274bbbddcba69 (diff) | |
parent | 13b268f0491ae3cbcb4b7582d1a31bd5c45c69ee (diff) | |
download | wycheproof-1fcf477c640d5cd25514e9d261035a70fce3ad99.tar.gz |
Merge upstream-master into master.
am: 13b268f049
Change-Id: I87bfaacebb9d4c90d986bcfc4f75d3af87de29e1
42 files changed, 11798 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac51a05 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bazel-* @@ -0,0 +1,145 @@ +# Wycheproof tests + +java_library( + name = "utils", + srcs = [ + "java/com/google/security/wycheproof/EcUtil.java", + "java/com/google/security/wycheproof/RandomUtil.java", + "java/com/google/security/wycheproof/TestUtil.java", + ], +) + +common_deps = [ + ":utils", +] + +test_srcs = glob(["java/com/google/security/wycheproof/testcases/*.java"]) + ["java/com/google/security/wycheproof/WycheproofRunner.java"] + +# These targets run all tests. + +load(":build_defs.bzl", "bouncycastle_all_tests", "spongycastle_all_tests") + +# Generates BouncyCastleAllTests_1_xx target for all available versions, +# plus a BouncyCastleAllTests alias for latest stable. +# +# To test latest stable: +# $ bazel test BouncyCastleAllTests +# +# To test other versions, e.g., v1.52: +# $ bazel test BouncyCastleAllTests_1_52 +# +# To test all known versions (warning, will take a long time): +# $ bazel test BouncyCastleAllTest_* +bouncycastle_all_tests( + # This test takes a long time, because key generation for DSA and DH generate new parameters. + size = "large", + srcs = ["java/com/google/security/wycheproof/BouncyCastleAllTests.java"] + test_srcs, + test_class = "com.google.security.wycheproof.BouncyCastleAllTests", + deps = common_deps, +) + +java_test( + name = "BouncyCastleAllTestsLocal", + # this target requires specifing a shell variable, thus won't work with the wildcard target patterns. + # with tags=["manual"] it'll be excluded from said patterns. + tags = ["manual"], + size = "large", + srcs = ["java/com/google/security/wycheproof/BouncyCastleAllTests.java"] + test_srcs, + test_class = "com.google.security.wycheproof.BouncyCastleAllTests", + deps = common_deps + ["@local//:bouncycastle_jar"], +) + +# Generates SpongyCastleAllTests_1_xx target for all available versions, +# plus a SpongyCastleAllTests alias for latest stable. +# +# To test latest stable: +# $ bazel test SpongyCastleAllTests +# +# To test other versions, e.g., v1.52.0.0: +# $ bazel test SpongyCastleAllTests_1_52 +# +# To test all known versions (warning, will take a long time): +# $ bazel test SpongyCastleAllTests_* +spongycastle_all_tests( + # This test takes a long time, because key generation for DSA and DH generate new parameters. + size = "large", + srcs = ["java/com/google/security/wycheproof/SpongyCastleAllTests.java"] + test_srcs, + test_class = "com.google.security.wycheproof.SpongyCastleAllTests", + deps = common_deps, +) + +# These targets exclude slow tests. + +load(":build_defs.bzl", "bouncycastle_tests", "spongycastle_tests") + +# Generates BouncyCastleTest_1_xx target for all available versions, +# plus a BouncyCastleTest alias for latest stable. +# +# To test latest stable: +# $ bazel test BouncyCastleTest +# +# To test other versions, e.g., v1.52: +# $ bazel test BouncyCastleTest_1_52 +# +# To test all known versions: +# $ bazel test BouncyCastleTest_* +bouncycastle_tests( + size = "large", + srcs = ["java/com/google/security/wycheproof/BouncyCastleTest.java"] + test_srcs, + test_class = "com.google.security.wycheproof.BouncyCastleTest", + deps = common_deps, +) + +java_test( + name = "BouncyCastleTestLocal", + # this target requires specifing a shell variable, thus won't work with the wildcard target patterns. + # with tags=["manual"] it'll be excluded from said patterns. + tags = ["manual"], + size = "large", + srcs = ["java/com/google/security/wycheproof/BouncyCastleTest.java"] + test_srcs, + test_class = "com.google.security.wycheproof.BouncyCastleTest", + deps = common_deps + ["@local//:bouncycastle_jar"], +) + +# Generates SpongyCastleTest_1_xx target for all available versions, +# plus a SpongyCastleTest alias for latest stable. +# +# To test latest stable: +# $ bazel test SpongyCastleTest +# +# To test other versions, e.g., v1.52.0.0: +# $ bazel test SpongyCastleTest_1_52 +# +# To test all known versions: +# $ bazel test SpongyCastleTest_* +spongycastle_tests( + size = "large", + srcs = ["java/com/google/security/wycheproof/SpongyCastleTest.java"] + test_srcs, + test_class = "com.google.security.wycheproof.SpongyCastleTest", + deps = common_deps, +) + +# OpenJDK tests +java_test( + name = "OpenJDKTest", + size = "large", + srcs = ["java/com/google/security/wycheproof/OpenJDKTest.java"] + test_srcs, + test_class = "com.google.security.wycheproof.OpenJDKTest", + deps = common_deps, +) + +java_test( + name = "OpenJDKAllTests", + size = "large", + srcs = ["java/com/google/security/wycheproof/OpenJDKAllTests.java"] + test_srcs, + test_class = "com.google.security.wycheproof.OpenJDKAllTests", + deps = common_deps, +) + +# Platform-independent tests +java_test( + name = "ProviderIndependentTest", + size = "small", + srcs = ["java/com/google/security/wycheproof/ProviderIndependentTest.java"] + test_srcs, + deps = common_deps, +) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fa97ad3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,43 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement] +(https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Disclosure +If your tests uncover security vulnerabilities, please first report directly to +the maintainers of the libraries. You should only submit tests to us once the +bugs have been acknowledged or fixed. + +Google has several +[security reward programs](https://www.google.com/about/appsecurity/programs-home/) +that provide cash rewards for quality security research that identifies or fixes +security vulnerabilities in products that we provide or proactive security +improvements to select open-source products. If your tests found or helped fix +vulnerabilities that are in scope you should submit them to these programs. + +If you have any question with regard to disclosure, please email us at +security@google.com. + +### Code reviews +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the +[Software Grant and Corporate Contributor License Agreement] +(https://cla.developers.google.com/about/google-corporate).
\ No newline at end of file @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..07b10fd --- /dev/null +++ b/README.md @@ -0,0 +1,198 @@ +# Project Wycheproof +https://github.com/google/wycheproof + +*Project Wycheproof is named after +[Mount Wycheproof](https://en.wikipedia.org/wiki/Mount_Wycheproof), the smallest +mountain in the world. The main motivation for the project is to have a goal +that is achievable. The smaller the mountain the more likely it is to be able to +climb it.* + +[TOC] + +## Introduction + +Project Wycheproof tests crypto libraries against known attacks. It is developed +and maintained by members of Google Security Team, but it is not an official +Google product. + +At Google, we rely on many third party cryptographic software libraries. +Unfortunately, in cryptography, subtle mistakes can have catastrophic +consequences, and we found that libraries fall into such implementation +pitfalls much too often and for much too long. Good implementation guidelines, +however, are hard to come by: understanding how to implement cryptography +securely requires digesting decades' worth of academic literature. We recognize +that software engineers fix and prevent bugs with unit testing, and we found +that cryptographic loopholes can be resolved by the same means. + +These observations have prompted us to develop Project Wycheproof, a collection +of unit tests that detect known weaknesses or check for expected behaviors of +some cryptographic algorithm. Project Wycheproof provides tests for most +cryptographic algorithms, including RSA, elliptic curve crypto and +authenticated encryption. Our cryptographers have systematically surveyed the +literature and implemented most known attacks. We have over 80 test cases which +have uncovered more than [40 bugs](doc/bugs.md). For +example, we found that we could recover the private key of widely-used DSA and +ECDHC implementations. + +While we are committed to develop as many attacks as possible, Project +Wycheproof is by no means complete. Passing the tests does not imply that the +library is secure, it just means that it is not vulnerable to the attacks that +Project Wycheproof tests for. Cryptographers are also constantly discovering +new attacks. Nevertheless, with Project Wycheproof developers and users now can +check their libraries against a large number of known attacks, without having +to spend years reading academic papers or become cryptographers themselves. + +For more information on the goals and strategies of Project Wycheproof, please +check out our [doc](doc/). + +### Coverage + +Project Wycheproof has tests for the most popular crypto algorithms, including + +- AES-EAX +- AES-GCM +- [DH](doc/dh.md) +- DHIES +- [DSA](doc/dsa.md) +- [ECDH](doc/ecdh.md) +- ECDSA +- ECIES +- [RSA](doc/rsa.md) + +The tests detect whether a library is vulnerable to many attacks, including + +- Invalid curve attacks +- Biased nonces in digital signature schemes +- Of course, all Bleichenbacher’s attacks +- And many more -- we have over 80 test cases + +Our first set of tests are written in Java, because Java has a common +cryptographic interface. This allowed us to test multiple providers with a +single test suite. While this interface is somewhat low level, and should not +be used directly, we still apply a "defense in depth" argument and expect that +the implementations are as robust as possible. For example, we consider weak +default values to be a significant security flaw. We are converting as many +tests into sets of test vectors to simplify porting the tests to other +languages. We provide ready-to-use test runners for Java Cryptography +Architecture providers such as [Bouncy Castle](http://bouncycastle.org), +[Spongy Castle](https://rtyley.github.io/spongycastle/), and the default +providers in [OpenJDK](http://openjdk.java.net/). + +### Usage + +- Install [Bazel](https://bazel.build/). + +- Install [Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction + Policy + Files](http://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters): + this enables tests with large key sizes. Otherwise you'll see a lot of + "illegal key size" exceptions. + +- Check out the tests + +``` +git clone https://github.com/google/wycheproof.git +``` + +- To test latest stable version of Bouncy Castle: + +``` +bazel test BouncyCastleAllTests +``` + +- To test other versions, e.g., v1.52: + +``` +bazel test BouncyCastleAllTests_1_52 +``` + +- To test all known versions (warning, will take a long time): + +``` +bazel test BouncyCastleAllTests_* +``` + +- To test a local jar, set the `WYCHEPROOF_BOUNCYCASTLE_JAR` environment + variable: + +```shell +$ WYCHEPROOF_BOUNCYCASTLE_JAR=/path/to/bouncycastle +$ bazel test BouncyCastleTestLocal +$ bazel test BouncyCastleAllTestsLocal +``` + +Note: bazel does not currently invalidate the build on environment changes. If +you change the `WYCHEPROOF_BOUNCYCASTLE_JAR` environment variable, run `bazel +clean` to force a rebuild: + +```shell +$ WYCHEPROOF_BOUNCYCASTLE_JAR=/path/to/bouncycastle +$ bazel test BouncyCastleTestLocal +$ WYCHEPROOF_BOUNCYCASTLE_JAR=/path/to/other/jar +$ bazel clean +$ bazel test BouncyCastleTestLocal +``` + +- To test [Spongy Castle](https://rtyley.github.io/spongycastle/), replace +BouncyCastle with SpongyCastle in your commands, for example + +``` +bazel test SpongyCastleAllTests +``` + +- To test your current installation of +[OpenJDK](http://openjdk.java.net/): + +``` +bazel test OpenJDKAllTests +``` + +Note that OpenJDKAllTests expects that OpenJDK is your default JDK, so it might +refuse to run or its results might be incorrect if you are using some other JDK. +If you downloaded your JDK from Oracle or https://java.com, you're probably +using Oracle JDK, which should be compatible with OpenJDK, thus the tests should +run correctly. + +Some tests take a very long time to finish. If you want to exclude them, use +BouncyCastleTest, SpongyCastleTest or OpenJDKTest -- these targets exclude all +slow tests (which are annotated with @SlowTest). + +Most test targets are failing, and each failure might be a security issue. To +learn more about what a failed test means, you might want to check out [our +documentation](doc/bugs.md) or the comments on top of the corresponding test +function and test class. + +### Hall of Bugs + +Here are some of the notable vulnerabilities that are uncovered by +Project Wycheproof: + +- OpenJDK's SHA1withDSA leaks private keys > 1024 bits + - Test: testBiasSha1WithDSA in +[DsaTest](https://github.com/google/wycheproof/blob/master/java/com/google/security/wycheproof/testcases/DsaTest.java). + - This bug is the same as +[CVE-2003-0971 - GnuPG generated ElGamal signatures that leaked the private key] +(https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2003-0971). + +- Bouncy Castle's ECDHC leaks private keys + - Test: testModifiedPublic and testWrongOrderEcdhc in +[EcdhTest](https://github.com/google/wycheproof/blob/master/java/com/google/security/wycheproof/testcases/EcdhTest.java). + +### Maintainers + +Project Wycheproof is maintained by: + +- Daniel Bleichenbacher +- Thai Duong +- Emilia Kasper +- Quan Nguyen + +### Contact and mailing list + +If you want to contribute, please read [CONTRIBUTING](CONTRIBUTING.md) and send +us pull requests. You can also report bugs or request new tests. + +If you'd like to talk to our developers or get notified about major new +tests, you may want to subscribe to our +[mailing list](https://groups.google.com/forum/#!forum/wycheproof-users). To +join, simply send an empty mail to wycheproof-users+subscribe@googlegroups.com. diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..f170ca8 --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,108 @@ +maven_jar( + name = "bouncycastle_1_46", + artifact = "org.bouncycastle:bcprov-jdk15on:1.46", +) + +maven_jar( + name = "bouncycastle_1_47", + artifact = "org.bouncycastle:bcprov-jdk15on:1.47", +) + +maven_jar( + name = "bouncycastle_1_48", + artifact = "org.bouncycastle:bcprov-jdk15on:1.48", +) + +maven_jar( + name = "bouncycastle_1_49", + artifact = "org.bouncycastle:bcprov-jdk15on:1.49", +) + +maven_jar( + name = "bouncycastle_1_50", + artifact = "org.bouncycastle:bcprov-jdk15on:1.50", +) + +maven_jar( + name = "bouncycastle_1_51", + artifact = "org.bouncycastle:bcprov-jdk15on:1.51", +) + +maven_jar( + name = "bouncycastle_1_52", + artifact = "org.bouncycastle:bcprov-jdk15on:1.52", +) + +maven_jar( + name = "bouncycastle_1_53", + artifact = "org.bouncycastle:bcprov-jdk15on:1.53", +) + +maven_jar( + name = "bouncycastle_1_54", + artifact = "org.bouncycastle:bcprov-jdk15on:1.54", +) + +maven_jar( + name = "bouncycastle_1_55", + artifact = "org.bouncycastle:bcprov-jdk15on:1.55", +) + +maven_jar( + name = "bouncycastle_1_56", + artifact = "org.bouncycastle:bcprov-jdk15on:1.56", +) + +maven_jar( + name = "spongycastle_core_1_50", + artifact = "com.madgag.spongycastle:core:1.50.0.0", +) + +maven_jar( + name = "spongycastle_prov_1_50", + artifact = "com.madgag.spongycastle:prov:1.50.0.0", +) + +maven_jar( + name = "spongycastle_core_1_51", + artifact = "com.madgag.spongycastle:core:1.51.0.0", +) + +maven_jar( + name = "spongycastle_prov_1_51", + artifact = "com.madgag.spongycastle:prov:1.51.0.0", +) + +maven_jar( + name = "spongycastle_core_1_52", + artifact = "com.madgag.spongycastle:core:1.52.0.0", +) + +maven_jar( + name = "spongycastle_prov_1_52", + artifact = "com.madgag.spongycastle:prov:1.52.0.0", +) + +maven_jar( + name = "spongycastle_core_1_53", + artifact = "com.madgag.spongycastle:core:1.53.0.0", +) + +maven_jar( + name = "spongycastle_prov_1_53", + artifact = "com.madgag.spongycastle:prov:1.53.0.0", +) + +maven_jar( + name = "spongycastle_core_1_54", + artifact = "com.madgag.spongycastle:core:1.54.0.0", +) + +maven_jar( + name = "spongycastle_prov_1_54", + artifact = "com.madgag.spongycastle:prov:1.54.0.0", +) + +load(":local_repository_defs.bzl", "local_jars") + +local_jars(name = "local") diff --git a/build_defs.bzl b/build_defs.bzl new file mode 100644 index 0000000..61858bd --- /dev/null +++ b/build_defs.bzl @@ -0,0 +1,119 @@ +bouncycastle_versions = range(49, 57) + +# These targets run all tests. +def bouncycastle_all_tests(srcs, deps, size, test_class): + """BouncyCastle version-specific tests.""" + + # Generates BouncyCastleAllTests_1_56, ..., BouncyCastleAllTests_1_49 + for version in bouncycastle_versions: + native.java_test( + name = "BouncyCastleAllTests_1_%s" % version, + srcs = srcs, + deps = deps + [ + "@bouncycastle_1_%s//jar" % version, + ], + size = size, + test_class = test_class, + ) + + # Latest stable. + # We can't use native.alias, because aliased tests are not run. + # So, we simply duplicate the test. + native.java_test( + name = "BouncyCastleAllTests", + srcs = srcs, + deps = deps + ["@bouncycastle_1_%s//jar" % max(bouncycastle_versions)], + size = size, + test_class = test_class, + ) + +# These targets exclude slow tests. +def bouncycastle_tests(srcs, deps, size, test_class): + """BouncyCastle version-specific tests.""" + + # Generates BouncyCastleTest_1_56, ..., BouncyCastleTest_1_49 + for version in bouncycastle_versions: + native.java_test( + name = "BouncyCastleTest_1_%s" % version, + srcs = srcs, + deps = deps + [ + "@bouncycastle_1_%s//jar" % version, + ], + size = size, + test_class = test_class, + ) + + # Latest stable. + # We can't use native.alias, because aliased tests are not run. + # So, we simply duplicate the test. + native.java_test( + name = "BouncyCastleTest", + srcs = srcs, + deps = deps + ["@bouncycastle_1_%s//jar" % max(bouncycastle_versions)], + size = size, + test_class = test_class, + ) + +spongycastle_versions = range(50, 55) + +# These targets run all tests. +def spongycastle_all_tests(srcs, deps, size, test_class): + """SpongyCastle version-specific tests.""" + + # Generates SpongyCastleAllTests_1_54, ..., SpongyCastleAllTests_1_50 + for version in spongycastle_versions: + native.java_test( + name = "SpongyCastleAllTests_1_%s" % version, + srcs = srcs, + deps = deps + [ + "@spongycastle_core_1_%s//jar" % version, + "@spongycastle_prov_1_%s//jar" % version, + ], + size = size, + test_class = test_class, + ) + + # Latest stable. + # We can't use native.alias, because aliased tests are not run. + # So, we simply duplicate the test. + native.java_test( + name = "SpongyCastleAllTests", + srcs = srcs, + deps = deps + [ + "@spongycastle_core_1_%s//jar" % max(spongycastle_versions), + "@spongycastle_prov_1_%s//jar" % max(spongycastle_versions), + ], + size = size, + test_class = test_class, + ) + +# These targets exclude slow tests. +def spongycastle_tests(srcs, deps, size, test_class): + """SpongyCastle version-specific tests.""" + + # Generates SpongyCastleTest_1_54, ..., SpongyCastleTest_1_50 + for version in spongycastle_versions: + native.java_test( + name = "SpongyCastleTest_1_%s" % version, + srcs = srcs, + deps = deps + [ + "@spongycastle_core_1_%s//jar" % version, + "@spongycastle_prov_1_%s//jar" % version, + ], + size = size, + test_class = test_class, + ) + + # Latest stable. + # We can't use native.alias, because aliased tests are not run. + # So, we simply duplicate the test. + native.java_test( + name = "SpongyCastleTest", + srcs = srcs, + deps = deps + [ + "@spongycastle_core_1_%s//jar" % max(spongycastle_versions), + "@spongycastle_prov_1_%s//jar" % max(spongycastle_versions), + ], + size = size, + test_class = test_class, + ) diff --git a/doc/bugs.md b/doc/bugs.md new file mode 100644 index 0000000..1533e3b --- /dev/null +++ b/doc/bugs.md @@ -0,0 +1,5 @@ +# List of bugs in common algorithms +* [RSA](rsa.md) +* [DSA](dsa.md) +* [ECDH](ecdh.md) +* [Diffie-Hellman](dh.md) diff --git a/doc/dh.md b/doc/dh.md new file mode 100644 index 0000000..ca8c410 --- /dev/null +++ b/doc/dh.md @@ -0,0 +1,141 @@ +# Diffie-Hellman + +## Subgroup confinement attacks + +The papers by van Oorshot and Wiener [OW96] rsp. Lim and Lee [LL98] show that +Diffie-Hellman keys can be found much faster if the short exponents are used and +if the multiplicative group modulo p contains small subgroups. In particular an +attacker can try to send a public key that is an element of a small subgroup. If +the receiver does not check for such elements then may be possible to find the +private key modulo the order of the small subgroup. Several countermeasures +against such attacks have been proposed: For example IKE uses fields of order p +where p is a safe prime (i.e. $$q=(p-1)/2),$$ hence the only elements of small +order are 1 and p-1. + +[NIST SP 800-56A] rev. 2, Section 5.5.1.1 only requires that the size of the +subgroup generated by the generator g is big enough to prevent the baby-step +giant-step algorithm. I.e. for 80-bit security p must be at least 1024 bits long +and the prime q must be at least 160 bits long. A 2048 bit prime p and a 224 bit +prime q are sufficient for 112 bit security. To avoid subgroup confinment +attacks NIST requires that public keys are validated, i.e. by checking that a +public key y satisfies the conditions $$2 \leq y \leq p-2$$ and $$y^q \mod p = +1$$ (Section 5.6.2.3.1). Further, after generating the shared secret $$z = +y_a^{x_b} \mod p$$ each party should check that $$z \neq 1.$$ RFC 2785 contains +similar recommendations. The public key validation described by NIST requires +that the order q of the generator g is known to the verifier. Unfortunately, the +order q is missing in [PKCS #3]. [PKCS #3] describes the Diffie-Hellman +parameters only by the values p, g and optionally the key size in bits. + +The class DHParameterSpec that defines the Diffie-Hellman parameters in JCE +contains the same values as [PKCS #3]. In particular, it does not contain the +order of the subgroup q. Moreover, the SUN provider uses the minimal sizes +specified by NIST for q. Essentially the provider reuses the parameters for DSA. + +Therefore, there is no guarantee that an implementation of Diffie-Hellman is secure against +subgroup confinement attacks. Without a key validation it is insecure to use the key-pair +generation from [NIST SP 800-56A] Section 5.6.1.1 (The key-pair generation there only requires that +static and ephemeral private keys are randomly chosen in the range \\(1..q-1)\\). + +To avoid big disasters the tests below require that key sizes are not minimal. I.e., currently +the tests require at least 512 bit keys for 1024 bit fields. We use this lower limit because that +is what the SUN provider is currently doing. + +TODO(bleichen): Find a reference supporting or disproving that decision. + +## Weak parameters + +The DH parameters must be carefully chosen to avoid security issues. A panel at +Eurocrypt'92 discussed the possiblity of trapdoors in DL based primitives +[Eurocrypt92 panel]. A. Lenstra pointed out that the primes chould be chosen +such that the special number field sieve can be used to compute discrete +logarithms. Gordon has analyzed methods to generate and detect weak parameters +[G92]. Section 4 of Gordons paper describes a method that can detect some +special cases, but no general method was given. Recently Fried et al. showed +that 1024 bit discrete logarithms with the special number field sieve are +feasible [FGHT16]. Moreover some libraries use primes that are susceptible to +this attack [FGHT16]. + +TODO(bleichen): So far not test for weak DH parameters has been implemented. +Possibly we should at least implement a test that detects special cases, so +that weak primes (such as the one used in libtomcrypt) are detected. + +DH implementations are sometimes misconfigured. Adrian et al. [WeakDh] analyzed +various implementations and found for example the following problems in the +parameters: p is sometimes composite, p-1 contains no large prime factor, q is +used instead of the generator g. + +## References +[Eurocrypt92 panel]: "The Eurocrypt'92 Controversial Issue Trapdoor Primes and Moduli", +EUROCRYPT '92, LNCS 658, pp. 194-199. + +[G92]: D. M. Gordon. "Designing and detecting trapdoors for discrete log +cryptosystems." CRYPTO’92, pp. 66–75. + +\[FGHT16]: J. Fried, P. Gaudry, N. Heininger, E. Thome. "A kilobit hidden SNFS +discrete logarithm computation". http://eprint.iacr.org/2016/961.pdf + +[OW96]: P. C. van Oorschot, M. J. Wiener, "On Diffie-Hellman key agreement with short exponents", +Eurocrypt 96, pp 332–343. + +[LL98]: C.H. Lim and P.J. Lee, +"A key recovery attack on discrete log-based schemes using a prime order subgroup", +CRYPTO' 98, pp 249–263. + +[WeakDh]: D. Adrian, K. Bhargavan, Z. Durumeric, P. Gaudry, M. Green, +J. A. Halderman, N. Heninger, D. Springall, E. Thomé, Luke Valenta, +B. VanderSloot, E. Wustrow, S. Zanella-Béguelink, P. Zimmermann, +"Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice" +https://weakdh.org/imperfect-forward-secrecy-ccs15.pdf + +[NIST SP 800-56A], revision 2, May 2013 +http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf + +[PKCS #3]: "Diffie–Hellman Key Agreement", +http://uk.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm + +[RFC 2785]: R. Zuccherato, +"Methods for Avoiding 'Small-Subgroup' Attacks on the Diffie-Hellman Key Agreement Method for S/MIME", +March 2000 +https://www.ietf.org/rfc/rfc2785.txt + +<!-- +## Sources that might be used for additional tests: + +CVE-2015-3193: The Montgomery squaring implementation in crypto/bn/asm/x86_64-mont5.pl +in OpenSSL 1.0.2 before 1.0.2e on the x86_64 platform, as used by the BN_mod_exp function, +mishandles carry propagation +https://blog.fuzzing-project.org/31-Fuzzing-Math-miscalculations-in-OpenSSLs-BN_mod_exp-CVE-2015-3193.html + +CVE-2016-0739: libssh before 0.7.3 improperly truncates ephemeral secrets generated for the +(1) diffie-hellman-group1 and (2) diffie-hellman-group14 key exchange methods to 128 bits ... + +CVE-2015-1787 The ssl3_get_client_key_exchange function in s3_srvr.c in OpenSSL 1.0.2 before +1.0.2a, when client authentication and an ephemeral Diffie-Hellman ciphersuite are enabled, +allows remote attackers to cause a denial of service (daemon crash) via a ClientKeyExchange +message with a length of zero. + +CVE-2015-0205 The ssl3_get_cert_verify function in s3_srvr.c in OpenSSL 1.0.0 before 1.0.0p +and 1.0.1 before 1.0.1k accepts client authentication with a Diffie-Hellman (DH) certificate +without requiring a CertificateVerify message, which allows remote attackers to obtain access +without knowledge of a private key via crafted TLS Handshake Protocol traffic to a server that +recognizes a Certification Authority with DH support. + +CVE-2016-0701 The DH_check_pub_key function in crypto/dh/dh_check.c in OpenSSL 1.0.2 before +1.0.2f does not ensure that prime numbers are appropriate for Diffie-Hellman (DH) key exchange, +which makes it easier for remote attackers to discover a private DH exponent by making multiple +handshakes with a peer that chose an inappropriate number, as demonstrated by a number in an +X9.42 file. + +CVE-2006-1115 nCipher HSM before 2.22.6, when generating a Diffie-Hellman public/private key +pair without any specified DiscreteLogGroup parameters, chooses random parameters that could +allow an attacker to crack the private key in significantly less time than a brute force attack. + +CVE-2015-1716 Schannel in Microsoft Windows Server 2003 SP2, Windows Vista SP2, Windows Server +2008 SP2 and R2 SP1, Windows 7 SP1, Windows 8, Windows 8.1, Windows Server 2012 Gold and R2, and +Windows RT Gold and 8.1 does not properly restrict Diffie-Hellman Ephemeral (DHE) key lengths, +which makes it easier for remote attackers to defeat cryptographic protection mechanisms via +unspecified vectors, aka "Schannel Information Disclosure Vulnerability. + +CVE-2015-2419: Random generation of the prime p allows Pohlig-Hellman and probably other +stuff. +--> diff --git a/doc/dsa.md b/doc/dsa.md new file mode 100644 index 0000000..0c2f631 --- /dev/null +++ b/doc/dsa.md @@ -0,0 +1,192 @@ +# DSA + +[TOC] + +The digital signature algorithm (DSA) is one of three signature schemes +descripted in the digital signature standard [DSS]. + +## Key generation + +4.2 Selection of Parameter Sizes and Hash Functions for DSA +The DSS specifies the following choices for the pair (L,N), +where L is the size of p in bits and N is the size of q in bits: + +L | N +---:|----: +1024| 160 +2048| 224 +2048| 256 +3072| 256 + +The tests expect the following properties of the parameters used during +key generation: + +* If only the parameter L is specified by the caller then N should be one + of the options proposed in [DSS]. +* If no size is specified then L should be at least 2048. This is the minimal + key size recommended by NIST for the period up to the year 2030. + +## Signature generation + +The DSA signature algorithm requires that each signature is computed with a new +one-time secret k. This secret value should be close to uniformly distributed. +If that is not the case then DSA signatures can leak the private key that was +used to generate the signature. Two methods for generating the one-time secrets +are described in FIPS PUB 186-4, Section B.5.1 or B.5.2 [DSS]. There is also the +possibility that the use of mismatched implementations for key generation and +signature generation are leaking the private keys. + +## Signature verification + +A DSA signature is a DER encoded tuple of two integers (r,s). To verify a +signature the verifier first checks $$0 < r < q$$ and $$0 < s < q$$. The +verifier then computes: + +$$ +\begin{array}{l} +w=s^{-1} \bmod q\\ +u1 = w \cdot H(m) \bmod q\\ +u2 = w \cdot r \bmod q\\ +\end{array} +$$ + +and then verifies that \\(r = (g^{u1}y^{u2} \bmod p) \bmod q\\) + +## Incorrect computations and range checks. + +Some libraries return 0 as the modular inverse of 0 or q. +This can happen if the library computes the modular +inverse of s as \\(w=s^{q-2} \mod q\\) (gpg4browsers) of simply +if the implementations is buggy (pycrypto). if additionally to such +a bug the range of r,s is not or incorrectly tested then it might +be feasible to forge signatures with the values (r=1, s=0) or (r=1, s=q). +In particular, if a library can be forced to compute \\(s^{-1} \mod q = 0\\) +then the verification would compute \\( w = u1 = u2 = 0 \\) and hence +\\( (g^{u1}y^{u2} \mod p) \mod q = 1 .\\) + +## Timing attacks + +TBD + +# Some notable failures of crypto libraries. + +## JDK + +The jdk8 implementation of SHA1withDSA previously checked the key size as follows: + +```java +@Override + protected void checkKey(DSAParams params) + throws InvalidKeyException { + int valueL = params.getP().bitLength(); + if (valueL > 1024) { + throw new InvalidKeyException("Key is too long for this algorithm"); + } + } +``` + +This check was reasonable, it partially ensures conformance with the NIST +standard. In most cases would prevent the attack described above. + +However, Oracle released a patch that removed the length verification in DSA in +jdk9: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/edd7a67585a5 +https://bugs.openjdk.java.net/browse/JDK-8039921 + +The new code is here: +http://hg.openjdk.java.net/jdk9/dev/jdk/file/edd7a67585a5/src/java.base/share/classes/sun/security/provider/DSA.java + +The change was further backported to jdk8: +http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/3212f1631643 + +Doing this was a serious mistake. It easily allowed incorrect implementations. +While generating 2048 bit DSA keys in jdk7 was not yet supported, doing so in +jdk8 is. To trigger this bug in jdk7 an application had to use a key generated +by a third party library (e.g. OpenSSL). Now, it is possible to trigger the bug +just using JCE. Moreover, the excessive use of default values in JCE makes it +easy to go wrong and rather difficult to spot the errors. + +The bug was for example triggered by the following code snippet: + +```java + KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); + Keygen.initialize(2048); + KeyPair keypair = keygen.genKeyPair(); + Signature s = Signature.getInstance("DSA"); + s.initSign(keypair.getPrivate()); +``` + +The first three lines generate a 2048 bit DSA key. 2048 bits is currently the +smallest key size recommended by NIST. + +```java + KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); + Keygen.initialize(2048); + KeyPair keypair = keygen.genKeyPair(); +``` + +The key size specifies the size of p but not the size of q. The NIST standard +allows either 224 or 256 bits for the size of q. The selection typically depends +on the library. The Sun provider uses 224. Other libraries e.g. OpenSSL +generates by default a 256 bit q for 2048 bit DSA keys. + +The next line contains a default in the initialization + +```java + Signature s = Signature.getInstance("DSA"); +``` +This line is equivalent to + +```java + Signature s = Signature.getInstance("SHA1withDSA"); +``` +Hence the code above uses SHA1 but with DSA parameters generated for SHA-224 +or SHA-256 hashes. Allowing this combination by itself is already a mistake, +but a flawed implementaion made the situation even worse. + +The implementation of SHA1withDSA assumeed that the parameter q is 160 bits +long and used this assumption to generate a random 160-bit k when generating a +signature instead of choosing it uniformly in the range (1,q-1). +Hence, k severely biased. Attacks against DSA with biased k are well known. +Howgrave-Graham and Smart analyzed such a situation [HS99]. Their results +show that about 4 signatrues leak enough information to determine +the private key in a few milliseconds. +Nguyen analyzed a similar flaw in GPG [N04]. +I.e., Section 3.2 of Nguyens paper describes essentially the same attack as +used here. More generally, attacks based on lattice reduction were developed +to break a variety of cryptosystems such as the knapsack cryptosystem [O90]. + +## Further notes + +The short algorithm name “DSA” is misleading, since it hides the fact that +`Signature.getInstance(“DSA”)` is equivalent to +`Signature.getInstance(“SHA1withDSA”)`. To reduce the chance of a +misunderstanding short algorithm names should be deprecated. In JCE the hash +algorithm is defined by the algorithm. I.e. depending on the hash algorithm to +use one would call one of: + +```java + Signature.getInstance(“SHA1withDSA”); + Signature.getInstance(“SHA224withDSA”); + Signature.getInstance(“SHA256withDSA”); +``` + +A possible way to push such a change are code analysis tools. "DSA" is in good +company with other algorithm names “RSA”, “AES”, “DES”, all of which default to +weak algorithms. + +## References + +[HS99]: N.A. Howgrave-Graham, N.P. Smart, + “Lattice Attacks on Digital Signature Schemes” + http://www.hpl.hp.com/techreports/1999/HPL-1999-90.pdf + +[N04]: Phong Nguyen, “Can we trust cryptographic software? Cryptographic flaws + in Gnu privacy guard 1.2.3”, Eurocrypt 2004, + https://www.iacr.org/archive/eurocrypt2004/30270550/ProcEC04.pdf + +[O90]: A. M. Odlyzko, "The rise and fall of knapsack cryptosystems", Cryptology + and Computational Number Theory, pp.75-88, 1990 + +[DSS]: FIPS PUB 186-4, "Digital Signature Standard (DSS)", National Institute + of Standards and Technology, July 2013 + http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf diff --git a/doc/ecdh.md b/doc/ecdh.md new file mode 100644 index 0000000..c86b140 --- /dev/null +++ b/doc/ecdh.md @@ -0,0 +1,58 @@ + +# ECDH + +[TOC] + +##ECDH description: +See https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman + +##Bugs +Some libraries do not check if the elliptic curve points received from another +party are points on the curve. Encodings of public keys typically contain the +curve for the public key point. If such an encoding is used in the key exchange +then it is important to check that the public and secret key used to compute +the shared ECDH secret are using the same curve. +Some libraries fail to do this check. + +**Potential exploits:** +The damage done depends on the protocol that uses ECDH. E.g. if ECDH is used +with ephemeral keys then the damage is typically limited. If the EC keys are +static, i.e. used for multiple key exchanges then a failure to verify a public +point can disclose the private key used in the same protocol. +(To do: add papers describing the attack). + +##Libraries +**Sun JCE provider:** +ECDH does not check if the points are on the curve. +The implementer must do this. + +**Bouncycastle:** +The ECDH implementation does not check if the point is on the curve. +Furthermore, Bouncycastle does not even check if the public and private key are +on the same curve. It performs a point multiplication \\(x \cdot Y\\) over the +curve specified by the public key. + +**OpenSSL:** +Point verification is done in OpenSSL if the right functions are used. +Since OpenSSL is not well documented it is a bit tricky to find the right +functions. +(To do: maybe add an example). + +##Countermeasures +TODO: +* use point compression. Formats such as X509EncodedKeySpec +in Java include bits that indicate whether the point is compressed or not. +Hence an attacker can always choose to use uncompressed points as long as this +option is incorrectly implemented. +* check that public and private key use the same curve +* restrict the protocol to named curves +* reconstruct the public key explicitly using the parameters of the private + key. + +**Further recommendations:** +If possible I also check if the points are on the curve after point +multiplications on an elliptic curve in the hope to catch implementation +and hardware faults. + +## Some notable bugs: +* ECDHC in bouncy castle could be broken by modifying the order of the public key. diff --git a/doc/index.md b/doc/index.md new file mode 100644 index 0000000..9fe48b3 --- /dev/null +++ b/doc/index.md @@ -0,0 +1,80 @@ +# Project Wycheproof + +This page describes the goals and strategies of project Wycheproof. See +[README](../README.md) for an introduction to the project. + +## Defense in depth + +There are a number of tests where we check for expected behaviour +rather than exploitability. Examples: + +* default values: we expect that default values are reasonable and correspond + to recommendations by current standards. Concretely, in 2016 it is not OK + if an RSA key generation uses 1024 bits as default or digital signatures + use SHA-1 as default. +* timing attacks: any timing that relation between keys (or other sensitive) + data and the measured time fails the test. However tests are set up + such that too much noise during the test can prevent that a relation + is detected. +* wrong exceptions: The JCE interface often specifies the exceptions that + should be thrown when the input is invalid. We expect the specified + exceptions in the tests. +* leaking information through exceptions: While it is a good practice to not + return detailed logs to a sender, we consider text in exceptions as + information that a potential attacker can learn. For example padding + failures during decryption should not contain information about the + reason why a decryption failed. +* RSA PKCS #1 signatures: If a signature verification allows signatures + with lots of modifications, then RSA signatures can be forged for small + public exponents. Tests do not measure how many bytes can be modified. + Any accepted modification of the PKCS #1 padding fails the test. + +## Compatibility between providers + +One of the goals of Wycheproof is to test for compatibility issues. +Switching JCE providers should not introduce vulnerabilities simply because +the solution was developed by another provider. + +An example for this was the following observation: When using AES-GCM then +javax.crypto.CipherInputStream worked sort of with JCE and +org.bouncycastle.jcajce.io.CipherInputStream.java worked with BouncyCastle. +However, authentication was skipped in some cases when +javax.crypto.CipherInputStream was used with BouncyCastle. + +## Comparing cryptographic libraries is not a primary goal + +Because of the strategies mentioned above we expect that a comparison of +cryptographic libraries based on the bugs found would be biased: + +* Libraries used internally in Google get more attention. + Serious vulnerabilities in these libraries should be fixed at the time the + tests are added to Wycheproof. On the other hand it is also likely that + tests find a larger number of bugs in these libraries when old versions are + tested. +* Tests often check for expected behaviour and compatibility. + Expected behaviour is often defined by a prominent library. + Pointing out such problems can therefore penalize smaller third party + libraries. +* We are working toward covering as many potential vulnerabilities as possible + with test vectors, because this simplifies porting the tests to other + languages or interfaces. Thus a single test case can cover multiple + vulnerabilities. + +We are not trying to remove this bias when this interferes with more important +goals such as early reporting. +Hence we are reluctant to publish comparisons. + + +## Thoughts on the design of cryptographic libraries + +We should promote robust interfaces with the goal to simplify +the use of the library, code reviews of applications using the +library and testing the library. + +* When cryptographic primitives require randomness then the random + numbers should be chosen by the library. It shouldn't be possible + for a user to provide randomness. If the library itself chooses the + randomness then it is possible (at least to some degree) to check + that the random number generation is appropriate for the primitive. + If the user can provide the randomness then it is not possible to + catch this in our tests. diff --git a/doc/rsa.md b/doc/rsa.md new file mode 100644 index 0000000..b1f47c5 --- /dev/null +++ b/doc/rsa.md @@ -0,0 +1,131 @@ +# RSA + +[TOC] + +## RSA key generation + +**Default size:** If a library supports a key default size for RSA keys then +this key size should be at least 2048 bits. This limit is based on the minimum +recommendation of [NIST SP 800-57] part1 revision 4, Table 2, page 53. NIST +recommends a minimal security strength of 112 bits for keys used until 2030. 112 +bit security strength translates to a minimal key size of 2048 bits. Other +organizations recommend somewhat different sizes: [Enisa], Section 3.6 also +suggests that 2048-bit RSA keys provide a security strength of about 112 bits, +but recommends a security strength of 128 bits for near term systems, hence 3072 +bit RSA keys. [ECRYPT II], Section 13.3 suggests at least 2432 bits for new +keys. + +All the references above clearly state that keys smaller than 2048 bits should +only be used in legacy cases. Therefore, it seems wrong to use a default key +size smaller than 2048 bits. If a user really wants a small RSA key then such a +choice should be made by explicitly providing the desired key length during the +initalization of a key pair generator. + +According to https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html +every implementation of the Java platform is required to implement RSA with both +1024 and 2048 bit key sizes. Hence a 2048 bit default should not lead to +compatibility problems. + +**Cryptographically strong random numbers:** +So far the tests check that java.util.Random is not used. This needs to be +extended. + +**Other bugs:** +The public exponent e should be larger than 1 [CVE-1999-1444] + +## RSA PKCS #1 v1.5 encryption + +PKCS #1 v1.5 padding is susceptible to adaptive chosen ciphertext attacks and +hence should be avoided [B98]. The difficulty of exploiting protocols using +PKCS #1 v1.5 encryption often depends on the amount of information leaked after +decrypting corrupt ciphertexts. Implementations frequently leak information +about the decrypted plaintext in form of error messages. The content of the +error messages are extremely helpful to potential attackers. Bardou et al. +[BFKLSST12] analyze the difficult of attacks based on different types of +information leakage. Smart even describes an attack that only needs about 40 +chosen ciphertexts [S10], though in this case the encryption did not use PKCS #1 +padding. + +**Bugs** + +* Bouncycastle throws detailed exceptions: + InvalidCipherTextException("unknown block type") or + InvalidCipherTextException("block padding incorrect"). + +<!-- the SUN provider used to include that block type --> + +**Tests** To test whether an implementation leaks more information than +necessary a test decrypts some random ciphertexts and catches the exceptions. If +the exceptions are distinguishable then the test assumes that unnecessary +information about the padding is leaked. + +Due to the nature of unit tests not every attack can be detected this way. Some +attacks require a large number of ciphertexts to be detected if random +ciphertexts are used. For example Klima et al. [KPR03] describe an +implementation flaw that could not be detected with our test. + +Timing leakages because of differences in parsing the padding can leak +information (e.g. CVE-2015-7827). Such differences are too small to be reliably +detectable in unit tests. + +## RSA OAEP + +Manger describes an chosen ciphertext attack against RSA in [M01]. There are +implementations that were susceptible to Mangers attack, e.g. [CVE-2012-5081]. + +## RSA PKCS1 signatures +**Potential problems:** + +* Some libraries parse PKCS#1 padding during signature verification + incorrectly. +* Some libraries determine the hash function from the signature (rather than + encoding this in the key) Effect: +* If the verification is buggy then an attacker might be able to generate + signatures for keys with a small (i.e. e=3) public exponent. +* If the hash algorithm is not determined by in an authentic manner then + preimage attacks against weak hashes are possible, even if the hashes are + not used by the signer. + +**Countermeasures:** A good way to implement RSA signature verification is +described in the standard PKCS#1 v.2.2 Section 8.2.2. This standard proposes to +reconstruct the padding during verification and compare the padded hash to the +value $$s^e \bmod n$$ obtained from applying a public key exponentiation to the +signature s. Since this is a recurring bug it makes also a lot of sense to avoid +small public exponents and prefer for example e=65537 . + +**List of broken implementations** +This is a large list. + +## References + +\[B98]: D. Bleichenbacher, "Chosen ciphertext attacks against protocols based on +the RSA encryption standard PKCS# 1" Crypto 98 + +\[M01]: J. Manger, "A chosen ciphertext attack on RSA optimal asymmetric +encryption padding (OAEP) as standardized in PKCS# 1 v2.0", Crypto 2001 This +paper shows that OAEP is susceptible to a chosen ciphertext attack if error +messages distinguish between different failure condidtions. [S10]: N. Smart, +"Errors matter: Breaking RSA-based PIN encryption with thirty ciphertext +validity queries" RSA conference, 2010 This paper shows that padding oracle +attacks can be successful with even a small number of queries. + +\[KPR03]: V. Klima, O. Pokorny, and T. Rosa, "Attacking RSA-based Sessions in +SSL/TLS" https://eprint.iacr.org/2003/052/ + +\[BFKLSST12]: "Efficient padding oracle attacks on cryptographic hardware" R. +Bardou, R. Focardi, Y. Kawamoto, L. Simionato, G. Steel, J.K. Tsay, Crypto 2012 + +\[NIST SP 800-57]: +http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf + +\[Enisa]: "Algorithms, key size and parameters report – 2014" +https://www.enisa.europa.eu/publications/algorithms-key-size-and-parameters-report-2014 + +\[ECRYPT II]: Yearly Report on Algorithms and Keysizes (2011-2012), +http://www.ecrypt.eu.org/ecrypt2/documents/D.SPA.20.pdf + +\[CVE-1999-1444]: Alibaba 2.0 generated RSA key pairs with an exponent 1 + +\[CVE-2012-5081]: Java JSSE provider leaked information through exceptions and +timing. Both the PKCS #1 padding and the OAEP padding were broken: +http://www-brs.ub.ruhr-uni-bochum.de/netahtml/HSS/Diss/MeyerChristopher/diss.pdf diff --git a/java/com/google/security/wycheproof/BouncyCastleAllTests.java b/java/com/google/security/wycheproof/BouncyCastleAllTests.java new file mode 100644 index 0000000..47a4dcf --- /dev/null +++ b/java/com/google/security/wycheproof/BouncyCastleAllTests.java @@ -0,0 +1,53 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; + +/** + * BouncyCastleAllTests runs all tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesEaxTest.class, + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + DhTest.class, + DhiesTest.class, + DsaTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + EciesTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class, +}) +@Provider(ProviderType.BOUNCY_CASTLE) +public final class BouncyCastleAllTests { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyThisProvider(new BouncyCastleProvider()); + } +} diff --git a/java/com/google/security/wycheproof/BouncyCastleTest.java b/java/com/google/security/wycheproof/BouncyCastleTest.java new file mode 100644 index 0000000..941b94f --- /dev/null +++ b/java/com/google/security/wycheproof/BouncyCastleTest.java @@ -0,0 +1,55 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Fast; +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; + +/** + * BouncyCastleTest excludes {@code @SlowTest} tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesEaxTest.class, + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + DhTest.class, + DhiesTest.class, + DsaTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + EciesTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class, +}) +@Provider(ProviderType.BOUNCY_CASTLE) +@Fast +public final class BouncyCastleTest { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyThisProvider(new BouncyCastleProvider()); + } +} diff --git a/java/com/google/security/wycheproof/ConscryptTest.java b/java/com/google/security/wycheproof/ConscryptTest.java new file mode 100644 index 0000000..c4f58d5 --- /dev/null +++ b/java/com/google/security/wycheproof/ConscryptTest.java @@ -0,0 +1,51 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Fast; +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.conscrypt.OpenSSLProvider; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Conscrypt is a Java security provider that uses OpenSSL. See {@link https://conscrypt.org/}. + * ConscryptTest excludes {@code @SlowTest} tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class +}) +@Provider(ProviderType.CONSCRYPT) +@Fast +public final class ConscryptTest { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyThisProvider(new OpenSSLProvider()); + } +} diff --git a/java/com/google/security/wycheproof/EcUtil.java b/java/com/google/security/wycheproof/EcUtil.java new file mode 100644 index 0000000..f464cba --- /dev/null +++ b/java/com/google/security/wycheproof/EcUtil.java @@ -0,0 +1,454 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECField; +import java.security.spec.ECFieldFp; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; +import java.security.spec.InvalidParameterSpecException; +import java.util.Arrays; + +/** + * Some utilities for testing Elliptic curve crypto. This code is for testing only and hasn't been + * reviewed for production. + */ +public class EcUtil { + /** + * Returns the ECParameterSpec for a named curve. Not every provider implements the + * AlgorithmParameters. Therefore, most test use alternative functions. + */ + public static ECParameterSpec getCurveSpec(String name) + throws NoSuchAlgorithmException, InvalidParameterSpecException { + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); + parameters.init(new ECGenParameterSpec(name)); + return parameters.getParameterSpec(ECParameterSpec.class); + } + + /** + * Returns the ECParameterSpec for a named curve. Only a handful curves that are used in the tests + * are implemented. + */ + public static ECParameterSpec getCurveSpecRef(String name) throws NoSuchAlgorithmException { + if (name.equals("secp224r1")) { + return getNistP224Params(); + } else if (name.equals("secp256r1")) { + return getNistP256Params(); + } else if (name.equals("secp384r1")) { + return getNistP384Params(); + } else if (name.equals("secp521r1")) { + return getNistP521Params(); + } else if (name.equals("brainpoolp256r1")) { + return getBrainpoolP256r1Params(); + } else { + throw new NoSuchAlgorithmException("Curve not implemented:" + name); + } + } + + public static ECParameterSpec getNistCurveSpec( + String decimalP, String decimalN, String hexB, String hexGX, String hexGY) { + final BigInteger p = new BigInteger(decimalP); + final BigInteger n = new BigInteger(decimalN); + final BigInteger three = new BigInteger("3"); + final BigInteger a = p.subtract(three); + final BigInteger b = new BigInteger(hexB, 16); + final BigInteger gx = new BigInteger(hexGX, 16); + final BigInteger gy = new BigInteger(hexGY, 16); + final int h = 1; + ECFieldFp fp = new ECFieldFp(p); + java.security.spec.EllipticCurve curveSpec = new java.security.spec.EllipticCurve(fp, a, b); + ECPoint g = new ECPoint(gx, gy); + ECParameterSpec ecSpec = new ECParameterSpec(curveSpec, g, n, h); + return ecSpec; + } + + public static ECParameterSpec getNistP224Params() { + return getNistCurveSpec( + "26959946667150639794667015087019630673557916260026308143510066298881", + "26959946667150639794667015087019625940457807714424391721682722368061", + "b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", + "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"); + } + + public static ECParameterSpec getNistP256Params() { + return getNistCurveSpec( + "115792089210356248762697446949407573530086143415290314195533631308867097853951", + "115792089210356248762697446949407573529996955224135760342422259061068512044369", + "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"); + } + + public static ECParameterSpec getNistP384Params() { + return getNistCurveSpec( + "3940200619639447921227904010014361380507973927046544666794829340" + + "4245721771496870329047266088258938001861606973112319", + "3940200619639447921227904010014361380507973927046544666794690527" + + "9627659399113263569398956308152294913554433653942643", + "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a" + + "c656398d8a2ed19d2a85c8edd3ec2aef", + "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38" + + "5502f25dbf55296c3a545e3872760ab7", + "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0" + + "0a60b1ce1d7e819d7a431d7c90ea0e5f"); + } + + public static ECParameterSpec getNistP521Params() { + return getNistCurveSpec( + "6864797660130609714981900799081393217269435300143305409394463459" + + "18554318339765605212255964066145455497729631139148085803712198" + + "7999716643812574028291115057151", + "6864797660130609714981900799081393217269435300143305409394463459" + + "18554318339765539424505774633321719753296399637136332111386476" + + "8612440380340372808892707005449", + "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10" + + "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d" + + "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", + "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6" + + "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"); + } + + public static ECParameterSpec getBrainpoolP256r1Params() { + BigInteger p = + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16); + BigInteger a = + new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16); + BigInteger b = + new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16); + BigInteger x = + new BigInteger("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16); + BigInteger y = + new BigInteger("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16); + BigInteger n = + new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16); + final int h = 1; + ECFieldFp fp = new ECFieldFp(p); + EllipticCurve curve = new EllipticCurve(fp, a, b); + ECPoint g = new ECPoint(x, y); + return new ECParameterSpec(curve, g, n, h); + } + + /** + * Compute the Legendre symbol of x mod p. This implementation is slow. Faster would be the + * computation for the Jacobi symbol. + * + * @param x an integer + * @param p a prime modulus + * @returns 1 if x is a quadratic residue, -1 if x is a non-quadratic residue and 0 if x and p are + * not coprime. + * @throws GeneralSecurityException when the computation shows that p is not prime. + */ + public static int legendre(BigInteger x, BigInteger p) throws GeneralSecurityException { + BigInteger q = p.subtract(BigInteger.ONE).shiftRight(1); + BigInteger t = x.modPow(q, p); + if (t.equals(BigInteger.ONE)) { + return 1; + } else if (t.equals(BigInteger.ZERO)) { + return 0; + } else if (t.add(BigInteger.ONE).equals(p)) { + return -1; + } else { + throw new GeneralSecurityException("p is not prime"); + } + } + + /** + * Computes a modular square root. Timing and exceptions can leak information about the inputs. + * Therefore this method must only be used in tests. + * + * @param x the square + * @param p the prime modulus + * @returns a value s such that s^2 mod p == x mod p + * @throws GeneralSecurityException if the square root could not be found. + */ + public static BigInteger modSqrt(BigInteger x, BigInteger p) throws GeneralSecurityException { + if (p.signum() != 1) { + throw new GeneralSecurityException("p must be positive"); + } + x = x.mod(p); + BigInteger squareRoot = null; + // Special case for x == 0. + // This check is necessary for Cipolla's algorithm. + if (x.equals(BigInteger.ZERO)) { + return x; + } + if (p.testBit(0) && p.testBit(1)) { + // Case p % 4 == 3 + // q = (p + 1) / 4 + BigInteger q = p.add(BigInteger.ONE).shiftRight(2); + squareRoot = x.modPow(q, p); + } else if (p.testBit(0) && !p.testBit(1)) { + // Case p % 4 == 1 + // For this case we use Cipolla's algorithm. + // This alogorithm is preferrable to Tonelli-Shanks for primes p where p-1 is divisible by + // a large power of 2, which is a frequent choice since it simplifies modular reduction. + BigInteger a = BigInteger.ONE; + BigInteger d = null; + while (true) { + d = a.multiply(a).subtract(x).mod(p); + // Computes the Legendre symbol. Using the Jacobi symbol would be a faster. Using Legendre + // has the advantage, that it detects a non prime p with high probability. + // On the other hand if p = q^2 then the Jacobi (d/p)==1 for almost all d's and thus + // using the Jacobi symbol here can result in an endless loop with invalid inputs. + int t = legendre(d, p); + if (t == -1) { + break; + } else { + a = a.add(BigInteger.ONE); + } + } + // Since d = a^2 - n is a non-residue modulo p, we have + // a - sqrt(d) == (a+sqrt(d))^p (mod p), + // and hence + // n == (a + sqrt(d))(a - sqrt(d) == (a+sqrt(d))^(p+1) (mod p). + // Thus if n is square then (a+sqrt(d))^((p+1)/2) (mod p) is a square root of n. + BigInteger q = p.add(BigInteger.ONE).shiftRight(1); + BigInteger u = a; + BigInteger v = BigInteger.ONE; + for (int bit = q.bitLength() - 2; bit >= 0; bit--) { + // Compute (u + v sqrt(d))^2 + BigInteger tmp = u.multiply(v); + u = u.multiply(u).add(v.multiply(v).mod(p).multiply(d)).mod(p); + v = tmp.add(tmp).mod(p); + if (q.testBit(bit)) { + tmp = u.multiply(a).add(v.multiply(d)).mod(p); + v = a.multiply(v).add(u).mod(p); + u = tmp; + } + } + squareRoot = u; + } + // The methods used to compute the square root only guarantee a correct result if the + // preconditions (i.e. p prime and x is a square) are satisfied. Otherwise the value is + // undefined. Hence, it is important to verify that squareRoot is indeed a square root. + if (squareRoot != null && squareRoot.multiply(squareRoot).mod(p).compareTo(x) != 0) { + throw new GeneralSecurityException("Could not find square root"); + } + return squareRoot; + } + + /** + * Returns the modulus of the field used by the curve specified in ecParams. + * + * @param curve must be a prime order elliptic curve + * @return the order of the finite field over which curve is defined. + */ + public static BigInteger getModulus(EllipticCurve curve) throws GeneralSecurityException { + java.security.spec.ECField field = curve.getField(); + if (field instanceof java.security.spec.ECFieldFp) { + return ((java.security.spec.ECFieldFp) field).getP(); + } else { + throw new GeneralSecurityException("Only curves over prime order fields are supported"); + } + } + + /** + * Returns the size of an element of the field over which the curve is defined. + * + * @param curve must be a prime order elliptic curve + * @return the size of an element in bits + */ + public static int fieldSizeInBits(EllipticCurve curve) throws GeneralSecurityException { + return getModulus(curve).subtract(BigInteger.ONE).bitLength(); + } + + /** + * Returns the size of an element of the field over which the curve is defined. + * + * @param curve must be a prime order elliptic curve + * @return the size of an element in bytes. + */ + public static int fieldSizeInBytes(EllipticCurve curve) throws GeneralSecurityException { + return (fieldSizeInBits(curve) + 7) / 8; + } + + /** + * Checks that a point is on a given elliptic curve. This method implements the partial public key + * validation routine from Section 5.6.2.6 of NIST SP 800-56A + * http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf A partial + * public key validation is sufficient for curves with cofactor 1. See Section B.3 of + * http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf The point validations above are + * taken from recommendations for ECDH, because parameter checks in ECDH are much more important + * than for the case of ECDSA. Performing this test for ECDSA keys is mainly a sanity check. + * + * @param point the point that needs verification + * @param ec the elliptic curve. This must be a curve over a prime order field. + * @throws GeneralSecurityException if the field is binary or if the point is not on the curve. + */ + public static void checkPointOnCurve(ECPoint point, EllipticCurve ec) + throws GeneralSecurityException { + BigInteger p = getModulus(ec); + BigInteger x = point.getAffineX(); + BigInteger y = point.getAffineY(); + if (x == null || y == null) { + throw new GeneralSecurityException("point is at infinity"); + } + // Check 0 <= x < p and 0 <= y < p. + if (x.signum() == -1 || x.compareTo(p) != -1) { + throw new GeneralSecurityException("x is out of range"); + } + if (y.signum() == -1 || y.compareTo(p) != -1) { + throw new GeneralSecurityException("y is out of range"); + } + // Check y^2 == x^3 + a x + b (mod p) + BigInteger lhs = y.multiply(y).mod(p); + BigInteger rhs = x.multiply(x).add(ec.getA()).multiply(x).add(ec.getB()).mod(p); + if (!lhs.equals(rhs)) { + throw new GeneralSecurityException("Point is not on curve"); + } + } + + /** + * Checks a public key. I.e. this checks that the point defining the public key is on the curve. + * + * @param key must be a key defined over a curve using a prime order field. + * @throws GeneralSecurityException if the key is not valid. + */ + public static void checkPublicKey(ECPublicKey key) throws GeneralSecurityException { + checkPointOnCurve(key.getW(), key.getParams().getCurve()); + } + + /** + * Decompress a point + * + * @param x The x-coordinate of the point + * @param bit0 true if the least significant bit of y is set. + * @param ecParams contains the curve of the point. This must be over a prime order field. + */ + public static ECPoint getPoint(BigInteger x, boolean bit0, ECParameterSpec ecParams) + throws GeneralSecurityException { + EllipticCurve ec = ecParams.getCurve(); + ECField field = ec.getField(); + if (!(field instanceof ECFieldFp)) { + throw new GeneralSecurityException("Only curves over prime order fields are supported"); + } + BigInteger p = ((java.security.spec.ECFieldFp) field).getP(); + if (x.compareTo(BigInteger.ZERO) == -1 || x.compareTo(p) != -1) { + throw new GeneralSecurityException("x is out of range"); + } + // Compute rhs == x^3 + a x + b (mod p) + BigInteger rhs = x.multiply(x).add(ec.getA()).multiply(x).add(ec.getB()).mod(p); + BigInteger y = modSqrt(rhs, p); + if (bit0 != y.testBit(0)) { + y = p.subtract(y).mod(p); + } + return new ECPoint(x, y); + } + + /** + * Decompress a point on an elliptic curve. + * + * @param bytes The compressed point. Its representation is z || x where z is 2+lsb(y) and x is + * using a unsigned fixed length big-endian representation. + * @param ecParams the specification of the curve. Only Weierstrass curves over prime order fields + * are implemented. + */ + public static ECPoint decompressPoint(byte[] bytes, ECParameterSpec ecParams) + throws GeneralSecurityException { + EllipticCurve ec = ecParams.getCurve(); + ECField field = ec.getField(); + if (!(field instanceof ECFieldFp)) { + throw new GeneralSecurityException("Only curves over prime order fields are supported"); + } + BigInteger p = ((java.security.spec.ECFieldFp) field).getP(); + int expectedLength = 1 + (p.bitLength() + 7) / 8; + if (bytes.length != expectedLength) { + throw new GeneralSecurityException("compressed point has wrong length"); + } + boolean lsb; + switch (bytes[0]) { + case 2: + lsb = false; + break; + case 3: + lsb = true; + break; + default: + throw new GeneralSecurityException("Invalid format"); + } + BigInteger x = new BigInteger(1, Arrays.copyOfRange(bytes, 1, bytes.length)); + if (x.compareTo(BigInteger.ZERO) == -1 || x.compareTo(p) != -1) { + throw new GeneralSecurityException("x is out of range"); + } + // Compute rhs == x^3 + a x + b (mod p) + BigInteger rhs = x.multiply(x).add(ec.getA()).multiply(x).add(ec.getB()).mod(p); + BigInteger y = modSqrt(rhs, p); + if (lsb != y.testBit(0)) { + y = p.subtract(y).mod(p); + } + return new ECPoint(x, y); + } + + /** + * Returns a weak public key of order 3 such that the public key point is on the curve specified + * in ecParams. This method is used to check ECC implementations for missing step in the + * verification of the public key. E.g. implementations of ECDH must verify that the public key + * contains a point on the curve as well as public and secret key are using the same curve. + * + * @param ecParams the parameters of the key to attack. This must be a curve in Weierstrass form + * over a prime order field. + * @return a weak EC group with a genrator of order 3. + */ + public static ECPublicKeySpec getWeakPublicKey(ECParameterSpec ecParams) + throws GeneralSecurityException { + EllipticCurve curve = ecParams.getCurve(); + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + keyGen.initialize(ecParams); + BigInteger p = getModulus(curve); + BigInteger three = new BigInteger("3"); + while (true) { + // Generate a point on the original curve + KeyPair keyPair = keyGen.generateKeyPair(); + ECPublicKey pub = (ECPublicKey) keyPair.getPublic(); + ECPoint w = pub.getW(); + BigInteger x = w.getAffineX(); + BigInteger y = w.getAffineY(); + // Find the curve parameters a,b such that 3*w = infinity. + // This is the case if the following equations are satisfied: + // 3x == l^2 (mod p) + // l == (3x^2 + a) / 2*y (mod p) + // y^2 == x^3 + ax + b (mod p) + BigInteger l; + try { + l = modSqrt(x.multiply(three), p); + } catch (GeneralSecurityException ex) { + continue; + } + BigInteger xSqr = x.multiply(x).mod(p); + BigInteger a = l.multiply(y.add(y)).subtract(xSqr.multiply(three)).mod(p); + BigInteger b = y.multiply(y).subtract(x.multiply(xSqr.add(a))).mod(p); + EllipticCurve newCurve = new EllipticCurve(curve.getField(), a, b); + // Just a sanity check. + checkPointOnCurve(w, newCurve); + // Cofactor and order are of course wrong. + ECParameterSpec spec = new ECParameterSpec(newCurve, w, p, 1); + return new ECPublicKeySpec(w, spec); + } + } +} diff --git a/java/com/google/security/wycheproof/OpenJDKAllTests.java b/java/com/google/security/wycheproof/OpenJDKAllTests.java new file mode 100644 index 0000000..a2b3b06 --- /dev/null +++ b/java/com/google/security/wycheproof/OpenJDKAllTests.java @@ -0,0 +1,34 @@ +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Tests for OpenJDK's providers: SunJCE, SunEC, etc. + * OpenJDKAllTests runs all tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + DhTest.class, + DsaTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class +}) +@Provider(ProviderType.OPENJDK) +public final class OpenJDKAllTests { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyOpenJDKProviders(); + } +} diff --git a/java/com/google/security/wycheproof/OpenJDKTest.java b/java/com/google/security/wycheproof/OpenJDKTest.java new file mode 100644 index 0000000..b326fef --- /dev/null +++ b/java/com/google/security/wycheproof/OpenJDKTest.java @@ -0,0 +1,36 @@ +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Fast; +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Tests for OpenJDK's providers: SunJCE, SunEC, etc. + * OpenJDKTest excludes slow tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + DhTest.class, + DsaTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class +}) +@Provider(ProviderType.OPENJDK) +@Fast +public final class OpenJDKTest { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyOpenJDKProviders(); + } +} diff --git a/java/com/google/security/wycheproof/ProviderIndependentTest.java b/java/com/google/security/wycheproof/ProviderIndependentTest.java new file mode 100644 index 0000000..931fc64 --- /dev/null +++ b/java/com/google/security/wycheproof/ProviderIndependentTest.java @@ -0,0 +1,26 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** Provider independent tests */ +@RunWith(Suite.class) +@SuiteClasses({BigIntegerTest.class}) +public final class ProviderIndependentTest {} diff --git a/java/com/google/security/wycheproof/RandomUtil.java b/java/com/google/security/wycheproof/RandomUtil.java new file mode 100644 index 0000000..388c272 --- /dev/null +++ b/java/com/google/security/wycheproof/RandomUtil.java @@ -0,0 +1,185 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.util.Random; + +/** + * A collection of utilities for testing random number generators. So far this util simply checks + * that random numbers are not generated by java.util.Random. Eventually we plan to add detection + * for other random number generators too. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +public class RandomUtil { + // Constants for java.util.Random; + static final long A = 0x5DEECE66DL; + static final long A_INVERSE = 246154705703781L; + static final long C = 0xBL; + + /** Given a state of a java.util.Random object compute the next state. */ + protected static long nextState(long seed) { + return (seed * A + C) & ((1L << 48) - 1); + } + + /** Give the state after stepping java.util.Random n times. */ + protected static long step(long seed, long n) { + long a = A; + long c = C; + n = n & 0xffffffffffffL; + while (n != 0) { + if ((n & 1) == 1) { + seed = seed * a + c; + } + c = c * (a + 1); + a = a * a; + n = n >> 1; + } + return seed & 0xffffffffffffL; + } + + /** Given a state of a java.util.Random object compute the previous state. */ + protected static long previousState(long seed) { + return ((seed - C) * A_INVERSE) & ((1L << 48) - 1); + } + + /** Computes a seed that would initialize a java.util.Random object with a given state. */ + protected static long getSeedForState(long seed) { + return seed ^ A; + } + + protected static long getStateForSeed(long seed) { + return (seed ^ A) & 0xffffffffffffL; + } + + /** + * Given two subsequent outputs x0 and x1 from java.util.Random this function computes the + * internal state of java.util.Random after returning x0 or returns -1 if no such state exists. + */ + protected static long getState(int x0, int x1) { + long mask = (1L << 48) - 1; + long multiplier = A; + // The state of the random number generator after returning x0 is + // l0 + eps for some 0 <= eps < 2**16. + long l0 = ((long) x0 << 16) & mask; + // The state of the random number generator after returning x1 is + // l1 + delta for some 0 <= delta < 2**16. + long l1 = ((long) x1 << 16) & mask; + // We have l1 + delta = (l0 + eps)*multiplier + 0xBL (mod 2**48). + // This allows to find an upper bound w for eps * multiplier mod 2**48 + // by assuming delta = 2**16-1. + long w = (l1 - l0 * multiplier + 65535L - 0xBL) & mask; + // The reduction eps * multiplier mod 2**48 only cuts off at most 3 bits. + // Hence a simple search is sufficient. The maximal number of loops is 6. + for (long em = w; em < (multiplier << 16); em += 1L << 48) { + // If the high order bits of em are guessed correctly then + // em == eps * multiplier + 65535 - delta. + long eps = em / multiplier; + long state0 = l0 + eps; + long state1 = nextState(state0); + if ((state1 & 0xffffffff0000L) == l1) { + return state0; + } + } + return -1; + } + + /** + * Find a seed such that this integer is the result of + * + * <pre>{@code + * Random rand = new Random(); + * rand.setSeed(seed); + * return new BigInteger(k, rand); + * }</pre> + * + * where k is max(64, x.BitLength()); + * + * <p>Returns -1 if no such seed exists. + */ + // TODO(bleichen): We want to detect cases where some of the bits + // (i.e. most significant bits or least significant bits have + // been modified. Often this happens during the generation + // of primes or other things. + // TODO(bleichen): This method is incomplete. + protected static long getSeedFor(java.math.BigInteger x) { + byte[] bytes = x.toByteArray(); + if (bytes.length == 0) { + return -1; + } + ByteBuffer buffer = ByteBuffer.allocate(8); + int offset = bytes[0] == 0 ? 1 : 0; + if (bytes.length - offset < 8) { + int size = bytes.length - offset; + buffer.position(8 - size); + buffer.put(bytes, offset, size); + } else { + buffer.put(bytes, offset, 8); + } + buffer.flip(); + buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN); + int x0 = buffer.getInt(); + int x1 = buffer.getInt(); + long state = getState(x0, x1); + if (state == -1) { + return -1; + } + return getSeedForState(previousState(state)); + } + + /** Attempts to find a seed such that it generates the prime p. Returns -1 if no seed is found. */ + static long getSeedForPrime(BigInteger p) { + int confidence = 64; + Random rand = new Random(); + int size = p.bitLength(); + // Prime generation often sets the most significant bit. + // Hence, clearing the most significant bit can help to find + // the seed used for the prime generation. + for (BigInteger x : new BigInteger[] {p, p.clearBit(size - 1)}) { + long seed = getSeedFor(x); + if (seed != -1) { + rand.setSeed(seed); + BigInteger q = new BigInteger(size, confidence, rand); + if (q.equals(p)) { + return seed; + } + } + } + return -1; + } + + /** + * Checks whether p is a random prime. A prime generated with a secure random number generator + * passes with probability > 1-2^{-32}. No checks are performed for primes smaller than 96 bits. + * + * @throws GeneralSecurityException if the prime was generated using java.util.Random + */ + static void checkPrime(BigInteger p) throws GeneralSecurityException { + // We can't reliably detect java.util.Random for small primes. + if (p.bitLength() < 96) { + return; + } + long seed = getSeedForPrime(p); + if (seed != -1) { + throw new GeneralSecurityException( + "java.util.Random with seed " + seed + " was likely used to generate prime"); + } + } +} diff --git a/java/com/google/security/wycheproof/SpongyCastleAllTests.java b/java/com/google/security/wycheproof/SpongyCastleAllTests.java new file mode 100644 index 0000000..5566827 --- /dev/null +++ b/java/com/google/security/wycheproof/SpongyCastleAllTests.java @@ -0,0 +1,54 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; +import org.spongycastle.jce.provider.BouncyCastleProvider; + +/** + * SpongyCastleTest excludes {@code @SlowTest} tests. + * SpongyCastleAllTests runs all tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesEaxTest.class, + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + DhTest.class, + DhiesTest.class, + DsaTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + EciesTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class, +}) +@Provider(ProviderType.SPONGY_CASTLE) +public final class SpongyCastleAllTests { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyThisProvider(new BouncyCastleProvider()); + } +} diff --git a/java/com/google/security/wycheproof/SpongyCastleTest.java b/java/com/google/security/wycheproof/SpongyCastleTest.java new file mode 100644 index 0000000..73c8ca1 --- /dev/null +++ b/java/com/google/security/wycheproof/SpongyCastleTest.java @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.Fast; +import com.google.security.wycheproof.WycheproofRunner.Provider; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite.SuiteClasses; +import org.spongycastle.jce.provider.BouncyCastleProvider; + +/** + * Spongy Castle is a Bouncy Castle clone with a few changes to make it work on Android. + * SpongyCastleTest excludes {@code @SlowTest} tests. + */ +@RunWith(WycheproofRunner.class) +@SuiteClasses({ + AesEaxTest.class, + AesGcmTest.class, + BasicTest.class, + CipherInputStreamTest.class, + CipherOutputStreamTest.class, + DhTest.class, + DhiesTest.class, + DsaTest.class, + EcKeyTest.class, + EcdhTest.class, + EcdsaTest.class, + EciesTest.class, + RsaEncryptionTest.class, + RsaKeyTest.class, + RsaSignatureTest.class, +}) +@Provider(ProviderType.SPONGY_CASTLE) +@Fast +public final class SpongyCastleTest { + @BeforeClass + public static void setUp() throws Exception { + TestUtil.installOnlyThisProvider(new BouncyCastleProvider()); + } +} diff --git a/java/com/google/security/wycheproof/TestUtil.java b/java/com/google/security/wycheproof/TestUtil.java new file mode 100644 index 0000000..ae21adc --- /dev/null +++ b/java/com/google/security/wycheproof/TestUtil.java @@ -0,0 +1,99 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.nio.ByteBuffer; +import java.security.Provider; +import java.security.Security; + +/** Test utilities */ +public class TestUtil { + + public static String bytesToHex(byte[] bytes) { + // bytesToHex is used to convert output from Cipher. + // cipher.update can return null, which is equivalent to returning + // no plaitext rsp. ciphertext. + if (bytes == null) { + return ""; + } + String chars = "0123456789abcdef"; + StringBuilder result = new StringBuilder(2 * bytes.length); + for (byte b : bytes) { + // convert to unsigned + int val = b & 0xff; + result.append(chars.charAt(val / 16)); + result.append(chars.charAt(val % 16)); + } + return result.toString(); + } + + /** + * Returns a hexadecimal representation of the bytes written to ByteBuffer (i.e. all the bytes + * before position()). + */ + public static String byteBufferToHex(ByteBuffer buffer) { + ByteBuffer tmp = buffer.duplicate(); + tmp.flip(); + byte[] bytes = new byte[tmp.remaining()]; + tmp.get(bytes); + return bytesToHex(bytes); + } + + public static byte[] hexToBytes(String hex) throws IllegalArgumentException { + if (hex.length() % 2 != 0) { + throw new IllegalArgumentException("Expected a string of even length"); + } + int size = hex.length() / 2; + byte[] result = new byte[size]; + for (int i = 0; i < size; i++) { + int hi = Character.digit(hex.charAt(2 * i), 16); + int lo = Character.digit(hex.charAt(2 * i + 1), 16); + if ((hi == -1) || (lo == -1)) { + throw new IllegalArgumentException("input is not hexadecimal"); + } + result[i] = (byte) (16 * hi + lo); + } + return result; + } + + public static void installOnlyThisProvider(Provider provider) { + for (Provider p : Security.getProviders()) { + Security.removeProvider(p.getName()); + } + Security.insertProviderAt(provider, 1); + } + + public static void installOnlyOpenJDKProviders() throws Exception { + for (Provider p : Security.getProviders()) { + Security.removeProvider(p.getName()); + } + installOpenJDKProvider("com.sun.net.ssl.internal.ssl.Provider"); + installOpenJDKProvider("com.sun.crypto.provider.SunJCE"); + installOpenJDKProvider("com.sun.security.sasl.Provider"); + installOpenJDKProvider("org.jcp.xml.dsig.internal.dom.XMLDSigRI"); + installOpenJDKProvider("sun.security.ec.SunEC"); + installOpenJDKProvider("sun.security.jgss.SunProvider"); + installOpenJDKProvider("sun.security.provider.Sun"); + installOpenJDKProvider("sun.security.rsa.SunRsaSign"); + installOpenJDKProvider("sun.security.smartcardio.SunPCSC"); + } + + private static void installOpenJDKProvider(String className) throws Exception { + Provider provider = (Provider) Class.forName(className).getConstructor().newInstance(); + Security.insertProviderAt(provider, 1); + } +} diff --git a/java/com/google/security/wycheproof/WycheproofRunner.java b/java/com/google/security/wycheproof/WycheproofRunner.java new file mode 100644 index 0000000..e4da431 --- /dev/null +++ b/java/com/google/security/wycheproof/WycheproofRunner.java @@ -0,0 +1,206 @@ +/** + * @license + * Copyright 2013 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Arrays; +import org.junit.runner.Description; +import org.junit.runner.manipulation.Filter; +import org.junit.runner.manipulation.NoTestsRemainException; +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; + +/** + * <p>A custom JUnit4 runner that, with annotations, allows choosing tests to run on a specific + * provider. To use it, annotate a runner class with {@code RunWith(WycheproofRunner.class)}, and + * {@code SuiteClasses({AesGcmTest.class, ...})}. When you run this class, it will run all the tests + * in all the suite classes. + * + * <p>To exclude certain tests, a runner class should be annotated with {@code @Provider} which + * indicates the target provider. Test exclusion is defined as follows: + * <ul>@Fast test runners skip @SlowTest test functions. + * <ul>@Presubmit test runners skip @NoPresubmitTest test functions. + * <ul>All test runners skip @ExcludedTest test functions. + * + * @author thaidn@google.com (Thai Duong) + */ +public class WycheproofRunner extends Suite { + + /** List of supported providers. */ + public enum ProviderType { + BOUNCY_CASTLE, + CONSCRYPT, + OPENJDK, + SPONGY_CASTLE, + } + + // Annotations for test runners. + + /** + * Annotation to specify the target provider of a test runner. + * + * <p>Usage: @Provider(ProviderType.BOUNCY_CASTLE) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE}) + public @interface Provider { + ProviderType value(); + } + + /** + * Annotation to specify presubmit test runners that exclude {@code @NoPresubmitTets} tests. + * + * <p>Usage: @Presubmit(ProviderType.BOUNCY_CASTLE) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE}) + public @interface Presubmit {} + + /** + * Annotation to specify fast test runners that exclude {@code @SlowTest} tests. + * + * <p>Usage: @Fast + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.TYPE}) + public @interface Fast {} + + // Annotations for test functions + + /** + * Tests that take too much time to run, should be excluded from TAP and wildcard target patterns + * like:..., :*, or :all. + * + * <p>Usage: @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ...}) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + public @interface SlowTest { + ProviderType[] providers(); + } + + /** + * Tests that should be excluded from presubmit checks on specific providers. + * + * <p>Usage: @NoPresubmitTest( + * providers = {ProviderType.BOUNCY_CASTLE, ...}, + * bugs = {"b/123456789"} + * ) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD, ElementType.FIELD}) + public @interface NoPresubmitTest { + /** List of providers that this test method should not run as presubmit check. */ + ProviderType[] providers(); + + /** List of blocking bugs (and comments). */ + String[] bugs(); + } + + /** + * Annotation to specify test functions that should be excluded on specific providers. + * + * <p>Usage: @ExcludedTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.OPENJDK}) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + public @interface ExcludedTest { + ProviderType[] providers(); + String comment(); + } + + /** + * Custom filter to exclude certain test functions. + * + */ + public static class ExcludeTestFilter extends Filter { + + Class<?> runnerClass; + Provider targetProvider; + Fast fast; + Presubmit presubmit; + + public ExcludeTestFilter(Class<?> runnerClass) { + this.runnerClass = runnerClass; + this.targetProvider = runnerClass.getAnnotation(Provider.class); + this.fast = runnerClass.getAnnotation(Fast.class); + this.presubmit = runnerClass.getAnnotation(Presubmit.class); + } + + @Override + public String describe() { + return "exclude certain tests on specific providers"; + } + + @Override + public boolean shouldRun(Description description) { + return isOkayToRunTest(description); + } + + private boolean isOkayToRunTest(Description description) { + if (targetProvider == null) { + // Run all test functions if the test runner is not annotated with {@code @Provider}. + return true; + } + // Skip @ExcludedTest tests + ExcludedTest excludedTest = description.getAnnotation(ExcludedTest.class); + if (excludedTest != null + && Arrays.asList(excludedTest.providers()).contains(targetProvider.value())) { + return false; + } + + // If the runner class is annotated with @Presubmit, skip non-presubmit tests + if (presubmit != null) { + NoPresubmitTest ignoreOn = description.getAnnotation(NoPresubmitTest.class); + if (ignoreOn != null + && Arrays.asList(ignoreOn.providers()).contains(targetProvider.value())) { + return false; + } + } + + // If the runner class is annotated with @Fast, skip slow tests + if (fast != null) { + SlowTest ignoreOn = description.getAnnotation(SlowTest.class); + if (ignoreOn != null + && Arrays.asList(ignoreOn.providers()).contains(targetProvider.value())) { + return false; + } + } + + // run everything else + return true; + } + } + + /** Required constructor: called by JUnit reflectively. */ + public WycheproofRunner(Class<?> runnerClass, RunnerBuilder builder) throws InitializationError { + super(runnerClass, builder); + addFilter(new ExcludeTestFilter(runnerClass)); + } + + private void addFilter(Filter filter) { + try { + filter(filter); + } catch (NoTestsRemainException ex) { + System.out.println("No tests remain exception: " + ex); + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/AesEaxTest.java b/java/com/google/security/wycheproof/testcases/AesEaxTest.java new file mode 100644 index 0000000..3237afa --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/AesEaxTest.java @@ -0,0 +1,285 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(bleichen): +// - So far only 16 byte tags are tested. +// - default values: BC uses a 64-bit default for tags. +// Tag size is not such a big problem as with AES-GCM, +// since a 64 bit tag gives 64 bit strength for AES-EAX. + +package com.google.security.wycheproof; + +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import junit.framework.TestCase; + +/** AES-EAX tests */ +public class AesEaxTest extends TestCase { + + /** Test vectors */ + public static class EaxTestVector { + final byte[] pt; + final byte[] aad; + final byte[] ct; + final String ptHex; + final String ctHex; + final GCMParameterSpec parameters; + final SecretKeySpec key; + + public EaxTestVector( + String message, String keyMaterial, String nonce, String aad, String ciphertext) { + this.ptHex = message; + this.pt = TestUtil.hexToBytes(message); + this.aad = TestUtil.hexToBytes(aad); + this.ct = TestUtil.hexToBytes(ciphertext); + this.ctHex = ciphertext; + // BouncyCastle uses GCMParameterSpec to specify the parameters for EAX. + // This solution is a bit of a hack, but so far we don't know a better way to + // specify these parameters. + // So far all test vectors use a 128 bit tag. + this.parameters = new GCMParameterSpec(128, TestUtil.hexToBytes(nonce)); + this.key = new SecretKeySpec(TestUtil.hexToBytes(keyMaterial), "AES"); + } + }; + + private static final EaxTestVector[] EAX_TEST_VECTOR = { + new EaxTestVector( + "", + "010511c5e24ee7097dca93272ebfae9e", + "93ad516bc6f7302b8edb884ca37f2e65", + "", + "12edfdb379ef62e845da3d17995b4a1e"), + new EaxTestVector( + "", + "acf877a5aa71e794efd6dc82d5b1a155", + "4e301710ae15b2f0ee6335d774741f7e", + "c0e0f00a919b7652", + "eb3dae1fc33be95848da9fd24e7dbae3"), + new EaxTestVector( + "c3", + "95d8e3675bbc3b96befdc5efb7433a68", + "0d40fdefd9289e3a49114454b3c4a5f4", + "f2", + "c5814dfc2f4ee1719bd5f1d5a649174c1a"), + new EaxTestVector( + "5810842d", + "2eed51af91b178b26e9b53c8877a7af6", + "e78747ca46cb9f2068e07717d5226e8a", + "", + "24245c5bb54aa8bfaceca3665867fa2d7de1653d"), + new EaxTestVector( + "5ae11bb3b7d60e55", + "cb782da180e97023530d1612e2287f0d", + "ba641ebe03057b387dd3132e0c7a3853", + "", + "f6f64fa858708b8f445812fd75a9639f635045fd5972b820"), + new EaxTestVector( + "54332ed26cd966761710ea58a8f248", + "8b4457d52e5c04b38d306f8f38480e97", + "3f9d6faca5dd97eb1bc74e1954304cca", + "", + "3ebbf1fe11e2f454e0ef587fb42a7588e1e32ea788cae20d1700584f448814"), + new EaxTestVector( + "82ce1f2934dcafe9dee7e0e7cbfdfcd0", + "2892cf62d2cc0e8e9c796624e05920f5", + "8a0da6d1c4b7a4f426ad62f6829cc310", + "c3ed66484eb367c8", + "c374afaa42d9497326af332f42d2dee8fb478c82a2b2567b0ab9597c93f137cf"), + new EaxTestVector( + "e0c993ff5d1d00b4cbee523a1df01db011794d54ab7a504c", + "463d89aadfa7d8158dcff9b9c3fc32aa", + "356ab4709b32fc85ff82f40561e9f08b", + "5ab01a3bfa141f8d33720bd1", + "d34bc706a9d7a2be6c2d8805cec2fac270ec6d17844b0911accb612cbb3b373438c74c1280445359"), + new EaxTestVector( + "e9dfb2897e44236880baf166fa62fa5b8a4713aa981dbc3fe6cf65d9f0c30f47", + "54617abbeb90fff7095b26af0e596064", + "2621c97c4fe379d9d42f04c479ae1bac", + "b6b29c2fbe29dcd2", + "212263116062443db28d6abd2c3bca880ea4d178282247fffbc10532d40e9cea" + + "6f580fdaca33d446dd6f38a4425be844"), + new EaxTestVector( + "7537f3e4cbe228468a7837c66aec8a9b6033cba4f1b3d8", + "7c74da83b1f292b869c891c80850e85f8237412e13a0bf3f", + "cfab2c573a0e723613e6e5b58787af60", + "", + "98a55f7db58fde8ed8bc00c01c97a6e5bda137b03e56e0dddfbe396c44a14646cbc89979f38736"), + // Some test vectors for counter overflow: + // Initial counter value == 2^128-1 + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111", + "000102030405060708090a0b0c0d0e0f", + "3c8cc2970a008f75cc5beae2847258c2", + "", + "3c441f32ce07822364d7a2990e50bb13d7b02a26969e4a937e5e9073b0d9c968" + + "db90bdb3da3d00afd0fc6a83551da95e"), + // counter value overflows at 64-bit boundary + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111", + "000102030405060708090a0b0c0d0e0f", + "aef03d00598494e9fb03cd7d8b590866", + "", + "d19ac59849026a91aa1b9aec29b11a202a4d739fd86c28e3ae3d588ea21d70c6" + + "c30f6cd9202074ed6e2a2a360eac8c47"), + // no counter overflow, but the 64 most significant bits are set. + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111", + "000102030405060708090a0b0c0d0e0f", + "55d12511c696a80d0514d1ffba49cada", + "", + "2108558ac4b2c2d5cc66cea51d6210e046177a67631cd2dd8f09469733acb517" + + "fc355e87a267be3ae3e44c0bf3f99b2b"), + // counter value overflows at 32-bit boundary + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111", + "000102030405060708090a0b0c0d0e0f", + "79422ddd91c4eee2deaef1f968305304", + "", + "4d2c1524ca4baa4eefcce6b91b227ee83abaff8105dcafa2ab191f5df2575035" + + "e2c865ce2d7abdac024c6f991a848390"), + // no counter overflow, but bits 32-64 and 96-128 are set. + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111", + "000102030405060708090a0b0c0d0e0f", + "0af5aa7a7676e28306306bcd9bf2003a", + "", + "8eb01e62185d782eb9287a341a6862ac5257d6f9adc99ee0a24d9c22b3e9b38a" + + "39c339bc8a74c75e2c65c6119544d61e"), + // no counter overflow, lower 64 bits are 2^63-1 + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111", + "000102030405060708090a0b0c0d0e0f", + "af5a03ae7edd73471bdcdfac5e194a60", + "", + "94c5d2aca6dbbce8c24513a25e095c0e54a942860d327a222a815cc713b163b4" + + "f50b30304e45c9d411e8df4508a98612"), + // counter overflow between block 2 and block 3. + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111" + + "2222222222222222222222222222222233333333333333333333333333333333", + "000102030405060708090a0b0c0d0e0f", + "b37087680f0edd5a52228b8c7aaea664", + "", + "3bb6173e3772d4b62eef37f9ef0781f360b6c74be3bf6b371067bc1b090d9d66" + + "22a1fbec6ac471b3349cd4277a101d40890fbf27dfdcd0b4e3781f9806daabb6" + + "a0498745e59999ddc32d5b140241124e"), + // no counter overflow, the lower 64 bits are 2^63-4. + new EaxTestVector( + "0000000000000000000000000000000011111111111111111111111111111111" + + "2222222222222222222222222222222233333333333333333333333333333333" + + "44444444444444444444444444444444", + "000102030405060708090a0b0c0d0e0f", + "4f802da62a384555a19bc2b382eb25af", + "", + "e9b0bb8857818ce3201c3690d21daa7f264fb8ee93cc7a4674ea2fc32bf182fb" + + "2a7e8ad51507ad4f31cefc2356fe7936a7f6e19f95e88fdbf17620916d3a6f3d" + + "01fc17d358672f777fd4099246e436e167910be744b8315ae0eb6124590c5d8b"), + // 192-bit keys + new EaxTestVector( + "", + "03dd258601c1d4872a52b27892db0356911b2df1436dc7f4", + "723cb2022102113018dcd2d204022114", + "", + "c472b1c6c22b4f2b7e02409499aa2ade"), + new EaxTestVector( + "", + "d33dda72649575e42d6eb1f3255e686084b8a9cf4480803c", + "ad2a1d2ef236dfaeb109ab29b1084d63", + "fb9c0938a5d317fad5f43edc", + "6edc358f22358e1d328c4c1cd98184c6"), + new EaxTestVector( + "abcdef", + "03dd258601c1d4872a52b27892db0356911b2df1436dc7f4", + "025f3d2286c143976412022102696708231208", + "8917328de211", + "520f4f2cf1b893ae3ba8ecbac3a08ea57de2cd"), + new EaxTestVector( + "4e43dbebe316b7d684b56236fdd928dd", + "a36eed1cb54130f547664c184c249e777a3d8ba2e2251b58", + "e9587847b1e81511e0643f7dda5b725c", + "80c7cb954463b6067b081ff66b1d40cc", + "e2645cd32a6e8c1e7cd1991d879b335756f848aba8e51f0b56712bb2889c4783"), + new EaxTestVector( + "1111111111111111111111111111111122222222222222222222222222222222", + "0172acf299142c001d0c231287c1182784554ca3a21908276ac2c92af1294612", + "000102030405060708090a0b0c0d0e0f1a1b1c1d", + "77922d34e452e0a40962873d22901dd22ad1c303", + "5917879b9fa85f4007b7bd0cd46f067d5a7bf287f19dfcc5475c95a4acce520a" + + "4c5df804bc091a3b5d6c838b7e494571"), + // 256-bit keys + new EaxTestVector( + "", + "0172acf299142c001d0c231287c1182784554ca3a21908276ac2c92af1294612", + "696708231208", + "", + "7c8f86f837a4f72c574678d92f637f07"), + new EaxTestVector( + "abcdef", + "0172acf299142c001d0c231287c1182784554ca3a21908276ac2c92af1294612", + "696708231208", + "8917328de211", + "12486c87bf9a7f22fa65a9493ec0f57f8070f5"), + new EaxTestVector( + "13d106d7be0890093f44a457d4cc5309", + "db50934278a8d8101d1c538acfbfaa13aba9fe53408b6205a0c996d53cf04e8d", + "eaef04607a36b2e1b1c539bc335aee9a", + "d50e7dbdcc7cf92822dd9dd762a0fc12", + "2202165697a2d21316c5f65d2aedb3c52b5567b3f8a25e247cfda1f02bc6cf6f"), + new EaxTestVector( + "17672288fff3e93a45b3b951bbcfa8a4cb", + "1cd28aca6542a4df7316b2c6e9232a4e2cc88cf7aaece33eec7da32ab514051f", + "d219298abb115ccbb473cf8e2da9671a", + "9c504ab2e5ce0f46844833aba6a11c9186e500239460bb26", + "aa518b62c5422e56ce393951aa0441e99df8cafb1555d5a30c90391bb9272c32b9"), + new EaxTestVector( + "1111111111111111111111111111111122222222222222222222222222222222", + "0172acf299142c001d0c231287c1182784554ca3a21908276ac2c92af1294612", + "000102030405060708090a0b0c0d0e0f1a1b1c1d", + "92d3e42e0409273291d2dc034450", + "5917879b9fa85f4007b7bd0cd46f067d5a7bf287f19dfcc5475c95a4acce520a" + + "e632946e4999be20159977431bef0454"), + }; + + public void testEax() throws Exception { + for (EaxTestVector test : EAX_TEST_VECTOR) { + Cipher cipher = Cipher.getInstance("AES/EAX/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + byte[] ct = cipher.doFinal(test.pt); + assertEquals(test.ctHex, TestUtil.bytesToHex(ct)); + } + } + + public void testLateUpdateAAD() throws Exception { + for (EaxTestVector test : EAX_TEST_VECTOR) { + Cipher cipher = Cipher.getInstance("AES/EAX/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + byte[] c0 = cipher.update(test.pt); + try { + cipher.updateAAD(test.aad); + } catch (java.lang.IllegalStateException ex) { + // Typically one should pass the AAD in first. + // Hence it is OK to get this exception. + // For example, this is the behaviour of SUNJce. + continue; + } + byte[] c1 = cipher.doFinal(); + String result = TestUtil.bytesToHex(c0) + TestUtil.bytesToHex(c1); + assertEquals(test.ctHex, result); + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/AesGcmTest.java b/java/com/google/security/wycheproof/testcases/AesGcmTest.java new file mode 100644 index 0000000..4e4a879 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/AesGcmTest.java @@ -0,0 +1,473 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.ExcludedTest; +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import com.google.security.wycheproof.WycheproofRunner.SlowTest; +import java.nio.ByteBuffer; +import java.security.AlgorithmParameterGenerator; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import junit.framework.TestCase; + +// TODO(bleichen): +// - For EAX I was able to derive some special cases by inverting OMAC. +// Not sure if that is possible here. +/** + * Testing AES-GCM + * + * <p>Other tests using AES-GCM are: CipherInputStreamTest.java CipherOuputStreamTest.java + */ +public class AesGcmTest extends TestCase { + + /** Test vectors */ + public static class GcmTestVector { + final byte[] pt; + final byte[] aad; + final byte[] ct; + final String ptHex; + final String ctHex; + final GCMParameterSpec parameters; + final SecretKeySpec key; + final int nonceLengthInBits; + final int tagLengthInBits; + + public GcmTestVector( + String message, + String keyMaterial, + String nonce, + String aad, + String ciphertext, + String tag) { + this.ptHex = message; + this.pt = TestUtil.hexToBytes(message); + this.aad = TestUtil.hexToBytes(aad); + this.ct = TestUtil.hexToBytes(ciphertext + tag); + this.ctHex = ciphertext + tag; + this.tagLengthInBits = 4 * tag.length(); + this.nonceLengthInBits = 4 * nonce.length(); + this.parameters = new GCMParameterSpec(tagLengthInBits, TestUtil.hexToBytes(nonce)); + this.key = new SecretKeySpec(TestUtil.hexToBytes(keyMaterial), "AES"); + } + }; + + private static final GcmTestVector[] GCM_TEST_VECTORS = { + new GcmTestVector( + "001d0c231287c1182784554ca3a21908", + "5b9604fe14eadba931b0ccf34843dab9", + "028318abc1824029138141a2", + "", + "26073cc1d851beff176384dc9896d5ff", + "0a3ea7a5487cb5f7d70fb6c58d038554"), + new GcmTestVector( + "001d0c231287c1182784554ca3a21908", + "5b9604fe14eadba931b0ccf34843dab9", + "921d2507fa8007b7bd067d34", + "00112233445566778899aabbccddeeff", + "49d8b9783e911913d87094d1f63cc765", + "1e348ba07cca2cf04c618cb4"), + new GcmTestVector( + "2035af313d1346ab00154fea78322105", + "aa023d0478dcb2b2312498293d9a9129", + "0432bc49ac34412081288127", + "aac39231129872a2", + "eea945f3d0f98cc0fbab472a0cf24e87", + "4bb9b4812519dadf9e1232016d068133"), + new GcmTestVector( + "2035af313d1346ab00154fea78322105", + "aa023d0478dcb2b2312498293d9a9129", + "0432bc49ac344120", + "aac39231129872a2", + "64c36bb3b732034e3a7d04efc5197785", + "b7d0dd70b00d65b97cfd080ff4b819d1"), + new GcmTestVector( + "02efd2e5782312827ed5d230189a2a342b277ce048462193", + "2034a82547276c83dd3212a813572bce", + "3254202d854734812398127a3d134421", + "1a0293d8f90219058902139013908190bc490890d3ff12a3", + "64069c2d58690561f27ee199e6b479b6369eec688672bde9", + "9b7abadd6e69c1d9ec925786534f5075"), + }; + + /** + * Returns the GCM test vectors supported by the current provider. + * This is necessary since not every provider supports all parameters sizes. + * For example SUNJCE does not support 8 byte tags and Conscrypt only supports + * 12 byte nonces. + * Such restrictions are often made because AES-GCM is a relatively weak algorithm and + * especially small parameter sizes can lead to easy attacks. + * Avoiding such small parameter sizes should not be seen as a bug in the library. + * + * <p>The only assumption we make here is that all test vectors with 128 bit tags and nonces + * with at least 96 bits are supported. + */ + private Iterable<GcmTestVector> getTestVectors() throws Exception { + ArrayList<GcmTestVector> supported = new ArrayList<GcmTestVector>(); + for (GcmTestVector test : GCM_TEST_VECTORS) { + if (test.nonceLengthInBits != 96 || test.tagLengthInBits != 128) { + try { + // Checks whether the parameter size is supported. + // It would be nice if there was a way to check this without trying to encrypt. + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + } catch (InvalidKeyException | InvalidAlgorithmParameterException ex) { + // Not supported + continue; + } + } + supported.add(test); + } + return supported; + } + + public void testVectors() throws Exception { + for (GcmTestVector test : getTestVectors()) { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + byte[] ct = cipher.doFinal(test.pt); + assertEquals(test.ctHex, TestUtil.bytesToHex(ct)); + } + } + + /** + * Typically one should always call updateAAD before any call to update. This test checks what + * happens if the order is reversed. The test expects that a correct implementation either + * computes the tag correctly or throws an exception. + * + * <p>For example, OpenJdk did compute incorrect tags in this case. The bug has been fixed in + * http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/89c06ca1e6cc + * + * <p>For example BouncyCastle computes correct tags if the calls are reversed, SunJCE and OpenJdk + * now throw exceptions. + */ + public void testLateUpdateAAD() throws Exception { + for (GcmTestVector test : getTestVectors()) { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + byte[] c0 = cipher.update(test.pt); + try { + cipher.updateAAD(test.aad); + } catch (java.lang.IllegalStateException ex) { + // Throwing an exception is valid behaviour. + continue; + } + byte[] c1 = cipher.doFinal(); + String result = TestUtil.bytesToHex(c0) + TestUtil.bytesToHex(c1); + assertEquals(test.ctHex, result); + } + } + + /** + * JCE has a dangerous feature: after a doFinal the cipher is typically reinitialized using the + * previous IV. This "feature" can easily break AES-GCM usages, because encrypting twice with + * the same key and IV leaks the authentication key. Hence any reasonable implementation of + * AES-GCM should not allow this. The expected behaviour of OpenJDK can be derived from the tests + * in jdk/test/com/sun/crypto/provider/Cipher/AES/TestGCMKeyAndIvCheck.java. + * OpenJDK does not allow two consecutive initializations for encryption with the same key and IV. + * + * <p>The test here is weaker than the restrictions in OpenJDK. The only requirement here is that + * reusing a Cipher without an explicit init() is caught. + * + * <p>BouncyCastle 1.52 failed this test + * + * <p>Conscrypt failed this test + */ + public void testIvReuse() throws Exception { + for (GcmTestVector test : getTestVectors()) { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + byte[] ct1 = cipher.doFinal(test.pt); + try { + byte[] ct2 = cipher.doFinal(test.pt); + fail( + "It should not possible to reuse an IV." + + " ct1:" + + TestUtil.bytesToHex(ct1) + + " ct2:" + + TestUtil.bytesToHex(ct2)); + } catch (java.lang.IllegalStateException ex) { + // This is expected. + } + } + } + + /** Encryption with ByteBuffers. */ + public void testByteBuffer() throws Exception { + for (GcmTestVector test : getTestVectors()) { + // Encryption + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + ByteBuffer ptBuffer = ByteBuffer.wrap(test.pt); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + int outputSize = cipher.getOutputSize(test.pt.length); + ByteBuffer ctBuffer = ByteBuffer.allocate(outputSize); + cipher.updateAAD(test.aad); + cipher.doFinal(ptBuffer, ctBuffer); + assertEquals(test.ctHex, TestUtil.byteBufferToHex(ctBuffer)); + + // Decryption + ctBuffer.flip(); + cipher.init(Cipher.DECRYPT_MODE, test.key, test.parameters); + outputSize = cipher.getOutputSize(test.ct.length); + ByteBuffer decrypted = ByteBuffer.allocate(outputSize); + cipher.updateAAD(test.aad); + cipher.doFinal(ctBuffer, decrypted); + assertEquals(test.ptHex, TestUtil.byteBufferToHex(decrypted)); + } + } + + /** Encryption with ByteBuffers should be copy-safe. */ + public void testByteBufferAlias() throws Exception { + for (GcmTestVector test : getTestVectors()) { + // Encryption + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + int outputSize = cipher.getOutputSize(test.pt.length); + byte[] backingArray = new byte[outputSize]; + ByteBuffer ptBuffer = ByteBuffer.wrap(backingArray); + ptBuffer.put(test.pt); + ptBuffer.flip(); + ByteBuffer ctBuffer = ByteBuffer.wrap(backingArray); + cipher.updateAAD(test.aad); + cipher.doFinal(ptBuffer, ctBuffer); + assertEquals(test.ctHex, TestUtil.byteBufferToHex(ctBuffer)); + + // Decryption + ByteBuffer decrypted = ByteBuffer.wrap(backingArray); + ctBuffer.flip(); + cipher.init(Cipher.DECRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + cipher.doFinal(ctBuffer, decrypted); + assertEquals(test.ptHex, TestUtil.byteBufferToHex(decrypted)); + } + } + + public void testReadOnlyByteBuffer() throws Exception { + for (GcmTestVector test : getTestVectors()) { + // Encryption + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + ByteBuffer ptBuffer = ByteBuffer.wrap(test.pt).asReadOnlyBuffer(); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + int outputSize = cipher.getOutputSize(test.pt.length); + ByteBuffer ctBuffer = ByteBuffer.allocate(outputSize); + cipher.updateAAD(test.aad); + cipher.doFinal(ptBuffer, ctBuffer); + assertEquals(test.ctHex, TestUtil.byteBufferToHex(ctBuffer)); + + // Decryption + ctBuffer.flip(); + ctBuffer = ctBuffer.asReadOnlyBuffer(); + cipher.init(Cipher.DECRYPT_MODE, test.key, test.parameters); + outputSize = cipher.getOutputSize(test.ct.length); + ByteBuffer decrypted = ByteBuffer.allocate(outputSize); + cipher.updateAAD(test.aad); + cipher.doFinal(ctBuffer, decrypted); + assertEquals(test.ptHex, TestUtil.byteBufferToHex(decrypted)); + } + } + + /** + * If a ByteBuffer is backed by an array and not readonly, then it is possible to access the data + * through the .array() method. An implementation using this possiblity must ensure that it + * considers the offset. + */ + public void testByteBufferWithOffset() throws Exception { + for (GcmTestVector test : getTestVectors()) { + // Encryption + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + ByteBuffer ptBuffer = ByteBuffer.wrap(new byte[test.pt.length + 50]); + ptBuffer.position(5); + ptBuffer = ptBuffer.slice(); + ptBuffer.put(test.pt); + ptBuffer.flip(); + + ByteBuffer ctBuffer = ByteBuffer.wrap(new byte[test.ct.length + 50]); + ctBuffer.position(8); + ctBuffer = ctBuffer.slice(); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + cipher.doFinal(ptBuffer, ctBuffer); + assertEquals(test.ctHex, TestUtil.byteBufferToHex(ctBuffer)); + ctBuffer.flip(); + + // Decryption + ByteBuffer decBuffer = ByteBuffer.wrap(new byte[test.pt.length + 50]); + decBuffer.position(6); + decBuffer = decBuffer.slice(); + cipher.init(Cipher.DECRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + cipher.doFinal(ctBuffer, decBuffer); + assertEquals(test.ptHex, TestUtil.byteBufferToHex(decBuffer)); + } + } + + public void testByteBufferTooShort() throws Exception { + for (GcmTestVector test : getTestVectors()) { + // Encryption + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + ByteBuffer ptBuffer = ByteBuffer.wrap(test.pt); + ByteBuffer ctBuffer = ByteBuffer.allocate(test.ct.length - 1); + cipher.init(Cipher.ENCRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + try { + cipher.doFinal(ptBuffer, ctBuffer); + fail("This should not work"); + } catch (ShortBufferException ex) { + // expected + } + + // Decryption + ctBuffer = ByteBuffer.wrap(test.ct); + ByteBuffer decrypted = ByteBuffer.allocate(test.pt.length - 1); + cipher.init(Cipher.DECRYPT_MODE, test.key, test.parameters); + cipher.updateAAD(test.aad); + try { + cipher.doFinal(ctBuffer, decrypted); + fail("This should not work"); + } catch (ShortBufferException ex) { + // expected + } + } + } + + /** + * The default authentication tag size should be 128-bit by default for the following reasons: + * <br> + * (1) Security: Ferguson, N., Authentication Weaknesses in GCM, Natl. Inst. Stand. Technol. [Web + * page], http://www.csrc.nist.gov/groups/ST/toolkit/BCM/documents/comments/ + * CWC-GCM/Ferguson2.pdf, May 20, 2005. This paper points out that a n-bit tag has lower strength + * than expected. <br> + * (2) Compatibility: Assume an implementer tests some code using one provider than switches to + * another provider. Such a switch should ideally not lower the security. <br> + * Conscrypt used to have only 12-byte authentication tag (b/26186727). + */ + public void testDefaultTagSizeIvParameterSpec() throws Exception { + byte[] counter = new byte[12]; + byte[] input = new byte[16]; + byte[] key = new byte[16]; + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + try { + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(counter)); + } catch (InvalidAlgorithmParameterException ex) { + // OpenJDK8 does not support IvParameterSpec for GCM. + System.out.println("testDefaultTagSizeIvParameterSpec:" + ex.toString()); + return; + } + byte[] output = cipher.doFinal(input); + assertEquals(input.length + 16, output.length); + } + + /** + * The default authentication tag size should be 128-bit by default for the following reasons: + * <br> + * (1) Security: Ferguson, N., Authentication Weaknesses in GCM, Natl. Inst. Stand. Technol. [Web + * page], http://www.csrc.nist.gov/groups/ST/toolkit/BCM/documents/comments/ + * CWC-GCM/Ferguson2.pdf, May 20, 2005. This paper points out that a n-bit tag has lower strength + * than expected. <br> + * (2) Compatibility: Assume an implementer tests some code using one provider than switches to + * another provider. Such a switch should ideally not lower the security. <br> + * BouncyCastle used to have only 12-byte authentication tag (b/26186727). + */ + public void testDefaultTagSizeAlgorithmParameterGenerator() throws Exception { + byte[] input = new byte[10]; + byte[] key = new byte[16]; + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + try { + AlgorithmParameterGenerator.getInstance("GCM"); + } catch (NoSuchAlgorithmException ex) { + // Conscrypt does not support AlgorithmParameterGenerator for GCM. + System.out.println("testDefaultTagSizeAlgorithmParameterGenerator:" + ex.toString()); + return; + } + AlgorithmParameters param = AlgorithmParameterGenerator.getInstance("GCM").generateParameters(); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), param); + byte[] output = cipher.doFinal(input); + assertEquals(input.length + 16, output.length); + } + + /** + * Test AES-GCM wrapped around counter bug which leaks plaintext and authentication key. Let's + * consider 12-byte IV, counter = IV || 0^31 || 1. For each encryption block, the last 4 bytes of + * the counter is increased by 1. After 2^32 blocks, the counter will be wrapped around causing + * counter collision and hence, leaking plaintext and authentication key as explained below. The + * library must make a check to make sure that the plaintext's length never exceeds 2^32 - 2 + * blocks. Note that this is different from usual IV collisions because it happens even if users + * use different IVs. <br> + * We have: <br> + * J0 = IV || 0^31 || 1 <br> + * Plaintext: P[0], P[1], P[2], .... <br> + * Ciphertext: <br> + * C[0] = Enc(K, (J0 + 1) % 2^32) XOR P[0] <br> + * C[1] = Enc(K, (J0 + 2) % 2^32) XOR P[1] <br> + * C[2] = Enc(K, (J0 + 3) % 2^32) XOR P[2] <br> + * ... <br> + * C[2^32 - 1] = Enc(K, J0) XOR P[2^32 - 1] <br> + * C[2^32] = Enc(K, (J0 + 1)% 2^32) XOR P[2^32] <br> + * It means that after 2^32 blocks, the counter is wrapped around causing counter collisions. In + * counter mode, once the counter is collided then it's reasonable to assume that the plaintext is + * leaked. As the ciphertext is already known to attacker, Enc(K, J0) is leaked. <br> + * Now, as the authentication tag T is computed as GHASH(H, {}, C) XOR E(K, J0), the attacker can + * learn GHASH(H, {}, C}. It essentially means that the attacker finds a polynomial where H is the + * root (see Joux attack http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/Joux_comments.pdf). + * Solving polynomial equation in GF(2^128) is enough to extract the authentication key. + * + * <p>BouncyCastle used to have this bug (CVE-2015-6644). + * + * <p>OpenJDK8 used to have this bug (http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/0c3ed12cdaf5) + * + * <p>The test is slow as we have to encrypt 2^32 blocks. + */ + // TODO(quannguyen): Is there a faster way to test it? +/* + @ExcludedTest( + providers = {ProviderType.CONSCRYPT}, + comment = "Conscrypt doesn't support streaming, would crash") + @SlowTest( + providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE, ProviderType.OPENJDK}) + public void testWrappedAroundCounter() throws Exception { + try { + byte[] iv = new byte[12]; + byte[] input = new byte[16]; + byte[] key = new byte[16]; + (new SecureRandom()).nextBytes(key); + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init( + Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(16 * 8, iv)); + byte[] output = cipher.update(input); + for (long i = 0; i < 4294967296L + 2; i++) { + byte[] output1 = cipher.update(input); + assertFalse("GCM Wrapped Around Counter" + i, Arrays.equals(output, output1)); + } + fail("Expected Exception"); + } catch (Exception expected) { + System.out.println("testWrappedAroundcounter:" + expected.toString()); + } + } +*/ +} diff --git a/java/com/google/security/wycheproof/testcases/BasicTest.java b/java/com/google/security/wycheproof/testcases/BasicTest.java new file mode 100644 index 0000000..1cd9ca4 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/BasicTest.java @@ -0,0 +1,45 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.security.Provider; +import java.security.Security; +import java.util.TreeSet; +import junit.framework.TestCase; + +/** Not a true test: reports information about the provider. */ +public class BasicTest extends TestCase { + + /** List all algorithms known to the security manager. */ + public void testListAllAlgorithms() { + for (Provider p : Security.getProviders()) { + System.out.println(); + System.out.println("Provider:" + p.getName()); + // Using a TreeSet here, because the elements are sorted. + TreeSet<String> list = new TreeSet<String>(); + for (Object key : p.keySet()) { + list.add((String) key); + } + for (String algorithm : list) { + if (algorithm.startsWith("Alg.Alias.")) { + continue; + } + System.out.println(algorithm); + } + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/BigIntegerTest.java b/java/com/google/security/wycheproof/testcases/BigIntegerTest.java new file mode 100644 index 0000000..8173a89 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/BigIntegerTest.java @@ -0,0 +1,456 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import junit.framework.TestCase; + +/** + * Test BigInteger class. + * + * <p>This unit tests focuses on checking security relevant properties. + */ +public class BigIntegerTest extends TestCase { + public static final BigInteger[] NONPRIMES = + new BigInteger[] { + // small non prime integers + new BigInteger("-1"), + new BigInteger("0"), + new BigInteger("1"), + // If p is prime then the Mersenne number 2^p-1 is pseudoprime for base 2. + new BigInteger("147573952589676412927"), + new BigInteger("2361183241434822606847"), + // pseudoprime squares derived from Wiefrich primes + new BigInteger("1194649"), + new BigInteger("12327121"), + // G. Jaeschke: "On strong pseudoprimes to several bases", Math o. comp. v.61, p 915-926 + new BigInteger("2152302898747"), + new BigInteger("3474749660383"), + new BigInteger("341550071728321"), + new BigInteger("41234316135705689041"), + new BigInteger("1553360566073143205541002401"), + new BigInteger("56897193526942024370326972321"), + // A list of strong pseudoprimes to 12 or more bases from + // https://arxiv.org/pdf/1509.00864v1.pdf + new BigInteger("360681321802296925566181"), + new BigInteger("164280218643672633986221"), + new BigInteger("318665857834031151167461"), + new BigInteger("7395010240794120709381"), + new BigInteger("2995741773170734841812261"), + new BigInteger("667636712015520329618581"), + new BigInteger("3317044064679887385961981"), + new BigInteger("3110269097300703345712981"), + new BigInteger("552727880697763694556181"), + new BigInteger("3404730287403079539471001"), + // Richarg G.E. Pinch, "Some primality testing algorithms" + // Some composites that passed Maple V's primality test. + new BigInteger("10710604680091"), + new BigInteger("4498414682539051"), + new BigInteger("6830509209595831"), + // Composites that passed the primality test of Mathematica 2.0 + new BigInteger("38200901201"), + new BigInteger("6646915915638769"), + // Composites that passed Axioms primality tests + new BigInteger("168790877523676911809192454171451"), + new BigInteger("68528663395046912244223605902738356719751082784386681071"), + // A composite q that was acceptied by Gnu Crypto. p = 2*q + 1 is prime and could have been + // used to break the SRP with that library. + // http://www.iacr.org/archive/pkc2005/33860010/33860010.pdf + new BigInteger( + "2338274894573145273314679073561004052325493799717332496500873981" + + "9154269566267911565762670147721173495706686483597956042863296855" + + "8985491020031718032728786934761830612407539788738389834804112831" + + "0484933712924414264511799715503596253054638290097305254378560604" + + "3457282155730383806702845548017315217454390994052035233808454053" + + "2209678251"), + // I. Damgard, P. Landrock, and C. Pomerance. "Average case error estimates for the strong + // probable prime test." Math. of Comp. v.61 (203), pp. 177-194. + // + // This paper gives bounds for the number of bases necessary to distinguish composites from + // primes assuming that the tested integer has been chosen at random. + // + // The result is sometimes misinterpreted and used for pseudo primality tests. There the + // assumption of the paper may not be valid, especially if the integer to test has been + // chosen by a potentially malicious party. The following pseudoprimes are 1024 to 1280 bits + // long, pass the MR test for about 1/4 of all bases. They may expose pseudo primality tests + // that misinterpret the paper above. + new BigInteger( + "1730626114143993906582329178627391355248485443639984363030847275" + + "1308542667309368405802823431259718338553667079600118481458180717" + + "8685660312964257923307841168376622412972295432300191118906455596" + + "0636099366430317210651098229261736987868487865820945209431391380" + + "09108180649097618810676094425505547347369635059151651"), + new BigInteger( + "1360998858923994584770803056737393786894832450662215840614559215" + + "7078401469699701619693552331616875038702785662417391573713804038" + + "4334162971247398689854706029275431407028615888533012918610480990" + + "0223861487963796923928503972465761214360888693859314270808955367" + + "40913457414488449790876563256100025424908640036566991"), + new BigInteger( + "3166883756083864374213797577792765404121225450334428749136082272" + + "6277047033553982548405648549530365358167591776542577633638251648" + + "4708794514891794859629545011811469601460428778510574606216627610" + + "9305946545256861710197652701722202600572822026157108510694466031" + + "21873496655525294839125742517721479483987924741221051"), + new BigInteger( + "1867856940026786421328012256561867196437042470176831233408635728" + + "4012048133274069029642553787088950310027377534718962029124718226" + + "6051117402306961193255486702389001315623336948708913938663766675" + + "8226042898352219886123870222547007370332879734207273564946511954" + + "31833673259400609717994958747847898007198993092012403"), + new BigInteger( + "1796390661263009677994016718416108866609292079197277387452323006" + + "0275054640418696223480642324316099214952402651731083265854610369" + + "8224730515713772933976457906751697355710699183284927973990745341" + + "2311585789546147810071014069499060003398982340466066800822746698" + + "64309065127941774208780103317444828873858305613764441"), + new BigInteger( + "1971945240855615239359385779848543278459852521629467703761094672" + + "8118959477624582999696057042356627216821194209090396598966531204" + + "6718418693934025583647341695134065566474352554207810854787929284" + + "0150420997586371167811999782663434687606795518115913678131471778" + + "75984898571603525952885934025286780854976730638309011"), + new BigInteger( + "3150008132483461686934076250569912489352161839369648385736587811" + + "5997183822673267428826594197361084397177321281419482762875475084" + + "9549588421903702315436565970387119142993552663715551586581960248" + + "0385985798377103010348982470471826679560834315129605222126122792" + + "66245495948831504762364224662571600318327270033084451"), + new BigInteger( + "1708946102366142320715649564941267111465045510329061281476212740" + + "3257341007679575909346478379354045686824680545379443269343860874" + + "7656833753674500442989626468892341565281803639470271121897646438" + + "0297951614184327979794615696929197488480659590917557764806142256" + + "64177795195470929762281195447906351417368682849843661"), + new BigInteger( + "3440003701993474165051634746793659123122285886429390887874425798" + + "0539628797086399700050400512078053335053587477375429177907276765" + + "7299212000552180980839328379536622696237474649639004862671352175" + + "9289352494669383679530748723706821659664185661303953233767365167" + + "67872755699135674189217223109386132423577475778316621"), + new BigInteger( + "1384489093437226718803143517408309162781203263729355872818628349" + + "4469526441585078582037579393159945688413133085030944516305313234" + + "8118439725196722488178936032989162127096990828542718648126854836" + + "3215014994571003679167792328172868632219526006267874696849394364" + + "51238457213158274397103569820623680840515654121967511"), + new BigInteger( + "3164393868232068713466361644489248900506521258778648162638744470" + + "1911965299134147189251276735683301303659631352068168884603764242" + + "2058303711027020977731971469313828021385806157441077657252831199" + + "5151267291454080409585783805054468065763411635886980943812129069" + + "12979884469786023782783106107762632814558326808787771"), + new BigInteger( + "3429610981008641614862240834440649965306153336087134811684334214" + + "2781784784880823158748073620472850986640780368357758806487624898" + + "6627917970721407574366482474956464008840562218539437088991213443" + + "6865812444686702307687466249240837612849694711488568460832793683" + + "75653516879275492605255161494494045951397742913942521"), + new BigInteger( + "1452625971469501984029833170297844688666257429198467445330023676" + + "9656278238192507513913993052034672663086092503841752084104847874" + + "8173408690100803386628315407260460724324957380860416531476612359" + + "3906755149555321240901275978836270398698785709389076413509994529" + + "42901485886289548101644664410043634050840333618736241"), + new BigInteger( + "1038759703926769528247935492263828939187707228977771863002037516" + + "6447956205097712397228992931571755867770661683705025240420111189" + + "2868394359927108413461144788316226799790655169187714036057483534" + + "1379449940364129845302840193911613461736295410032863048528135257" + + "04436628490382188950208123780350213139500089456366841"), + new BigInteger( + "2092626848347087607813788288260128832160456227715887480495928337" + + "8143090879636401536763351823849725734769339835456348322174433133" + + "2528919261931329808331753456631473557050588173643619875493912344" + + "2621229276297788264420214803881217267094948976676445054939538411" + + "22580436721054077839958796624587867034849970594728503"), + new BigInteger( + "2599619740922490310102276030628575944314398371981276430688469612" + + "6677200542107317525516057185980658562393307608335402672015071146" + + "4375869967746325500371685760342898099183114419807958654613613854" + + "3992594086574371567802232690430810966098771990068625112489903295" + + "89067604336669355585402887916288037943709029191674911"), + new BigInteger( + "1484944124031033226177904474729672080414277081288126930486713099" + + "2951571588154552341076434413035940622712601649739964234772603407" + + "4857469854866669198948655053082186111410005989963123962723450119" + + "6642285521712848015932226566546835102733706632115364632204156914" + + "64644614536183219912321808854090915103775109695786903"), + new BigInteger( + "1989518237873611249304118136102198299910749751063921465712157675" + + "0160983808717982713586255483659294934004326549705203383719900307" + + "1263871954417468537542759843054899935687365194283002403584007149" + + "4878371117610681917576307737065411378178051858121032451282900716" + + "73542006653340382017735899123084476453857081318545991"), + new BigInteger( + "1001516549472529960430483041632117547467775871427023066924341669" + + "8403875533009883195522874469432253701609651260735835128759135299" + + "5655554893223580483857764100115214746205606713424344869011314868" + + "3107942731565140938612794494135227597999675233998980692687287393" + + "67463341929936509718884001903262839905032784262429503"), + new BigInteger( + "9523120659259647017050060990584944204556454726505878376759616021" + + "0162649328723702952067039028722189901551617226203049071432575686" + + "9121080710327716161595367835528315683397536615084723082551568364" + + "5739952184995573677453019127607472426963971562388390300785220049" + + "6655144350028488056721467755918814393298596327869403"), + new BigInteger( + "1132692896131390459872218381686704761578367301590229517271338668" + + "7180351798454882497438382954425835621126393661367213143371283272" + + "0317909560575328664237540188143415517690966913820407105917871661" + + "6365405171372246705778112163771743546945868623307467307997875571" + + "40869529264839386342569691698111927128704157615097153"), + new BigInteger( + "1468478445343635885853097900396288249751127795088868633754583040" + + "9902362001013473990040942210829761549194134324343879441927807081" + + "4832779046634885071582835688508933384516245429006116427382617949" + + "0797131644177507421862332328509904031871287120929769029086074503" + + "38866991708762791875618755240139448209180903665732503"), + new BigInteger( + "3584128102219288461651881096063603237206550481422480899564693370" + + "6989198816192527918220789937223699304075118319904981106473056074" + + "6022073963857677172123650694187762839204698560127083582857191356" + + "7619601857134928125369766912580367127840531257344393938629885107" + + "16841734490107828355376447675347185589367615046902903"), + new BigInteger( + "1364132540730201251194341844655148002850736352953819312409033451" + + "0581806956034928961765696532883678319811153534823893271895441595" + + "1560405730847235775035340408484490592989244418679611824558459897" + + "3970103405588145228028549820125837425523682281669049087481368021" + + "33702260393866732616878693744975284760231993354960641"), + new BigInteger( + "1201213090774136737579735845388953400530787071160074364126728551" + + "5147303301856817241515212573079940841340044269783294804816431383" + + "8284868252529547559069691488487393115675459439240223181642866729" + + "3429931964973711015111163544551414299071832349845971998375812575" + + "43510797169400923829329952407436122292964382266031253"), + new BigInteger( + "2749611624987217008377958765718501619519235049877079452181305657" + + "4724564026272242180811435338643866876903591496649439319889570905" + + "0358277453956447636555409300854018401232502616530331143658908539" + + "1682266093367017969369633046927346949982338985082398103545735993" + + "26268702707614772584950389057955691219494031838859791"), + new BigInteger( + "2472982114742145360236684931488791833991329788857529670921519821" + + "2275589064185672494327017904494686810840150314271250166999768972" + + "5488277075239138647902134463451436706674384070937644414378922408" + + "3974240802538174272534726968041801996779685771019246098603577098" + + "48139330190576017582503777009836399771498662905893541"), + new BigInteger( + "1865347188865809981733701115448160790425846704558108501171803277" + + "4616363375301457541345495992357828826645510919897778446537615423" + + "0882378024111971510810465276396395657415178370245114122816237302" + + "3283933030997110906700611097744954222271394790237582780817507949" + + "50528224900273599212004329531461848157373189908642761"), + new BigInteger( + "2852220663043188088074403487569592065121097371561337653207919689" + + "5806125544163953214258963319594971029379263400735515369955250013" + + "4028759770788754166339078427645792536001991144766729628117371050" + + "3065276544543379585207323093069812639902415298676791716773723086" + + "01834079961869281917489638496882679996929360595283091"), + new BigInteger( + "1812266945737014247808099956042081894034544124660090203840602123" + + "8933795306490611245152382127750687774085253618514158494675518742" + + "0904863344271961110077635791220319963938065397633608138595169161" + + "4365952732191284608496816156732317034130054052863296504407952482" + + "70402413500178325587999299003705988651612697260381081"), + new BigInteger( + "3461478020849089881636057301867459968070516872602987322072552610" + + "6122696717667098851127207650635960731479969936151065921604956606" + + "9966154794154897232197433347544538725616640069913605417680979153" + + "7941663920296351630552463916932109774095427601318332413237900565" + + "33380330505490643091283956267491266793755039018149751"), + new BigInteger( + "2919979800970068658905539811038971051531482233418344434620488229" + + "7069955478191515351496193695554391114007400265274653645749899336" + + "1682279972987736655018586409178146143048864596533190807270958265" + + "8386345811616055097769189859096393752934393213978617302764485594" + + "27971296399182413971389773786687947710326691137231821"), + new BigInteger( + "4145154657949019520090421067892641813006171355169512965016842717" + + "9656056083456770700476740539321891137934371895885040718614132068" + + "7659642286859932894319946334724710913927915623235424403674960713" + + "3015105499354740364264523832014989327244648027567866644179973588" + + "6851400410006028767095438327490143741004842299878541824964849824" + + "9350463409537126165182086675091928210325509674933575383432172361" + + "1"), + new BigInteger( + "7263570684005586918409651676342477962666063384721447164820162267" + + "3637900031379949446961412145104626127789865770334124795558653625" + + "0265693033953361779942717984970881106667840356057452866357943677" + + "0299187611159071848712668510417692823114550446719084221850233353" + + "5448622581084864206413295247972240845959033925761759264503271102" + + "8711358281311325650083539770515252900036932499310037595977096965" + + "3"), + new BigInteger( + "3266663369261434628530741133725226939380890029427130078147736465" + + "2996576096098663002890375510448427552966457154556853852292297530" + + "3748877081504218804805934729044054195328441392083622877088337833" + + "3839361634881282676119589334709165541036798092721269225600972531" + + "5718770210834831734568895865334347621480511738343920340920819445" + + "8602267925535790135884214787193459118783550610652631217006506945" + + "3"), + new BigInteger( + "2714275054823322283846947242758076394288969833351667671546539844" + + "8651643040817257191932781992745878593029648459331742640462067216" + + "1697889841582474665251728415469605782526629276939159099241968231" + + "4563946417035619325266947257091436696492494177352417584114484475" + + "6610785746958696759938071286674788996869751533043564234638049802" + + "5949514917474176492949501669603402532532836245346872590582496734" + + "1"), + new BigInteger( + "9266983839147571189339684823228253420616685503762301572754412275" + + "1127843293258964600702452397526178329259267484695086911638972315" + + "4961995491900251718105624646921122900256992784437600453557273835" + + "3861591882136393291951512396743267427648075154617935904316277726" + + "4493865072538820667287351636308197262473273185496543102226470825" + + "6662877019047683511136380480413028925833068997034750517865449915" + + "3"), + new BigInteger( + "6943685859962113005380005918916483733270787990846044283782171250" + + "1096851232736318325302320935157976786131666696364333532268184395" + + "8665950723719162662956110077840013184726020313880442980629145593" + + "2383952066228056762115442513166346145910224582828425403465971492" + + "7260150227126350939033438077449255619231502836209591891037493966" + + "9366963730251619187615962926310287121840421140621429191345783703" + + "1"), + new BigInteger( + "8697498751458522624235585703214358189002281420472600166267178848" + + "9809876665869248037334395420081653868096056103537493131465377226" + + "0261527380426559408040456405219848362023445401145511114936506394" + + "6240472545398288332411818055040869427951279027405975059749360297" + + "5868667379863439430711990295232153128900808256212596912819669440" + + "8461633147852596585348243485566178333170181585431955731179108942" + + "1"), + new BigInteger( + "4252141813347264797276096871298065242070358505647997888003056375" + + "0053145248543520793105289129514510723624029989029530989695904117" + + "1040883775014117200916554841688641022136017868157290925811239787" + + "3664014299809018676076741787758620956387796785085878200748397774" + + "1000982778291877557074489243525397961477916369196578483491169386" + + "2005017885694815977695115290403992818456642027646266206320076800" + + "3"), + new BigInteger( + "3356647398302910967427184201762737607743709740247537918189248572" + + "1755339542838026890625250818518527348898974773340867800840791470" + + "3182072707032492007084043715576322632015800128489921814932124611" + + "2300036417841991332124497348096579076242448857352000771247540736" + + "1254949324799638105796121388483225300620211599611028678202393567" + + "8095635541751658983704832859578366318530922805928053806070359946" + + "1"), + new BigInteger( + "3687125575229624930459923973437509789116885700012081850445193578" + + "4486423768425089350932846437401841871613673810991112360643320652" + + "0225782089986669258803208183278659152741552450801685341843048568" + + "1125008729650000322084879372381541270180139663134377177885154388" + + "9558281508372272794193460069397070875763691455289959733530070186" + + "0360525342531389354962332229432027179470095997955180502375530175" + + "3"), + new BigInteger( + "6088560764944279853795552546797623009536823218028533977947580608" + + "2015023514992395624319060987001625566234648211868300524182306472" + + "7026872385780533326083682960047644674758988927136149502626557718" + + "2561494515318563339483672950711193945073071458843901227339418284" + + "3084182493461642555372639047162641075337152622892862251731700231" + + "6672547426448574167370804559242233207791080547486632014153528258" + + "1"), + new BigInteger( + "6081766267938901970682791123502557184373300073506187731779846380" + + "4083193288475152882563422230130613717216469536080649276981712202" + + "8895707724700107471391574673087393411637415445150131834443587280" + + "4243131225731630921851260690656608624225797294197741881140769183" + + "0474230365914155543155728342161658185646742117306992051014301383" + + "8040790841165308968256142923362988225719340573836171022480960175" + + "3"), + new BigInteger( + "5000879164859908887599881582814678322611278734193303790540199067" + + "6946804876309491380295619810590406766227048051997595053442615914" + + "2677702465219525342790323338314172797422380779526016709102650201" + + "6058553529785304239405043134061167377896985489252957729348463979" + + "6066933483020351454994081895283883114206539208013308687170796286" + + "8268752695525736731805658439398227370325903928664994918343915975" + + "3"), + new BigInteger( + "5033660524073962747735388920230339629907033897027296197974576730" + + "5654422857706257645566447425553553516325935964234373316093019314" + + "9125347663842235853602126989737378697014753612431648011618832921" + + "3881347704723060451053853932258315572365588301231482715348124261" + + "9244292433503547002496906691530720882968955274299548904791181715" + + "4190217453383503386985567684902027707247767653326442247588135031" + + "1"), + new BigInteger( + "7656692474335471169217545128846872228367812415627865759181393395" + + "8241618825828371173259648247363305034462523584509943049089351382" + + "5433879053475325827330864407124355159557574919864955631956757119" + + "9044097578241324151657090338112756973390540016908863938814598847" + + "5396824620980380695503598397306050849284639259137342875066075738" + + "4060141031090753207116787791385102134328808638802350088507846845" + + "1"), + new BigInteger( + "6916552449605114038869281931877716049700938960849845402874660241" + + "3416574115770967736955518993475194932835724065347138687353620520" + + "8331524408574865319265572656228099650675609929009824224767253657" + + "5459382651810818256784829505942965567114371502731619372511210627" + + "1610362520274480185346478545007812850057950851029848830710521787" + + "8356932374617076535457900683468313279449103472700012568700849319" + + "1"), + // F. Arnault, "Rabin-Miller primality test: composite numbers which pass it", Math. comp. + // v.64, n.209, p 355-361. + // + // A strong pseudoprime for the first 46 primes + new BigInteger( + "8038374574536394912570796143419421081388376882875581458374889175" + + "2229742737653336521865023361639600454579150420236032087665699667" + + "6098728404396540823292873879185086916685732826776177102938969773" + + "9470167082304286871099974399765441448453411558724506334092790222" + + "7529622941498423068816854043264575340183297861112989606448452161" + + "91652872597534901"), + // Richard G.E. Pinch, Absolute quadratic pseudorprimes + // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.210.6783&rep=rep1&type=pdf + // Lucas-Charmichael-(-) numbers + new BigInteger("28295303263921"), + new BigInteger("443372888629441"), + new BigInteger("582920080863121"), + new BigInteger("894221105778001"), + new BigInteger("2013745337604001"), + // Lucas-Charmichael-(+) numbers + new BigInteger("6479"), + new BigInteger("84419"), + new BigInteger("1930499"), + new BigInteger("7110179"), + new BigInteger("15857855"), + new BigInteger("63278892599"), + new BigInteger("79397009999"), + }; + + /** + * Tests BigInteger.isProbablePrime with a list of composite integers. The integers have been + * chosen to check for weak pseudoprimality tests. E.g., they are counterexamples to weak + * implementations. The implementation in jdk uses a combination of a Miller-Rabin test and a + * Lucas test. This is similar to the Baillie-PSW test + * https://en.wikipedia.org/wiki/Baillie%E2%80%93PSW_primality_test + */ + public void testIsProbablePrime() throws Exception { + // The probability that a non-prime passes should be at most 1-2^{-certainty}. + int certainty = 80; + for (BigInteger n : NONPRIMES) { + if (n.isProbablePrime(certainty)) { + fail("Composite number " + n.toString() + " passed as probable prime test"); + } + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/CipherInputStreamTest.java b/java/com/google/security/wycheproof/testcases/CipherInputStreamTest.java new file mode 100644 index 0000000..da7e4fb --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/CipherInputStreamTest.java @@ -0,0 +1,279 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import junit.framework.TestCase; + +/** CipherInputStream tests */ +public class CipherInputStreamTest extends TestCase { + static final SecureRandom rand = new SecureRandom(); + + static byte[] randomBytes(int size) { + byte[] bytes = new byte[size]; + rand.nextBytes(bytes); + return bytes; + } + + static SecretKeySpec randomKey(String algorithm, int keySizeInBytes) { + return new SecretKeySpec(randomBytes(keySizeInBytes), "AES"); + } + + static AlgorithmParameterSpec randomParameters( + String algorithm, int ivSizeInBytes, int tagSizeInBytes) { + if ("AES/GCM/NoPadding".equals(algorithm) || "AES/EAX/NoPadding".equals(algorithm)) { + return new GCMParameterSpec(8 * tagSizeInBytes, randomBytes(ivSizeInBytes)); + } + return null; + } + + /** Test vectors */ + public static class TestVector { + public String algorithm; + public SecretKeySpec key; + public AlgorithmParameterSpec params; + public byte[] pt; + public byte[] aad; + public byte[] ct; + + @SuppressWarnings("InsecureCryptoUsage") + public TestVector( + String algorithm, int keySize, int ivSize, int tagSize, int ptSize, int aadSize) + throws Exception { + this.algorithm = algorithm; + this.key = randomKey(algorithm, keySize); + this.params = randomParameters(algorithm, ivSize, tagSize); + this.pt = randomBytes(ptSize); + this.aad = randomBytes(aadSize); + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, this.key, this.params); + cipher.updateAAD(aad); + this.ct = cipher.doFinal(pt); + } + } + + Iterable<TestVector> getTestVectors( + String algorithm, + int[] keySizes, + int[] ivSizes, + int[] tagSizes, + int[] ptSizes, + int[] aadSizes) + throws Exception { + ArrayList<TestVector> result = new ArrayList<TestVector>(); + for (int keySize : keySizes) { + for (int ivSize : ivSizes) { + for (int tagSize : tagSizes) { + for (int ptSize : ptSizes) { + for (int aadSize : aadSizes) { + result.add(new TestVector(algorithm, keySize, ivSize, tagSize, ptSize, aadSize)); + } + } + } + } + } + return result; + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testEncrypt(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.ENCRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + InputStream is = new ByteArrayInputStream(t.pt); + CipherInputStream cis = new CipherInputStream(is, cipher); + byte[] result = new byte[t.ct.length]; + int totalLength = 0; + int length = 0; + do { + length = cis.read(result, totalLength, result.length - totalLength); + if (length > 0) { + totalLength += length; + } + } while (length >= 0 && totalLength != result.length); + assertEquals(-1, cis.read()); + assertEquals(TestUtil.bytesToHex(t.ct), TestUtil.bytesToHex(result)); + cis.close(); + } + } + + /** JDK-8016249: CipherInputStream in decrypt mode fails on close with AEAD ciphers */ + @SuppressWarnings("InsecureCryptoUsage") + public void testDecrypt(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.DECRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + InputStream is = new ByteArrayInputStream(t.ct); + CipherInputStream cis = new CipherInputStream(is, cipher); + byte[] result = new byte[t.pt.length]; + int totalLength = 0; + int length = 0; + do { + length = cis.read(result, totalLength, result.length - totalLength); + if (length > 0) { + totalLength += length; + } + } while (length >= 0 && totalLength != result.length); + assertEquals(-1, cis.read()); + cis.close(); + assertEquals(TestUtil.bytesToHex(t.pt), TestUtil.bytesToHex(result)); + } + } + + /** + * JDK-8016171 : CipherInputStream masks ciphertext tampering with AEAD ciphers in decrypt mode + * Further description of the bug is here: + * https://blog.heckel.xyz/2014/03/01/cipherinputstream-for-aead-modes-is-broken-in-jdk7-gcm/ + * BouncyCastle claims that this bug is fixed in version 1.51. However, the test below still fails + * with BouncyCastle v 1.52. A possible explanation is that BouncyCastle has its own + * implemenatation of CipherInputStream (org.bouncycastle.crypto.io.CipherInputStream). + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testCorruptDecrypt(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.DECRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + byte[] ct = Arrays.copyOf(t.ct, t.ct.length); + ct[ct.length - 1] ^= (byte) 1; + InputStream is = new ByteArrayInputStream(ct); + CipherInputStream cis = new CipherInputStream(is, cipher); + try { + byte[] result = new byte[t.pt.length]; + int totalLength = 0; + int length = 0; + do { + length = cis.read(result, totalLength, result.length - totalLength); + if (length > 0) { + totalLength += length; + } + } while (length >= 0 && totalLength != result.length); + cis.close(); + if (result.length > 0) { + fail( + "this should fail; decrypted:" + + TestUtil.bytesToHex(result) + + " pt: " + + TestUtil.bytesToHex(t.pt)); + } + } catch (IOException ex) { + // expected + } + } + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testCorruptDecryptEmpty(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.DECRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + byte[] ct = Arrays.copyOf(t.ct, t.ct.length); + ct[ct.length - 1] ^= (byte) 1; + InputStream is = new ByteArrayInputStream(ct); + CipherInputStream cis = new CipherInputStream(is, cipher); + try { + byte[] result = new byte[t.pt.length]; + int totalLength = 0; + int length = 0; + do { + length = cis.read(result, totalLength, result.length - totalLength); + if (length > 0) { + totalLength += length; + } + } while (length >= 0 && totalLength != result.length); + cis.close(); + fail("this should fail"); + } catch (IOException ex) { + // expected + } + } + } + + public void testAesGcm() throws Exception { + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {0, 8, 16, 65, 8100}; + final int[] aadSizes = {0, 8, 24}; + Iterable<TestVector> v = + getTestVectors("AES/GCM/NoPadding", keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testEncrypt(v); + testDecrypt(v); + } + + public void testCorruptAesGcm() throws Exception { + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {8, 16, 65, 8100}; + final int[] aadSizes = {0, 8, 24}; + Iterable<TestVector> v = + getTestVectors("AES/GCM/NoPadding", keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testCorruptDecrypt(v); + } + + /** + * Unfortunately Oracle thinks that returning an empty array is valid behaviour for corrupt + * ciphertexts. Because of this we test empty plaintext separately to distinguish behaviour + * considered acceptable by Oracle from other behaviour. + */ + public void testEmptyPlaintext() throws Exception { + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {0}; + final int[] aadSizes = {0, 8, 24}; + Iterable<TestVector> v = + getTestVectors("AES/GCM/NoPadding", keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testCorruptDecryptEmpty(v); + } + + /** Tests CipherOutputStream with AES-EAX if this algorithm is supported by the provider. */ + public void testAesEax() throws Exception { + final String algorithm = "AES/EAX/NoPadding"; + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12, 16}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {0, 8, 16, 65, 8100}; + final int[] aadSizes = {0, 8, 24}; + try { + Cipher.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + System.out.println("Skipping testAesEax"); + return; + } + Iterable<TestVector> v = + getTestVectors(algorithm, keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testEncrypt(v); + testDecrypt(v); + testCorruptDecrypt(v); + } +} diff --git a/java/com/google/security/wycheproof/testcases/CipherOutputStreamTest.java b/java/com/google/security/wycheproof/testcases/CipherOutputStreamTest.java new file mode 100644 index 0000000..e4f288a --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/CipherOutputStreamTest.java @@ -0,0 +1,239 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.CipherOutputStream; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import junit.framework.TestCase; + +/** CipherOutputStream tests */ +public class CipherOutputStreamTest extends TestCase { + static final SecureRandom rand = new SecureRandom(); + + static byte[] randomBytes(int size) { + byte[] bytes = new byte[size]; + rand.nextBytes(bytes); + return bytes; + } + + static SecretKeySpec randomKey(String algorithm, int keySizeInBytes) { + return new SecretKeySpec(randomBytes(keySizeInBytes), "AES"); + } + + static AlgorithmParameterSpec randomParameters( + String algorithm, int ivSizeInBytes, int tagSizeInBytes) { + if ("AES/GCM/NoPadding".equals(algorithm) || "AES/EAX/NoPadding".equals(algorithm)) { + return new GCMParameterSpec(8 * tagSizeInBytes, randomBytes(ivSizeInBytes)); + } + return null; + } + + /** Test vectors */ + @SuppressWarnings("InsecureCryptoUsage") + public static class TestVector { + public String algorithm; + public SecretKeySpec key; + public AlgorithmParameterSpec params; + public byte[] pt; + public byte[] aad; + public byte[] ct; + + public TestVector( + String algorithm, int keySize, int ivSize, int tagSize, int ptSize, int aadSize) + throws Exception { + this.algorithm = algorithm; + this.key = randomKey(algorithm, keySize); + this.params = randomParameters(algorithm, ivSize, tagSize); + this.pt = randomBytes(ptSize); + this.aad = randomBytes(aadSize); + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, this.key, this.params); + cipher.updateAAD(aad); + this.ct = cipher.doFinal(pt); + } + } + + Iterable<TestVector> getTestVectors( + String algorithm, + int[] keySizes, + int[] ivSizes, + int[] tagSizes, + int[] ptSizes, + int[] aadSizes) + throws Exception { + ArrayList<TestVector> result = new ArrayList<TestVector>(); + for (int keySize : keySizes) { + for (int ivSize : ivSizes) { + for (int tagSize : tagSizes) { + for (int ptSize : ptSizes) { + for (int aadSize : aadSizes) { + result.add(new TestVector(algorithm, keySize, ivSize, tagSize, ptSize, aadSize)); + } + } + } + } + } + return result; + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testEncrypt(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.ENCRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + CipherOutputStream cos = new CipherOutputStream(os, cipher); + cos.write(t.pt); + cos.close(); + assertEquals(TestUtil.bytesToHex(t.ct), TestUtil.bytesToHex(os.toByteArray())); + } + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testDecrypt(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.DECRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + CipherOutputStream cos = new CipherOutputStream(os, cipher); + cos.write(t.ct); + cos.close(); + assertEquals(TestUtil.bytesToHex(t.pt), TestUtil.bytesToHex(os.toByteArray())); + } + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testCorruptDecrypt(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.DECRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + byte[] ct = Arrays.copyOf(t.ct, t.ct.length); + ct[ct.length - 1] ^= (byte) 1; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + CipherOutputStream cos = new CipherOutputStream(os, cipher); + cos.write(ct); + try { + // cos.close() should call cipher.doFinal(). + cos.close(); + byte[] decrypted = os.toByteArray(); + // Unfortunately Oracle thinks that returning an empty array is valid behaviour. + // We accept empty results here, but flag them in the next test, so that we can distinguish + // between beheviour considered acceptable by Oracle and more serious flaws. + if (decrypted.length > 0) { + fail( + "this should fail; decrypted:" + + TestUtil.bytesToHex(decrypted) + + " pt: " + + TestUtil.bytesToHex(t.pt)); + } + } catch (IOException ex) { + // expected + } + } + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testCorruptDecryptEmpty(Iterable<TestVector> tests) throws Exception { + for (TestVector t : tests) { + Cipher cipher = Cipher.getInstance(t.algorithm); + cipher.init(Cipher.DECRYPT_MODE, t.key, t.params); + cipher.updateAAD(t.aad); + byte[] ct = Arrays.copyOf(t.ct, t.ct.length); + ct[ct.length - 1] ^= (byte) 1; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + CipherOutputStream cos = new CipherOutputStream(os, cipher); + cos.write(ct); + try { + // cos.close() should call cipher.doFinal(). + cos.close(); + byte[] decrypted = os.toByteArray(); + fail( + "this should fail; decrypted:" + + TestUtil.bytesToHex(decrypted) + + " pt: " + + TestUtil.bytesToHex(t.pt)); + } catch (IOException ex) { + // expected + } + } + } + + public void testAesGcm() throws Exception { + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {8, 16, 65, 8100}; + final int[] aadSizes = {0, 8, 24}; + Iterable<TestVector> v = + getTestVectors("AES/GCM/NoPadding", keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testEncrypt(v); + testDecrypt(v); + testCorruptDecrypt(v); + } + + /** + * Unfortunately Oracle thinks that returning an empty array is valid behaviour for corrupt + * ciphertexts. Because of this we test empty plaintext separately to distinguish behaviour + * considered acceptable by Oracle from other behaviour. + */ + public void testEmptyPlaintext() throws Exception { + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {0}; + final int[] aadSizes = {0, 8, 24}; + Iterable<TestVector> v = + getTestVectors("AES/GCM/NoPadding", keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testEncrypt(v); + testDecrypt(v); + testCorruptDecryptEmpty(v); + } + + /** Tests CipherOutputStream with AES-EAX if AES-EAS is supported by the provider. */ + @SuppressWarnings("InsecureCryptoUsage") + public void testAesEax() throws Exception { + final String algorithm = "AES/EAX/NoPadding"; + final int[] keySizes = {16, 32}; + final int[] ivSizes = {12, 16}; + final int[] tagSizes = {12, 16}; + final int[] ptSizes = {8, 16, 65, 8100}; + final int[] aadSizes = {0, 8, 24}; + try { + Cipher.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + System.out.println("Skipping testAesEax"); + return; + } + Iterable<TestVector> v = + getTestVectors(algorithm, keySizes, ivSizes, tagSizes, ptSizes, aadSizes); + testEncrypt(v); + testDecrypt(v); + testCorruptDecrypt(v); + } +} diff --git a/java/com/google/security/wycheproof/testcases/DhTest.java b/java/com/google/security/wycheproof/testcases/DhTest.java new file mode 100644 index 0000000..32ab83a --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/DhTest.java @@ -0,0 +1,402 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import com.google.security.wycheproof.WycheproofRunner.SlowTest; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import javax.crypto.KeyAgreement; +import javax.crypto.interfaces.DHPrivateKey; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec; +import junit.framework.TestCase; + +/** + * Testing Diffie-Hellman key agreement. + * + * <p>Subgroup confinment attacks: + * The papers by van Oorshot and Wiener rsp. Lim and Lee show that Diffie-Hellman keys can + * be found much faster if the short exponents are used and if the multiplicative group modulo p + * contains small subgroups. In particular an attacker can try to send a public key that is an + * element of a small subgroup. If the receiver does not check for such elements then may be + * possible to find the private key modulo the order of the small subgroup. + * Several countermeasures against such attacks have been proposed: For example IKE uses + * fields of order p where p is a safe prime (i.e. q=(p-1)/2), hence the only elements of small + * order are 1 and p-1. + * NIST SP 800-56A rev. 2, Section 5.5.1.1 only requires that the size of the subgroup generated + * by the generator g is big enough to prevent the baby-step giant-step algorithm. I.e. for 80-bit + * security p must be at least 1024 bits long and the prime q must be at least 160 bits long. A 2048 + * bit prime p and a 224 bit prime q are sufficient for 112 bit security. To avoid subgroup + * confinment attacks NIST requires that public keys are validated, i.e. by checking that a public + * key y satisfies the conditions 2 <= y <= p-2 and y^q mod p == 1 (Section 5.6.2.3.1). Further, + * after generating the shared secret z = y_a ^ x_b mod p each party should check that z != 1. RFC + * 2785 contains similar recommendations. + * The public key validation described by NIST requires that the order q of the generator g + * is known to the verifier. Unfortunately, the order q is missing in PKCS #3. PKCS #3 describes + * the Diffie-Hellman parameters only by the values p, g and optionally the key size in bits. + * + * <p>The class DHParameterSpec that defines the Diffie-Hellman parameters in JCE contains the same + * values as PKCS#3. In particular, it does not contain the order of the subgroup q. + * Moreover, the SUN provider uses the minimal sizes specified by NIST for q. + * Essentially the provider reuses the parameters for DSA. + * + * <p>Therefore, there is no guarantee that an implementation of Diffie-Hellman is secure against + * subgroup confinement attacks. Without a key validation it is insecure to use the key-pair + * generation from NIST SP 800-56A Section 5.6.1.1 (The key-pair generation there only requires that + * static and ephemeral private keys are randomly chosen in the range 1..q-1). + * + * <p>To avoid big disasters the tests below require that key sizes are not minimal. I.e., currently + * the tests require at least 512 bit keys for 1024 bit fields. We use this lower limit because that + * is what the SUN provider is currently doing. TODO(bleichen): Find a reference supporting or + * disproving that decision. + * + * <p>References: P. C. van Oorschot, M. J. Wiener, "On Diffie-Hellman key agreement with short + * exponents", Eurocrypt 96, pp 332–343. + * + * <p>C.H. Lim and P.J. Lee, "A key recovery attack on discrete log-based schemes using a prime + * order subgroup", CRYPTO' 98, pp 249–263. + * + * <p>NIST SP 800-56A, revision 2, May 2013 + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf + * + * <p>PKCS #3, Diffie–Hellman Key Agreement + * http://uk.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm + * + * <p>RFC 2785, "Methods for Avoiding 'Small-Subgroup' Attacks on the Diffie-Hellman Key Agreement + * Method for S/MIME", March 2000 + * https://www.ietf.org/rfc/rfc2785.txt + * + * <p>D. Adrian et al. "Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice" + * https://weakdh.org/imperfect-forward-secrecy-ccs15.pdf + * A good analysis of various DH implementations. + * Some misconfigurations pointed out in the paper are: p is composite, p-1 contains no large + * prime factor, q is used instead of the generator g. + * + * <p>Sources that might be used for additional tests: + * + * CVE-2015-3193: The Montgomery squaring implementation in crypto/bn/asm/x86_64-mont5.pl + * in OpenSSL 1.0.2 before 1.0.2e on the x86_64 platform, as used by the BN_mod_exp function, + * mishandles carry propagation + * https://blog.fuzzing-project.org/31-Fuzzing-Math-miscalculations-in-OpenSSLs-BN_mod_exp-CVE-2015-3193.html + * + * <p>CVE-2016-0739: libssh before 0.7.3 improperly truncates ephemeral secrets generated for the + * (1) diffie-hellman-group1 and (2) diffie-hellman-group14 key exchange methods to 128 bits ... + * + * <p>CVE-2015-1787 The ssl3_get_client_key_exchange function in s3_srvr.c in OpenSSL 1.0.2 before + * 1.0.2a, when client authentication and an ephemeral Diffie-Hellman ciphersuite are enabled, + * allows remote attackers to cause a denial of service (daemon crash) via a ClientKeyExchange + * message with a length of zero. + * + * <p>CVE-2015-0205 The ssl3_get_cert_verify function in s3_srvr.c in OpenSSL 1.0.0 before 1.0.0p + * and 1.0.1 before 1.0.1k accepts client authentication with a Diffie-Hellman (DH) certificate + * without requiring a CertificateVerify message, which allows remote attackers to obtain access + * without knowledge of a private key via crafted TLS Handshake Protocol traffic to a server that + * recognizes a Certification Authority with DH support. + * + * <p>CVE-2016-0701 The DH_check_pub_key function in crypto/dh/dh_check.c in OpenSSL 1.0.2 before + * 1.0.2f does not ensure that prime numbers are appropriate for Diffie-Hellman (DH) key exchange, + * which makes it easier for remote attackers to discover a private DH exponent by making multiple + * handshakes with a peer that chose an inappropriate number, as demonstrated by a number in an + * X9.42 file. + * + * <p>CVE-2006-1115 nCipher HSM before 2.22.6, when generating a Diffie-Hellman public/private key + * pair without any specified DiscreteLogGroup parameters, chooses random parameters that could + * allow an attacker to crack the private key in significantly less time than a brute force attack. + * + * <p>CVE-2015-1716 Schannel in Microsoft Windows Server 2003 SP2, Windows Vista SP2, Windows Server + * 2008 SP2 and R2 SP1, Windows 7 SP1, Windows 8, Windows 8.1, Windows Server 2012 Gold and R2, and + * Windows RT Gold and 8.1 does not properly restrict Diffie-Hellman Ephemeral (DHE) key lengths, + * which makes it easier for remote attackers to defeat cryptographic protection mechanisms via + * unspecified vectors, aka "Schannel Information Disclosure Vulnerability. + * + * <p>CVE-2015-2419: Random generation of the prime p allows Pohlig-Hellman and probably other + * stuff. + * + * <p> J. Fried et al. "A kilobit hidden SNFS discrete logarithm computation". + * http://eprint.iacr.org/2016/961.pdf + * Some crypto libraries use fields that can be broken with the SNFS. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +public class DhTest extends TestCase { + public DHParameterSpec ike1536() { + final BigInteger p = + new BigInteger( + "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" + + "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" + + "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" + + "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf05" + + "98da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb" + + "9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff", + 16); + final BigInteger g = new BigInteger("2"); + return new DHParameterSpec(p, g); + } + + public DHParameterSpec ike2048() { + final BigInteger p = + new BigInteger( + "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74" + + "020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f1437" + + "4fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7ed" + + "ee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf05" + + "98da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb" + + "9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3b" + + "e39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf695581718" + + "3995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff", + 16); + final BigInteger g = new BigInteger("2"); + return new DHParameterSpec(p, g); + } + + // The default parameters returned for 1024 bit DH keys from OpenJdk as defined in + // openjdk7/releases/v6/trunk/jdk/src/share/classes/sun/security/provider/ParameterCache.java + // I.e., these are the same parameters as used for DSA. + public DHParameterSpec openJdk1024() { + final BigInteger p = + new BigInteger( + "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669" + + "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7" + + "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb" + + "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", + 16); + final BigInteger unusedQ = new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16); + final BigInteger g = + new BigInteger( + "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267" + + "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1" + + "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b" + + "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", + 16); + return new DHParameterSpec(p, g); + } + + /** Check that key agreement using DH works. */ + @SuppressWarnings("InsecureCryptoUsage") + public void testDh() throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); + DHParameterSpec dhparams = ike2048(); + keyGen.initialize(dhparams); + KeyPair keyPairA = keyGen.generateKeyPair(); + KeyPair keyPairB = keyGen.generateKeyPair(); + + KeyAgreement kaA = KeyAgreement.getInstance("DH"); + KeyAgreement kaB = KeyAgreement.getInstance("DH"); + kaA.init(keyPairA.getPrivate()); + kaB.init(keyPairB.getPrivate()); + kaA.doPhase(keyPairB.getPublic(), true); + kaB.doPhase(keyPairA.getPublic(), true); + byte[] kAB = kaA.generateSecret(); + byte[] kBA = kaB.generateSecret(); + assertEquals(TestUtil.bytesToHex(kAB), TestUtil.bytesToHex(kBA)); + } + + /** + * Returns the product of primes that can be found by a simple variant of Pollard-rho. + * The result should contain all prime factors of n smaller than 10^8. + * This method is heuristic, since it could in principle find large prime factors too. + * However, for a random 160-bit prime q the probability of this should be less than 2^{-100}. + */ + private BigInteger smoothDivisor(BigInteger n) { + // By examination we verified that for every prime p < 10^8 + // the iteration x_n = x_{n-1}^2 + 1 mod p enters a cycle of size < 50000 after at + // most 50000 steps. + int pollardRhoSteps = 50000; + BigInteger u = new BigInteger("2"); + for (int i = 0; i < pollardRhoSteps; i++) { + u = u.multiply(u).add(BigInteger.ONE).mod(n); + } + BigInteger v = u; + BigInteger prod = BigInteger.ONE; + for (int i = 0; i < pollardRhoSteps; i++) { + v = v.multiply(v).add(BigInteger.ONE).mod(n); + // This implementation is only looking for the product of small primes. + // Therefore, instead of continuously computing gcds of v-u and n, it is sufficient + // and more efficient to compute the product of of v-u for all v and compute the gcd + // at the end. + prod = prod.multiply(v.subtract(u).abs()).mod(n); + } + BigInteger result = BigInteger.ONE; + while (true) { + BigInteger f = n.gcd(prod); + if (f.equals(BigInteger.ONE)) { + return result; + } + result = result.multiply(f); + n = n.divide(f); + } + } + + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE}) + public void testKeyPair(KeyPair keyPair, int expectedKeySize) throws Exception { + DHPrivateKey priv = (DHPrivateKey) keyPair.getPrivate(); + BigInteger p = priv.getParams().getP(); + BigInteger g = priv.getParams().getG(); + int keySize = p.bitLength(); + assertEquals("wrong key size", keySize, expectedKeySize); + + // Checks the key size of the private key. + // NIST SP 800-56A requires that x is in the range (1, q-1). + // Such a choice would require a full key validation. Since such a validation + // requires the value q (which is not present in the DH parameters) larger keys + // should be chosen to prevent attacks. + int minPrivateKeyBits = keySize / 2; + BigInteger x = priv.getX(); + assertTrue(x.bitLength() >= minPrivateKeyBits - 32); + // TODO(bleichen): add tests for weak random number generators. + + // Verify the DH parameters. + System.out.println("p=" + p.toString(16)); + System.out.println("g=" + g.toString(16)); + System.out.println("testKeyPairGenerator L=" + priv.getParams().getL()); + // Basic parameter checks + assertTrue("Expecting g > 1", g.compareTo(BigInteger.ONE) > 0); + assertTrue("Expecting g < p - 1", g.compareTo(p.subtract(BigInteger.ONE)) < 0); + // Expecting p to be prime. + // No high certainty is needed, since this is a unit test. + assertTrue(p.isProbablePrime(4)); + // The order of g should be a large prime divisor q of p-1. + // (see e.g. NIST SP 800-56A, section 5.5.1.1.) + // If the order of g is composite then the the Decision Diffie Hellman assumption is + // not satisfied for the group generated by g. Moreover, attacks using Pohlig-Hellman + // might be feasible. + // A good way to achieve these requirements is to select a safe prime p (i.e. a prime + // where q=(p-1)/2 is prime too. NIST SP 800-56A does not require (or even recommend) + // safe primes and allows Diffie-Hellman parameters where q is significantly smaller. + // Unfortunately, the key does not contain q and thus the conditions above cannot be + // tested easily. + // We perform a partial test that performs a partial factorization of p-1 and then + // test whether one of the small factors found by the partial factorization divides + // the order of g. + boolean isSafePrime = p.shiftRight(1).isProbablePrime(4); + System.out.println("p is a safe prime:" + isSafePrime); + BigInteger r; // p-1 divided by small prime factors. + if (isSafePrime) { + r = p.shiftRight(1); + } else { + BigInteger p1 = p.subtract(BigInteger.ONE); + r = p1.divide(smoothDivisor(p1)); + } + System.out.println("r=" + r.toString(16)); + assertEquals("g likely does not generate a prime oder subgroup", BigInteger.ONE, + g.modPow(r, p)); + + // Checks that there are not too many short prime factors. + // I.e., subgroup confinment attacks can find at least keySize - r.bitLength() bits of the key. + // At least 160 unknown bits should remain. + // Only very weak parameters are detected here, since the factorization above only finds small + // prime factors. + assertTrue(minPrivateKeyBits - (keySize - r.bitLength()) > 160); + + // DH parameters are sometime misconfigures and g and q are swapped. + // A large g that divides p-1 is suspicious. + if (g.bitLength() >= 160) { + assertTrue(p.mod(g).compareTo(BigInteger.ONE) > 0); + } + } + + /** + * Tests Diffie-Hellman key pair generation. + * + * <p> This is a slow test since some providers (e.g. BouncyCastle) generate new safe primes + * for each new key. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testKeyPairGenerator() throws Exception { + int keySize = 1024; + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); + keyGen.initialize(keySize); + KeyPair keyPair = keyGen.generateKeyPair(); + testKeyPair(keyPair, keySize); + } + + /** This test tries a key agreement with keys using distinct parameters. */ + @SuppressWarnings("InsecureCryptoUsage") + public void testDHDistinctParameters() throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); + keyGen.initialize(ike1536()); + KeyPair keyPairA = keyGen.generateKeyPair(); + + keyGen.initialize(ike2048()); + KeyPair keyPairB = keyGen.generateKeyPair(); + + KeyAgreement kaA = KeyAgreement.getInstance("DH"); + kaA.init(keyPairA.getPrivate()); + try { + kaA.doPhase(keyPairB.getPublic(), true); + byte[] kAB = kaA.generateSecret(); + fail("Generated secrets with mixed keys " + TestUtil.bytesToHex(kAB) + ", "); + } catch (java.security.GeneralSecurityException ex) { + // This is expected. + } + } + + /** + * Tests whether a provider accepts invalid public keys that result in predictable shared secrets. + * This test is based on RFC 2785, Section 4 and NIST SP 800-56A, If an attacker can modify both + * public keys in an ephemeral-ephemeral key agreement scheme then it may be possible to coerce + * both parties into computing the same predictable shared key. + * + * <p> Note: the test is quite whimsical. If the prime p is not a safe prime then the provider + * itself cannot prevent all small-subgroup attacks because of the missing parameter q in the + * Diffie-Hellman parameters. Implementations must add additional countermeasures such as the ones + * proposed in RFC 2785. + * + * <p> CVE-2016-1000346: BouncyCastle before v.1.56 did not validate the other parties public key. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testSubgroupConfinement() throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); + DHParameterSpec params = ike2048(); + BigInteger p = params.getP(); + BigInteger g = params.getG(); + keyGen.initialize(params); + PrivateKey priv = keyGen.generateKeyPair().getPrivate(); + KeyAgreement ka = KeyAgreement.getInstance("DH"); + BigInteger[] weakPublicKeys = { + BigInteger.ZERO, + BigInteger.ONE, + p.subtract(BigInteger.ONE), + p, + p.add(BigInteger.ONE), + BigInteger.ONE.negate() + }; + for (BigInteger weakKey : weakPublicKeys) { + ka.init(priv); + try { + KeyFactory kf = KeyFactory.getInstance("DH"); + DHPublicKeySpec weakSpec = new DHPublicKeySpec(weakKey, p, g); + PublicKey pub = kf.generatePublic(weakSpec); + ka.doPhase(pub, true); + byte[] kAB = ka.generateSecret(); + fail( + "Generated secrets with weak public key:" + + weakKey.toString() + + " secret:" + + TestUtil.bytesToHex(kAB)); + } catch (GeneralSecurityException ex) { + // this is expected + } + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/DhiesTest.java b/java/com/google/security/wycheproof/testcases/DhiesTest.java new file mode 100644 index 0000000..2a4815c --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/DhiesTest.java @@ -0,0 +1,172 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import com.google.security.wycheproof.WycheproofRunner.SlowTest; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.Arrays; +import javax.crypto.Cipher; +import javax.crypto.spec.DHParameterSpec; +import junit.framework.TestCase; + +/** + * Testing DHIES. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// TODO(bleichen): +// - maybe again CipherInputStream, CipherOutputStream, +// - byteBuffer. +// - Exception handling +// - Is DHIES using the key derivation function for the key stream? +// - BouncyCastle knows an algorithm IES. Is this the same as DHIES? +// - Bouncy fixed a padding oracle bug in version 1.56 (CVE-2016-1000345) +// So far we have no test for this bug mainly because this cannot be tested +// through the JCA interface. BC does not register and algorithm such as +// Cipher.DHIESWITHAES-CBC. +// - So far only BouncyCastles is tesed because this is the only provider +// we use that implements DHIES. +public class DhiesTest extends TestCase { + + // TODO(bleichen): This is the same as DhTest.java + // We could move this into some TestUtil. + public DHParameterSpec ike2048() { + final BigInteger p = + new BigInteger( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", + 16); + final BigInteger g = new BigInteger("2"); + return new DHParameterSpec(p, g); + } + + /** + * WARNING: This test uses weak crypto (i.e. DHIESWithAES), if supported. Checks that key + * agreement using DHIES works in the sense that it can decrypt what it encrypts. Unfortunately it + * seems that there is no secure mode using AES. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testDhiesBasic() throws Exception { + DHParameterSpec params = ike2048(); + KeyPairGenerator kf = KeyPairGenerator.getInstance("DH"); + kf.initialize(params); + KeyPair keyPair = kf.generateKeyPair(); + PrivateKey priv = keyPair.getPrivate(); + PublicKey pub = keyPair.getPublic(); + byte[] message = "Hello".getBytes("UTF-8"); + Cipher dhies; + try { + dhies = Cipher.getInstance("DHIESwithAES"); + } catch (NoSuchAlgorithmException ex) { + // The algorithm isn't supported - even better! + return; + } + dhies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = dhies.doFinal(message); + System.out.println("testDhiesBasic:" + TestUtil.bytesToHex(ciphertext)); + dhies.init(Cipher.DECRYPT_MODE, priv); + byte[] decrypted = dhies.doFinal(ciphertext); + assertEquals(TestUtil.bytesToHex(message), TestUtil.bytesToHex(decrypted)); + } + + /** + * WARNING: This test uses weak crypto (i.e. DHIESWithAES). DHIES should be secure against chosen + * ciphertexts. Checks that a modification of the ciphertext is dectected. + */ + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE}) + @SuppressWarnings("InsecureCryptoUsage") + public void testDhiesCorrupt() throws Exception { + KeyPairGenerator kf = KeyPairGenerator.getInstance("DH"); + kf.initialize(ike2048()); + KeyPair keyPair = kf.generateKeyPair(); + PrivateKey priv = keyPair.getPrivate(); + PublicKey pub = keyPair.getPublic(); + byte[] message = new byte[32]; + Cipher dhies; + try { + dhies = Cipher.getInstance("DHIESwithAES"); + } catch (NoSuchAlgorithmException ex) { + // The algorithm isn't supported - even better! + return; + } + dhies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = dhies.doFinal(message); + for (int i = 0; i < ciphertext.length; i++) { + byte[] corrupt = Arrays.copyOf(ciphertext, ciphertext.length); + corrupt[i] ^= (byte) 1; + try { + dhies.init(Cipher.DECRYPT_MODE, priv); + dhies.doFinal(corrupt); + fail("Corrupt ciphertext accepted:" + i); + } catch (GeneralSecurityException ex) { + // This is expected + } + } + } + + /** + * Tries to detect if an algorithm is using ECB. Unfortunately, many JCE algorithms use ECB if no + * encryption mode is specified. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testNotEcb(String algorithm) throws Exception { + Cipher dhies; + try { + dhies = Cipher.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + // This test is called with short algorithm names such as just "DHIES". + // Requiring full names is typically a good practice. Hence it is OK + // to not assigning default algorithms. + System.out.println("No implementation for:" + algorithm); + return; + } + KeyPairGenerator kf = KeyPairGenerator.getInstance("DH"); + kf.initialize(ike2048()); + KeyPair keyPair = kf.generateKeyPair(); + PublicKey pub = keyPair.getPublic(); + byte[] message = new byte[512]; + dhies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = dhies.doFinal(message); + for (int i = 0; i + 32 <= ciphertext.length; i++) { + String block1 = TestUtil.bytesToHex(Arrays.copyOfRange(ciphertext, i, i + 16)); + String block2 = TestUtil.bytesToHex(Arrays.copyOfRange(ciphertext, i + 16, i + 32)); + assertTrue( + "Ciphertext repeats at " + i + ":" + TestUtil.bytesToHex(ciphertext), + !block1.equals(block2)); + } + } + + public void testSemanticSecurityDhies() throws Exception { + testNotEcb("DHIES"); + } +} diff --git a/java/com/google/security/wycheproof/testcases/DsaTest.java b/java/com/google/security/wycheproof/testcases/DsaTest.java new file mode 100644 index 0000000..edfaa74 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/DsaTest.java @@ -0,0 +1,1144 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(bleichen): +// - add tests for SHA1WithDSA with wrong key +// - add tests for "alternative" algorithm names +// - convert tests for deterministic DSA variants. +// Deterministic DSA has a few new drawbacks: +// * implementations flaws that generate k incorrectly can leak +// the key if multiple implementations (e.g. one correct one incorrect) +// is used. +// * timing attacks are more serious if the attacker can ask for the same +// signature multiple times, since this allows to get more accurate timings. +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import com.google.security.wycheproof.WycheproofRunner.SlowTest; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.util.Arrays; +import javax.crypto.Cipher; +import junit.framework.TestCase; + +/** + * Tests DSA against invalid signatures. The motivation for this test is the DSA implementation in + * gpg4browsers. This implementation accepts signatures with r=1 and s=0 as valid. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +public class DsaTest extends TestCase { + static final String MESSAGE = "Hello"; + + static final DSAPrivateKeySpec privateKey1 = + new DSAPrivateKeySpec( + // x + new BigInteger("15382583218386677486843706921635237927801862255437148328980464126979"), + // p + new BigInteger( + "181118486631420055711787706248812146965913392568235070235446058914" + + "1170708161715231951918020125044061516370042605439640379530343556" + + "4101919053459832890139496933938670005799610981765220283775567361" + + "4836626483403394052203488713085936276470766894079318754834062443" + + "1033792580942743268186462355159813630244169054658542719322425431" + + "4088256212718983105131138772434658820375111735710449331518776858" + + "7867938758654181244292694091187568128410190746310049564097068770" + + "8161261634790060655580211122402292101772553741704724263582994973" + + "9109274666495826205002104010355456981211025738812433088757102520" + + "562459649777989718122219159982614304359"), + // q + new BigInteger("19689526866605154788513693571065914024068069442724893395618704484701"), + // g + new BigInteger( + "2859278237642201956931085611015389087970918161297522023542900348" + + "0877180630984239764282523693409675060100542360520959501692726128" + + "3149190229583566074777557293475747419473934711587072321756053067" + + "2532404847508798651915566434553729839971841903983916294692452760" + + "2490198571084091890169933809199002313226100830607842692992570749" + + "0504363602970812128803790973955960534785317485341020833424202774" + + "0275688698461842637641566056165699733710043802697192696426360843" + + "1736206792141319514001488556117408586108219135730880594044593648" + + "9237302749293603778933701187571075920849848690861126195402696457" + + "4111219599568903257472567764789616958430")); + + static final DSAPublicKeySpec publicKey1 = + new DSAPublicKeySpec( + new BigInteger( + "3846308446317351758462473207111709291533523711306097971550086650" + + "2577333637930103311673872185522385807498738696446063139653693222" + + "3528823234976869516765207838304932337200968476150071617737755913" + + "3181601169463467065599372409821150709457431511200322947508290005" + + "1780020974429072640276810306302799924668893998032630777409440831" + + "4314588994475223696460940116068336991199969153649625334724122468" + + "7497038281983541563359385775312520539189474547346202842754393945" + + "8755803223951078082197762886933401284142487322057236814878262166" + + "5072306622943221607031324846468109901964841479558565694763440972" + + "5447389416166053148132419345627682740529"), + privateKey1.getP(), + privateKey1.getQ(), + privateKey1.getG()); + + // Signatures for Key1. + static final String[] VALID_SIGNATURES = { + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + }; + + /** + * The following test vectos are derived from a valid signature by + * using alternative BER encoding as well as legacy formats. + * Accepting such signatures is in many cases benign. Hence the tests + * below will pass if such signatures are accepted as valid. + * The test vectors could be used to check for signature malleability. + * An example where this kind of signature malleability was a problem is + * https://en.bitcoin.it/wiki/Transaction_Malleability + */ + static final String[] MODIFIED_SIGNATURES = { + // BER:long form encoding of length + "30813d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e02811c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "02811d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // BER:length contains leading 0 + "3082003d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + "303f0282001c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0282001d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + // BER:prepending 0's to integer + "303f021e00001e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021f000000ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + // The Sun provider accepts DSA signatures where a leading 00 has + // been omitted in the ASN encoding. + "303c021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021cade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + }; + + /** + * The following test vectors are invalid DSA signatures. + * According to {@link java.security.Signature#verify(byte[])} verifying an invalid + * signature may either return false or throw a SignatureException. + * We expect that a correct implementation of DSA signatures satisfies this contract. + * Throwing a RuntimeException instead of a SignatureException could for example + * result in a denial of service attack. + * + * <p>A list of problems that are caught by these signatures: + * <li> CVE-2016-5546: OpenJDK8 throwed java.lang.ArrayIndexOutOfBoundsException for + * some invalid DSA signatures. + * </ul> + */ + static final String[] INVALID_SIGNATURES = { + // wrong length + "303e021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303c021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021d1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021b1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021e00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021c00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // uint32 overflow in length + "3085010000003d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916" + + "173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813f" + + "e8786236", + "30420285010000001c1e41b479ad576905b960fe14eadb91b0ccf34843dab916" + + "173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813f" + + "e8786236", + "3042021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0285010000001d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813f" + + "e8786236", + // uint64 overflow in length + "308901000000000000003d021c1e41b479ad576905b960fe14eadb91b0ccf348" + + "43dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf" + + "3365813fe8786236", + "3046028901000000000000001c1e41b479ad576905b960fe14eadb91b0ccf348" + + "43dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf" + + "3365813fe8786236", + "3046021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "028901000000000000001d00ade65988d237d30f9ef41dd424a4e1c8f16967cf" + + "3365813fe8786236", + // length = 2**31 - 1 + "30847fffffff021c1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "304102847fffffff1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "3041021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "02847fffffff00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + // length = 2**32 - 1 + "3084ffffffff021c1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "30410284ffffffff1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "3041021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0284ffffffff00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + // length = 2**64 - 1 + "3088ffffffffffffffff021c1e41b479ad576905b960fe14eadb91b0ccf34843" + + "dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + "30450288ffffffffffffffff1e41b479ad576905b960fe14eadb91b0ccf34843" + + "dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + "3045021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0288ffffffffffffffff00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + // removing sequence + "", + // appending 0's to sequence + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe878623600" + + "00", + // prepending 0's to sequence + "303f0000021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + // appending unused 0's + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0000021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + // appending null value + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe878623605" + + "00", + "303f021e1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0500021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021f00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe878623605" + + "00", + // including garbage + "3042498177303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916" + + "173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813f" + + "e8786236", + "30412500303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "303f303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "360004deadbeef", + "30422221498177021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916" + + "173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813f" + + "e8786236", + "304122202500021c1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "3045221e021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd0004deadbeef021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + "3042021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "2222498177021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813f" + + "e8786236", + "3041021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "22212500021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "3045021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "221f021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "360004deadbeef", + // including undefined tags + "3045aa00bb00cd00303d021c1e41b479ad576905b960fe14eadb91b0ccf34843" + + "dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + "3043aa02aabb303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab9" + + "16173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf336581" + + "3fe8786236", + "30452224aa00bb00cd00021c1e41b479ad576905b960fe14eadb91b0ccf34843" + + "dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + "30432222aa02aabb021c1e41b479ad576905b960fe14eadb91b0ccf34843dab9" + + "16173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf336581" + + "3fe8786236", + "3045021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "2225aa00bb00cd00021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf33" + + "65813fe8786236", + "3043021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "2223aa02aabb021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf336581" + + "3fe8786236", + // changing tag value + "2e3d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "323d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "ff3d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d001c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d041c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303dff1c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "001d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "041d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "ff1d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // dropping value of sequence + "3000", + // using composition + "3041300102303c1c1e41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "3041222002011e021b41b479ad576905b960fe14eadb91b0ccf34843dab91617" + + "3bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + "3041021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "2221020100021cade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8" + + "786236", + // truncate sequence + "303c021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862", + "303c1c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd02" + + "1d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // indefinite length with no delimiter + "3080021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // prepend empty sequence + "303f3000021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + // append empty sequence + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe878623630" + + "00", + // sequence of sequence + "303f303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8" + + "c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + // truncated sequence + "301e021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd", + // repeat element in sequence + "305c021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe878623602" + + "1d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // removing integer + "301f021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // appending 0's to integer + "303f021e1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "0000021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862" + + "36", + "303f021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021f00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe878623600" + + "00", + // dropping value of integer + "30210200021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "3020021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd0200", + // modify first byte of integer + "303d021c1f41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d01ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // modify last byte of integer + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cc" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786237", + // truncate integer + "303c021b1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c902" + + "1d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303c021b41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd02" + + "1d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303c021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021c00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862", + // leading ff in integer + "303e021dff1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021eff00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // infinity + "3022090180021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "3021021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd090180", + // Vectors where r or s have been modified e.g. by adding or subtracting the order of the + // group and hence violate the range check for r and s required by DSA. + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d0168dcf02f57b0caef7ddc183bee1ca94ee09c1a02ee4b0200a54dcb93", + "303c021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021cf2efc2e24cbedb2fc00c236c5b2d1a430236b59b7880007f2ba2f8d9", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021dff5219a6772dc82cf0610be22bdb5b1e370e969830cc9a7ec017879dca", + "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd" + + "021d01ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021d00d9384b2032d060e59848f87cb4535936bc25fa77959e96d7f88e33" + + "2a021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021d00d9384b2032d060e59848f87cb4535936bc25fa77959e96d7f88e33" + + "2a021d0168dcf02f57b0caef7ddc183bee1ca94ee09c1a02ee4b0200a54dcb93", + "303d021d00d9384b2032d060e59848f87cb4535936bc25fa77959e96d7f88e33" + + "2a021cf2efc2e24cbedb2fc00c236c5b2d1a430236b59b7880007f2ba2f8d9", + "303e021d00d9384b2032d060e59848f87cb4535936bc25fa77959e96d7f88e33" + + "2a021dff5219a6772dc82cf0610be22bdb5b1e370e969830cc9a7ec017879dca", + "303e021d00d9384b2032d060e59848f87cb4535936bc25fa77959e96d7f88e33" + + "2a021d01ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021dff634b1dd327de7125da7903ad2163ca2addc096101fd395567ee360" + + "70021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021dff634b1dd327de7125da7903ad2163ca2addc096101fd395567ee360" + + "70021d0168dcf02f57b0caef7ddc183bee1ca94ee09c1a02ee4b0200a54dcb93", + "303d021dff634b1dd327de7125da7903ad2163ca2addc096101fd395567ee360" + + "70021cf2efc2e24cbedb2fc00c236c5b2d1a430236b59b7880007f2ba2f8d9", + "303e021dff634b1dd327de7125da7903ad2163ca2addc096101fd395567ee360" + + "70021dff5219a6772dc82cf0610be22bdb5b1e370e969830cc9a7ec017879dca", + "303e021dff634b1dd327de7125da7903ad2163ca2addc096101fd395567ee360" + + "70021d01ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021ce1be4b8652a896fa469f01eb15246e4f330cb7bc2546e9e8c4473633" + + "021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303d021ce1be4b8652a896fa469f01eb15246e4f330cb7bc2546e9e8c4473633" + + "021d0168dcf02f57b0caef7ddc183bee1ca94ee09c1a02ee4b0200a54dcb93", + "303c021ce1be4b8652a896fa469f01eb15246e4f330cb7bc2546e9e8c4473633" + + "021cf2efc2e24cbedb2fc00c236c5b2d1a430236b59b7880007f2ba2f8d9", + "303d021ce1be4b8652a896fa469f01eb15246e4f330cb7bc2546e9e8c4473633" + + "021dff5219a6772dc82cf0610be22bdb5b1e370e969830cc9a7ec017879dca", + "303d021ce1be4b8652a896fa469f01eb15246e4f330cb7bc2546e9e8c4473633" + + "021d01ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021d011e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + "303e021d011e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021d0168dcf02f57b0caef7ddc183bee1ca94ee09c1a02ee4b0200a54dcb93", + "303d021d011e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021cf2efc2e24cbedb2fc00c236c5b2d1a430236b59b7880007f2ba2f8d9", + "303e021d011e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021dff5219a6772dc82cf0610be22bdb5b1e370e969830cc9a7ec017879dca", + "303e021d011e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9" + + "cd021d01ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe8786236", + // Signatures with special case values for r and s. E.g. r=1, s=0 are values that can lead to + // forgeries if the DSA implementation does not check boundaries and computes s^(-1) == 0. + "3022020100021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "3006020100020101", + "30060201000201ff", + "3022020100021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "3022020100021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "3022020100021d0100000000000000000000000000000000000000000000000000000000", + "3082010802010002820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e" + + "3baf3718e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b" + + "85d011adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a99345" + + "3409a0fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f" + + "9d648ef883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d" + + "8181e7338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f" + + "803b32a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de" + + "4b66ff04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e3" + + "42be484c05763939601cd667", + "3008020100090380fe01", + "3022020101021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "3006020101020101", + "30060201010201ff", + "3022020101021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "3022020101021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "3022020101021d0100000000000000000000000000000000000000000000000000000000", + "3082010802010102820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e" + + "3baf3718e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b" + + "85d011adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a99345" + + "3409a0fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f" + + "9d648ef883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d" + + "8181e7338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f" + + "803b32a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de" + + "4b66ff04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e3" + + "42be484c05763939601cd667", + "3008020101090380fe01", + "30220201ff021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "30060201ff020101", + "30060201ff0201ff", + "30220201ff021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "30220201ff021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "30220201ff021d0100000000000000000000000000000000000000000000000000000000", + "308201080201ff02820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e" + + "3baf3718e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b" + + "85d011adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a99345" + + "3409a0fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f" + + "9d648ef883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d" + + "8181e7338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f" + + "803b32a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de" + + "4b66ff04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e3" + + "42be484c05763939601cd667", + "30080201ff090380fe01", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5d021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "3022021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d020100", + "3022021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d020101", + "3022021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d0201ff", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5d021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5d021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5d021d0100000000000000000000000000000000000000000000000000000000", + "30820124021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bc" + + "d5695d02820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf3718" + + "e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011ad" + + "b8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0fe" + + "696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648ef8" + + "83448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e733" + + "8db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32a4" + + "c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff04" + + "903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be484c" + + "05763939601cd667", + "3024021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d090380fe01", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5e021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "3022021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e020100", + "3022021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e020101", + "3022021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e0201ff", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "303e021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd569" + + "5e021d0100000000000000000000000000000000000000000000000000000000", + "30820124021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bc" + + "d5695e02820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf3718" + + "e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011ad" + + "b8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0fe" + + "696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648ef8" + + "83448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e733" + + "8db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32a4" + + "c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff04" + + "903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be484c" + + "05763939601cd667", + "3024021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e090380fe01", + "303e021d01000000000000000000000000000000000000000000000000000000" + + "00021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "3022021d0100000000000000000000000000000000000000000000000000000000020100", + "3022021d0100000000000000000000000000000000000000000000000000000000020101", + "3022021d01000000000000000000000000000000000000000000000000000000000201ff", + "303e021d01000000000000000000000000000000000000000000000000000000" + + "00021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "303e021d01000000000000000000000000000000000000000000000000000000" + + "00021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "303e021d01000000000000000000000000000000000000000000000000000000" + + "00021d0100000000000000000000000000000000000000000000000000000000", + "30820124021d0100000000000000000000000000000000000000000000000000" + + "00000002820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf3718" + + "e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011ad" + + "b8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0fe" + + "696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648ef8" + + "83448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e733" + + "8db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32a4" + + "c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff04" + + "903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be484c" + + "05763939601cd667", + "3024021d0100000000000000000000000000000000000000000000000000000000090380fe01", + "3082012402820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667021dff450969597a870820211805983688387a10cd4dcc" + + "451a7f3f432a96a3", + "3082010802820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667020100", + "3082010802820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667020101", + "3082010802820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd6670201ff", + "3082012402820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667021d00baf696a68578f7dfdee7fa67c977c785ef32b233" + + "bae580c0bcd5695d", + "3082012402820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667021d00baf696a68578f7dfdee7fa67c977c785ef32b233" + + "bae580c0bcd5695e", + "3082012402820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667021d010000000000000000000000000000000000000000" + + "0000000000000000", + "3082020a02820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd66702820101008f7935d9b9aae9bfabed887acf4951b6f32e" + + "c59e3baf3718e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7" + + "475b85d011adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a9" + + "93453409a0fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6" + + "291f9d648ef883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9f" + + "fa9d8181e7338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633" + + "458f803b32a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea1" + + "43de4b66ff04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f8" + + "22e342be484c05763939601cd667", + "3082010a02820101008f7935d9b9aae9bfabed887acf4951b6f32ec59e3baf37" + + "18e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7475b85d011" + + "adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a993453409a0" + + "fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6291f9d648e" + + "f883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9ffa9d8181e7" + + "338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633458f803b32" + + "a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea143de4b66ff" + + "04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f822e342be48" + + "4c05763939601cd667090380fe01", + "3024090380fe01021dff450969597a870820211805983688387a10cd4dcc451a7f3f432a96a3", + "3008090380fe01020100", + "3008090380fe01020101", + "3008090380fe010201ff", + "3024090380fe01021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695d", + "3024090380fe01021d00baf696a68578f7dfdee7fa67c977c785ef32b233bae580c0bcd5695e", + "3024090380fe01021d0100000000000000000000000000000000000000000000000000000000", + "3082010a090380fe0102820101008f7935d9b9aae9bfabed887acf4951b6f32e" + + "c59e3baf3718e8eac4961f3efd3606e74351a9c4183339b809e7c2ae1c539ba7" + + "475b85d011adb8b47987754984695cac0e8f14b3360828a22ffa27110a3d62a9" + + "93453409a0fe696c4658f84bdd20819c3709a01057b195adcd00233dba5484b6" + + "291f9d648ef883448677979cec04b434a6ac2e75e9985de23db0292fc1118c9f" + + "fa9d8181e7338db792b730d7b9e349592f68099872153915ea3d6b8b4653c633" + + "458f803b32a4c2e0f27290256e4e3f8a3b0838a1c450e4e18c1a29a37ddf5ea1" + + "43de4b66ff04903ed5cf1623e158d487c608e97f211cd81dca23cb6e380765f8" + + "22e342be484c05763939601cd667", + "300a090380fe01090380fe01", + }; + + @SuppressWarnings("InsecureCryptoUsage") + public void testVectors( + String[] signatures, + DSAPublicKeySpec key, + String message, + String algorithm, + String signatureType, + boolean isValidDER, + boolean isValidBER) + throws Exception { + byte[] messageBytes = message.getBytes("UTF-8"); + Signature verifier = Signature.getInstance(algorithm); + KeyFactory kf = KeyFactory.getInstance("DSA"); + PublicKey pub = kf.generatePublic(key); + int errors = 0; + for (String signature : signatures) { + byte[] signatureBytes = TestUtil.hexToBytes(signature); + verifier.initVerify(pub); + verifier.update(messageBytes); + boolean verified = false; + try { + verified = verifier.verify(signatureBytes); + } catch (SignatureException ex) { + // verify can throw SignatureExceptions if the signature is malformed. + // We don't flag these cases and simply consider the signature as invalid. + verified = false; + } catch (Exception ex) { + // Other exceptions indicate some internal error, e.g. careless ASN parsing. + // We count these as errors. + System.out.println(signatureType + ":" + signature + " throws:" + ex.toString()); + errors++; + continue; + } + if (isValidDER && !verified) { + System.out.println(signatureType + " was not verified:" + signature); + errors++; + } else if (!isValidBER && verified) { + System.out.println(signatureType + " was verified:" + signature); + errors++; + } + } + assertEquals(0, errors); + } + + public void testValidSignatures() throws Exception { + testVectors( + VALID_SIGNATURES, publicKey1, "Hello", "SHA224WithDSA", "Valid DSA signature", true, true); + } + + public void testModifiedSignatures() throws Exception { + testVectors( + MODIFIED_SIGNATURES, publicKey1, "Hello", "SHA224WithDSA", "Modified DSA signature", + false, true); + } + + public void testInvalidSignatures() throws Exception { + testVectors( + INVALID_SIGNATURES, publicKey1, "Hello", "SHA224WithDSA", "Invalid DSA signature", + false, false); + } + + // Extract the integer r from a DSA signature. + // This method implicitely assumes that the DSA signature is DER encoded. + BigInteger extractR(byte[] signature) throws Exception { + int lengthR = signature[3]; + return new BigInteger(Arrays.copyOfRange(signature, 4, 4 + lengthR)); + } + + BigInteger extractS(byte[] signature) throws Exception { + int lengthR = signature[3]; + int startS = 4 + lengthR; + int lengthS = signature[startS + 1]; + return new BigInteger(Arrays.copyOfRange(signature, startS + 2, startS + 2 + lengthS)); + } + + /** Extract the k that was used to sign the signature. Validates the k if check == true. */ + BigInteger extractK(byte[] signature, BigInteger h, DSAPrivateKey priv, boolean check) + throws Exception { + BigInteger x = priv.getX(); + BigInteger q = priv.getParams().getQ(); + BigInteger r = extractR(signature); + BigInteger s = extractS(signature); + BigInteger k = x.multiply(r).add(h).multiply(s.modInverse(q)).mod(q); + if (check) { + BigInteger p = priv.getParams().getP(); + BigInteger g = priv.getParams().getG(); + BigInteger r2 = g.modPow(k, p).mod(q); + assertEquals(r.toString(), r2.toString()); + } + return k; + } + + /** + * Providers that implement SHA1WithDSA but not at least SHA256WithDSA are outdated and should be + * avoided even if DSA is currently not used in a project. Such providers promote using a weak + * signature scheme. It can also "inspire" developers to use invalid schemes such as SHA1WithDSA + * together with 2048-bit key. Such invalid use cases are often untested and can have serious + * flaws. For example the SUN provider leaked the private keys with 3 to 5 signatures in such + * instances. + */ + public void testOutdatedProvider() throws Exception { + try { + Signature sig = Signature.getInstance("SHA1WithDSA"); + try { + Signature.getInstance("SHA256WithDSA"); + } catch (NoSuchAlgorithmException ex) { + fail("Provider " + sig.getProvider().getName() + " is outdated and should not be used."); + } + } catch (NoSuchAlgorithmException ex) { + System.out.println("SHA1WithDSA is not supported"); + } + } + + /** + * This is just a test for basic functionality of DSA. The test generates a public and private + * key, generates a signature, verifies it and prints the whole thing out. This test is useful + * when an implementation is seriously broken. + */ + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE}) + @SuppressWarnings("InsecureCryptoUsage") + public void testBasic() throws Exception { + int keySize = 2048; + String algorithm = "SHA256WithDSA"; + String hashAlgorithm = "SHA-256"; + String message = "Hello"; + + byte[] messageBytes = message.getBytes("UTF-8"); + KeyPairGenerator generator = java.security.KeyPairGenerator.getInstance("DSA"); + generator.initialize(keySize); + KeyPair keyPair = generator.generateKeyPair(); + DSAPublicKey pub = (DSAPublicKey) keyPair.getPublic(); + DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate(); + Signature signer = Signature.getInstance(algorithm); + Signature verifier = Signature.getInstance(algorithm); + signer.initSign(priv); + signer.update(messageBytes); + byte[] signature = signer.sign(); + verifier.initVerify(pub); + verifier.update(messageBytes); + assertTrue(verifier.verify(signature)); + + // Extract some parameters. + byte[] rawHash = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + DSAParams params = priv.getParams(); + + // Print keys and signature, so that it can be used to generate new test vectors. + System.out.println("Message:" + message); + System.out.println("Hash:" + TestUtil.bytesToHex(rawHash)); + System.out.println("Params:"); + System.out.println("p:" + params.getP().toString()); + System.out.println("q:" + params.getQ().toString()); + System.out.println("g:" + params.getG().toString()); + System.out.println("Private key:"); + System.out.println("X:" + priv.getX().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(priv.getEncoded())); + System.out.println("Public key:"); + System.out.println("Y:" + pub.getY().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(pub.getEncoded())); + System.out.println("Signature:" + TestUtil.bytesToHex(signature)); + System.out.println("r:" + extractR(signature).toString()); + System.out.println("s:" + extractS(signature).toString()); + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testKeyGeneration(int keysize) throws Exception { + KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA"); + generator.initialize(keysize); + KeyPair keyPair = generator.generateKeyPair(); + DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate(); + DSAParams params = priv.getParams(); + assertEquals(keysize, params.getP().bitLength()); + // The NIST standard does not fully specify the size of q that + // must be used for a given key size. Hence there are differences. + // For example if keysize = 2048, then OpenSSL uses 256 bit q's by default, + // but the SUN provider uses 224 bits. Both are acceptable sizes. + // The tests below simply asserts that the size of q does not decrease the + // overall security of the DSA. + int qsize = params.getQ().bitLength(); + switch (keysize) { + case 1024: + assertTrue("Invalid qsize for 1024 bit key:" + qsize, qsize >= 160); + break; + case 2048: + assertTrue("Invalid qsize for 2048 bit key:" + qsize, qsize >= 224); + break; + case 3072: + assertTrue("Invalid qsize for 3072 bit key:" + qsize, qsize >= 256); + break; + default: + fail("Invalid key size:" + keysize); + } + // Check the length of the private key. + // For example GPG4Browsers or the KJUR library derived from it use + // q.bitCount() instead of q.bitLength() to determine the size of the private key + // and hence would generate keys that are much too small. + assertTrue(priv.getX().bitLength() >= qsize - 32); + } + + /** + * Tests the key generation for DSA. + * + * <p>Problems found: + * <ul> + * <li> CVE-2016-1000343 BouncyCastle before v.1.56 always generated DSA keys with + * a 160-bit q. + * </ul> + */ + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE}) + public void testKeyGenerationAll() throws Exception { + testKeyGeneration(1024); + testKeyGeneration(2048); + } + + /** + * Checks whether the one time key k in DSA is biased. For example the SUN provider fell for this + * test until April 2016. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testDsaBias() throws Exception { + // q is close to 2/3 * 2^160. + BigInteger q = new BigInteger("974317976835659416858874959372334979171063697271"); + BigInteger p = + new BigInteger( + "1106803511314772711673172950296693567629309594518393175860816428" + + "6658764043763662129010863568011543182924292444458455864283745070" + + "9908516713302345161980412667892373845670780253725557376379049862" + + "4062950082444499320797079243439689601679418602390654466821968220" + + "32212146727497041502702331623782703855119908989712161"); + BigInteger g = + new BigInteger( + "1057342118316953575810387190942009018497979302261477972033090351" + + "7561815639397594841480480197745063606756857212792356354588585967" + + "3837265237205154744016475608524531648654928648461175919672511710" + + "4878976887505840764543501512668232945506391524642105449699321960" + + "32410302985148400531470153936516167243072120845392903"); + BigInteger x = new BigInteger("13706102843888006547723575730792302382646994436"); + + KeyFactory kf = KeyFactory.getInstance("DSA"); + DSAPrivateKey priv = (DSAPrivateKey) kf.generatePrivate(new DSAPrivateKeySpec(x, p, q, g)); + + // If we make TESTS tests with a fair coin then the probability that + // either heads or tails appears less than MINCOUNT times is less than + // 2^{-32}. + // I.e. 2*sum(binomial(tests,i) for i in range(mincount))*2**32 < 2**tests + // Therefore the test below is not expected to fail unless the generation + // of the one time keys is indeed biased. + final int tests = 1024; + final int mincount = 410; + + String hashAlgorithm = "SHA"; + String message = "Hello"; + byte[] messageBytes = message.getBytes("UTF-8"); + byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + BigInteger h = new BigInteger(1, digest); + + final BigInteger qHalf = q.shiftRight(1); + Signature signer = Signature.getInstance("SHA1WithDSA"); + signer.initSign(priv); + int countLsb = 0; // count the number of k's with msb set + int countMsb = 0; // count the number of k's with lsb set + for (int i = 0; i < tests; i++) { + signer.update(messageBytes); + byte[] signature = signer.sign(); + BigInteger k = extractK(signature, h, priv, i < 10); + if (k.testBit(0)) { + countLsb++; + } + if (k.compareTo(qHalf) == 1) { + countMsb++; + } + } + if (countLsb < mincount || countLsb > tests - mincount) { + fail("Bias detected in the least significant bit of k:" + countLsb); + } + if (countMsb < mincount || countMsb > tests - mincount) { + fail("Bias detected in the most significant bit of k:" + countMsb); + } + } + + /** + * Checks whether CVE-2016-0695 has been fixed. Before the April 2016 security update, the SUN + * provider had a serious flaw that leaked the private key with about 3-5 signatures. In + * particular, "Sha1WithDSA" always generated 160 bit k's independently of q. Unfortunately, it is + * easily possible to use 2048 and 3072 bit DSA keys together with SHA1WithDSA. All a user has to + * do is to use the algorithm name "DSA" instead of "SHA256WithDSA" rsp. "SHA224WithDSA". + * + * <p>An algorithm to extract the key from the signatures has been described for example in the + * paper <a href="http://www.hpl.hp.com/techreports/1999/HPL-1999-90.pdf">Lattice Attacks on + * Digital Signature Schemes</a> by N.A. Howgrave-Graham, N.P. Smart. + * + * <p>This bug is the same as US-CERT: VU # 940388: GnuPG generated ElGamal signatures that leaked + * the private key. + */ + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE}) + @SuppressWarnings("InsecureCryptoUsage") + public void testBiasSha1WithDSA() throws Exception { + String hashAlgorithm = "SHA"; + String message = "Hello"; + byte[] messageBytes = message.getBytes("UTF-8"); + byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + BigInteger h = new BigInteger(1, digest); + + KeyPairGenerator generator = java.security.KeyPairGenerator.getInstance("DSA"); + generator.initialize(2048); + KeyPair keyPair = generator.generateKeyPair(); + DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate(); + Signature signer = Signature.getInstance("DSA"); + try { + // Private key and selected algorithm by signer do not match. + // Hence throwing an exception at this point would be the reasonable. + signer.initSign(priv); + signer.update(messageBytes); + byte[] signature = signer.sign(); + BigInteger q = priv.getParams().getQ(); + BigInteger k = extractK(signature, h, priv, true); + + // Now check if k is heavily biased. + int lengthDiff = q.bitLength() - k.bitLength(); + if (lengthDiff > 32) { + fail( + "Severly biased DSA signature:" + + " len(q)=" + + q.bitLength() + + " len(k)=" + + k.bitLength()); + } + } catch (GeneralSecurityException ex) { + // The key is invalid, hence getting here is reasonable. + return; + } + } + + /** + * This test checks for potential of a timing attack. The test generates a number of signatures, + * selects a fraction of them with a small timing and then compares the values k for the selected + * signatures with a normal distribution. The test fails if these ks are much smaller than + * expected. An implementation flaw that can lead to a test failure is to compute the signature + * with a modular exponentiation with a runtime that depend on the length of the exponent. + * + * <p>A failing test simply means that the timing can be used to get information about k. Further + * analysis is necessary to determine if the bias is exploitable and how many timings are + * necessary for an attack. A passing test does not mean that the implementation is secure against + * timing attacks. The test only catches relatively big timing differences. It requires high + * confidence to fail. Noise on the test machine can prevent that a relation between timing and k + * can be detected. + * + * <p>Claims of what is exploitable: http://www.hpl.hp.com/techreports/1999/HPL-1999-90.pdf 30 + * signatures are sufficient to find the private key if the attacker knows 8 bits of each k. + * http://eprint.iacr.org/2004/277.pdf 27 signatures are sufficient if 8 bits of each k is known. + * Our own old experiments (using 1GB memory on a Pentium-4? CPU): 2^11 signatures are sufficient + * with a 3 bit leakage. 2^15 signatures are sufficient with a 2 bit leakage. 2^24 signatures are + * sufficient with a 1 bit leakage. Estimate for biased generation in the NIST standard: e.g. 2^22 + * signatures, 2^40 memory, 2^64 time + * + * <p><b>Sample output for the SUN provider:</b> <code> + * count:50000 cutoff:4629300 relative average:0.9992225872624547 sigmas:0.3010906585642381 + * count:25000 cutoff:733961 relative average:0.976146066585879 sigmas:6.532668708070148 + * count:12500 cutoff:688305 relative average:0.9070352192339134 sigmas:18.00255238454385 + * count:6251 cutoff:673971 relative average:0.7747148791368986 sigmas:30.850903417893825 + * count:3125 cutoff:667045 relative average:0.5901994097874541 sigmas:39.67877152897901 + * count:1563 cutoff:662088 relative average:0.4060286694971057 sigmas:40.67294313795137 + * count:782 cutoff:657921 relative average:0.2577955312387898 sigmas:35.94906247333319 + * count:391 cutoff:653608 relative average:0.1453438859272699 sigmas:29.271192100879457 + * count:196 cutoff:649280 relative average:0.08035497211567771 sigmas:22.300206785132406 + * count:98 cutoff:645122 relative average:0.05063589092661368 sigmas:16.27820353139225 + * count:49 cutoff:641582 relative average:0.018255560447883384 sigmas:11.903018745467488 + * count:25 cutoff:638235 relative average:0.009082660721102722 sigmas:8.581595888660086 + * count:13 cutoff:633975 relative average:0.0067892346039088326 sigmas:6.20259924188633 + * </code> + * + * <p><b>What this shows:</b> The first line uses all 50'000 signatures. The average k of these + * signatures is close to the expected value q/2. Being more selective gives us signatures with a + * more biased k. For example, the 196 signatures with the fastest timing have about a 3-bit bias. + * From this we expect that 2^19 signatures and timings are sufficient to find the private key. + * + * <p>A list of problems caught by this test: + * <ul> + * <li> CVE-2016-5548 OpenJDK8's DSA is vulnerable to timing attacks. + * <li> CVE-2016-1000341 BouncyCastle before v 1.56 is vulnernerable to timing attacks. + * </ul> + */ + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.OPENJDK, + ProviderType.SPONGY_CASTLE}) + @SuppressWarnings("InsecureCryptoUsage") + public void testTiming() throws Exception { + ThreadMXBean bean = ManagementFactory.getThreadMXBean(); + if (!bean.isCurrentThreadCpuTimeSupported()) { + System.out.println("getCurrentThreadCpuTime is not supported. Skipping"); + return; + } + String hashAlgorithm = "SHA-1"; + String message = "Hello"; + byte[] messageBytes = message.getBytes("UTF-8"); + byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + BigInteger h = new BigInteger(1, digest); + KeyPairGenerator generator = java.security.KeyPairGenerator.getInstance("DSA"); + generator.initialize(1024); + KeyPair keyPair = generator.generateKeyPair(); + DSAPrivateKey priv = (DSAPrivateKey) keyPair.getPrivate(); + Signature signer = Signature.getInstance("SHA1WITHDSA"); + signer.initSign(priv); + // The timings below are quite noisy. Thus we need a large number of samples. + int samples = 50000; + long[] timing = new long[samples]; + BigInteger[] k = new BigInteger[samples]; + for (int i = 0; i < samples; i++) { + long start = bean.getCurrentThreadCpuTime(); + signer.update(messageBytes); + byte[] signature = signer.sign(); + timing[i] = bean.getCurrentThreadCpuTime() - start; + k[i] = extractK(signature, h, priv, false); + } + long[] sorted = Arrays.copyOf(timing, timing.length); + Arrays.sort(sorted); + // Here we are only interested in roughly the 8 most significant bits of the ks. + // Hence, using double is sufficiently precise. + double q = priv.getParams().getQ().doubleValue(); + double expectedAverage = q / 2; + double maxSigmas = 0; + System.out.println("testTiming: SHA1WITHDSA"); + for (int idx = samples - 1; idx > 10; idx /= 2) { + long cutoff = sorted[idx]; + int count = 0; + double total = 0; + for (int i = 0; i < samples; i++) { + if (timing[i] <= cutoff) { + total += k[i].doubleValue(); + count += 1; + } + } + double expectedStdDev = q / Math.sqrt(12 * count); + double average = total / count; + // Number of standard deviations that the average is away from + // the expected value: + double sigmas = (expectedAverage - average) / expectedStdDev; + if (sigmas > maxSigmas) { + maxSigmas = sigmas; + } + System.out.println( + "count:" + + count + + " cutoff:" + + cutoff + + " relative average:" + + (average / expectedAverage) + + " sigmas:" + + sigmas); + } + // Checks if the signatures with a small timing have a biased k. + // We use 7 standard deviations, so that the probability of a false positive is smaller + // than 10^{-10}. + if (maxSigmas >= 7) { + fail("Signatures with short timing have a biased k"); + } + } + + /** + * DSA does not allow encryption. This test verifies that a provider does not implement an ad hoc + * scheme that attempts to turn DSA into a public key encryption scheme. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testEncryptionWithDsa() throws Exception { + try { + Cipher cipher = Cipher.getInstance("DSA"); + fail("DSA must not be used as a cipher:" + cipher.getProvider().toString()); + } catch (NoSuchAlgorithmException ex) { + // This is expected + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/EcKeyTest.java b/java/com/google/security/wycheproof/testcases/EcKeyTest.java new file mode 100644 index 0000000..8d3563c --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/EcKeyTest.java @@ -0,0 +1,230 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// TODO(bleichen): RFC 3279 allows ECKeys with a number of different parameters. +// E.g. public keys can specify the order, base points etc. +// We might want to check how well these parameters are verified when parsing +// a public key. + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import junit.framework.TestCase; + +/** EC tests */ +public class EcKeyTest extends TestCase { + /** + * Encodings of public keys with invalid parameters. There are multiple places where a provider + * can validate a public key: some parameters are typically validated by the KeyFactory, more + * validation can be done by the cryptographic primitive. Unused parameters are sometimes not + * validated at all. + * + * <p>This following test vectors are public key encodings with invalid parameters where we expect + * that KeyFactory.generatePublic recognizes the problem. The documentation simply claims that an + * InvalidKeySpecException is thrown if the given key specification is inappropriate but does not + * specify what an appropriate key exactly is. Nonetheless we expect that the following minimal + * validations are performed: order is a positive integer, cofactor is a small positive integer. + * Some modifications may not be detected and must be caught by the primitives using them. E.g., + * it is expensive to verify the order of the group generated by the generator and hence the key + * factory may not verify the correctness of this parameter. Thus an implementation of ECDH must + * not trust an order claimed in the public key. + * + * <p>TODO(bleichen): The encoding is defined in https://tools.ietf.org/html/rfc3279 Section + * 2.3.5. This document defines a few additional requirements and options which are not yet + * checked: - OID for id-public-key_type must be ansi-X9.62 2 - OID for id-ecPublicKey must be + * id-publicKeyType 1 - The intended application for the key may be indicated in the key usage + * field (RFC 3280). - EcpkParameters can be implicitlyCA (not sure how we would specify the curve + * in this case) - the version is always 1 - the points on the curves can be either compressed or + * uncompressed (so far all points are uncompressed) - the seed value is optional (so far no test + * vector specifies the seed) - the cofactor is optional but must be included for ECDH keys. (so + * far all test vectors have a cofactor) + * + * <p>RFC 3279 also specifies curves over binary fields. Because of attacks against such curves, + * i.e. "New algorithm for the discrete logarithm problem on elliptic curves" by I.Semaev + * https://eprint.iacr.org/2015/310 such curves should no longer be used and hence testing them + * has low priority. + */ + public static final String[] EC_INVALID_PUBLIC_KEYS = { + // order = -115792089210356248762697446949407573529996955224135760342422259061068512044369 + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f50221ff00000000ffffffff0000000000000000" + + "4319055258e8617b0c46353d039cdaaf02010103420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + // order = 0 + "308201123081cb06072a8648ce3d02013081bf020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5020002010103420004cdeb39edd03e2b1a11a5" + + "e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b49" + + "bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + // cofactor = -1 + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc6325510201ff03420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + // cofactor = 0 + "308201323081eb06072a8648ce3d02013081df020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc632551020003420004cdeb39edd03e2b1a11a5" + + "e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b49" + + "bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + // cofactor = 115792089210356248762697446949407573529996955224135760342422259061068512044369 + "308201553082010d06072a8648ce3d020130820100020101302c06072a8648ce" + + "3d0101022100ffffffff00000001000000000000000000000000ffffffffffff" + + "ffffffffffff30440420ffffffff00000001000000000000000000000000ffff" + + "fffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0" + + "cc53b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277" + + "037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162b" + + "ce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffff" + + "ffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000000ffffff" + + "ffffffffffbce6faada7179e84f3b9cac2fc63255103420004cdeb39edd03e2b" + + "1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b842959" + + "8c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + }; + + public void testEncodedPublicKey() throws Exception { + KeyFactory kf = KeyFactory.getInstance("EC"); + for (String encodedHex : EC_INVALID_PUBLIC_KEYS) { + byte[] encoded = TestUtil.hexToBytes(encodedHex); + X509EncodedKeySpec x509keySpec = new X509EncodedKeySpec(encoded); + try { + ECPublicKey unused = (ECPublicKey) kf.generatePublic(x509keySpec); + fail("Constructed invalid public key from:" + encodedHex); + } catch (InvalidKeySpecException ex) { + // OK, since the public keys have been modified. + System.out.println(ex.toString()); + } + } + } + + public void testEncodedPrivateKey() throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + keyGen.initialize(EcUtil.getNistP256Params()); + KeyPair keyPair = keyGen.generateKeyPair(); + ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate(); + byte[] encoded = priv.getEncoded(); + System.out.println("Encoded ECPrivateKey:" + TestUtil.bytesToHex(encoded)); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded); + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPrivateKey decoded = (ECPrivateKey) kf.generatePrivate(spec); + assertEquals(priv.getS(), decoded.getS()); + assertEquals(priv.getParams().getCofactor(), decoded.getParams().getCofactor()); + assertEquals(priv.getParams().getCurve(), decoded.getParams().getCurve()); + assertEquals(priv.getParams().getGenerator(), decoded.getParams().getGenerator()); + assertEquals(priv.getParams().getOrder(), decoded.getParams().getOrder()); + } + + /** + * Tests key generation for given parameters. The test can be skipped if the curve is not a + * standard curve. + */ + void testKeyGeneration(ECParameterSpec ecParams, boolean isStandard) throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + KeyPair keyPair; + try { + keyGen.initialize(ecParams); + keyPair = keyGen.generateKeyPair(); + } catch (InvalidAlgorithmParameterException ex) { + if (!isStandard) { + return; + } + throw ex; + } + ECPublicKey pub = (ECPublicKey) keyPair.getPublic(); + ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate(); + EcUtil.checkPublicKey(pub); + BigInteger s = priv.getS(); + // Check the length of s. Could fail with probability 2^{-32}. + assertTrue(s.bitLength() >= EcUtil.fieldSizeInBits(ecParams.getCurve()) - 32); + // TODO(bleichen): correct curve? + // TODO(bleichen): use RandomUtil + } + + public void testKeyGenerationAll() throws Exception { + testKeyGeneration(EcUtil.getNistP224Params(), true); + testKeyGeneration(EcUtil.getNistP256Params(), true); + testKeyGeneration(EcUtil.getNistP384Params(), true); + testKeyGeneration(EcUtil.getNistP521Params(), true); + // Curves that are sometimes not supported. + testKeyGeneration(EcUtil.getBrainpoolP256r1Params(), false); + } + + /** + * Checks that the default key size for ECDSA is up to date. + * The test uses NIST SP 800-57 part1 revision 4, Table 2, page 53 + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf + * for the minimal key size of EC keys. + * Nist recommends a minimal security strength of 112 bits for the time until 2030. + * To achieve this security strength EC keys of at least 224 bits are required. + */ + public void testDefaultKeyGeneration() throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + KeyPair keyPair = keyGen.generateKeyPair(); + ECPublicKey pub = (ECPublicKey) keyPair.getPublic(); + int keySize = EcUtil.fieldSizeInBits(pub.getParams().getCurve()); + if (keySize < 224) { + fail("Expected a default key size of at least 224 bits. Size of generate key is " + keySize); + } + } + + /** + * Tries to generate a public key with a point at infinity. Public keys with a point at infinity + * should be rejected to prevent subgroup confinement attacks. + */ + public void testPublicKeyAtInfinity() throws Exception { + ECParameterSpec ecSpec = EcUtil.getNistP256Params(); + try { + ECPublicKeySpec pubSpec = new ECPublicKeySpec(ECPoint.POINT_INFINITY, ecSpec); + fail( + "Point at infinity is not a valid public key. " + + pubSpec.getW().equals(ECPoint.POINT_INFINITY)); + } catch (java.lang.IllegalArgumentException ex) { + // This is expected + } + } +} diff --git a/java/com/google/security/wycheproof/testcases/EcdhTest.java b/java/com/google/security/wycheproof/testcases/EcdhTest.java new file mode 100644 index 0000000..00be916 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/EcdhTest.java @@ -0,0 +1,1125 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECFieldFp; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import javax.crypto.KeyAgreement; +import junit.framework.TestCase; + +/** + * Testing ECDH. + * + * <p><b>Defense in depth</b>: The tests for ECDH assume that a attacker has control over all + * aspects of the public key in an exchange. That means that the attacker can potentially send weak + * or invalid public keys. For example, invalid public keys can contain points not on the curve, + * curves that have been deliberately chosen so that DLs are easy to compute as well as orders or + * cofactors that are wrong. It is expected that implementations validate the inputs of a key + * agreement and that in no case information about the private key is leaked. + * + * <p><b>References:</b> Ingrid Biehl, Bernd Meyer, Volker Müller, "Differential Fault Attacks on + * Elliptic Curve Cryptosystems", Crypto '00, pp. 131-164 + * + * <p>Adrian Antipa, Daniel Brown, Alfred Menezes, Rene Struik, and Scott Vanstone, "Validation of + * Elliptic Curve Public Keys", PKC 2003, https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf + * + * <p># <b>Bugs:</b> CVE-2015-7940: BouncyCastle before 1.51 does not validate a point is on the + * curve. BouncyCastle v.1.52 checks that the public key point is on the public key curve but does + * not check whether public key and private key use the same curve. BouncyCastle v.1.53 is still + * vulnerable to attacks with modified public keys. An attacker can change the order of the curve + * used by the public key. ECDHC would then reduce the private key modulo this order, which can be + * used to find the private key. + * + * <p>SunEC had similar problem. CVE ? + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// TODO(bleichen): Stuff we haven't implemented: +// - timing attacks +// Stuff we are delaying because there are more important bugs: +// - testWrongOrder using BouncyCastle with ECDHWithSHA1Kdf throws +// java.lang.UnsupportedOperationException: KDF can only be used when algorithm is known +// Not sure if that is expected or another bug. +// CVEs for ECDH we haven't used anywhere. +// - CVE-2014-3470: OpenSSL anonymous ECDH denial of service: triggered by NULL value in +// certificate. +// - CVE-2014-3572: OpenSSL downgrades ECDHE to ECDH +// - CVE-2011-3210: OpenSSL was not thread safe +public class EcdhTest extends TestCase { + + static final String[] ECDH_VARIANTS = { + // Raw ECDH. The shared secret is the x-coordinate of the ECDH computation. + // The tests below assume that this variant is implemenented. + "ECDH", + // ECDHC is a variant described in P1363 7.2.2 ECSVDP-DHC. + // BouncyCastle implements this variant. + "ECDHC", + // A variant with an explicit key derivation function. + // This is implemented by BouncyCastle. + "ECDHWITHSHA1KDF", + }; + + /** ECDH test vectors */ + public static class EcdhTestVector { + final String curvename; + final String pub; // hexadecimal representation of the X509 encoding + final BigInteger s; // private key + final String shared; // hexadecimal representation of the shared secret + + public EcdhTestVector(String curvename, String pub, BigInteger s, String shared) { + this.curvename = curvename; + this.pub = pub; + this.s = s; + this.shared = shared; + } + + public ECPublicKey getPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException { + KeyFactory kf = KeyFactory.getInstance("EC"); + byte[] encoded = TestUtil.hexToBytes(pub); + return (ECPublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded)); + } + + public ECPrivateKey getPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException { + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPrivateKeySpec spec = new ECPrivateKeySpec(s, EcUtil.getCurveSpecRef(curvename)); + return (ECPrivateKey) kf.generatePrivate(spec); + } + } + + public static final EcdhTestVector[] ECDH_TEST_VECTORS = { + // vectors with normal ECDH values + new EcdhTestVector( + "secp224r1", + "304e301006072a8648ce3d020106052b81040021033a00049c08bb3788a5cb8d" + + "22591f2520791cdaf61765a84f0419d28ff8fb2dcb5d51e5714d8740420d0945" + + "187f97be42872bae9bf3f5b1857a475f", + new BigInteger("8af784fe9cebd363df85f598dcc2ab82b2ca725360dadb77b3708032", 16), + "c1921af3d06d813ccb009e363a647836d30b3f9c211c26e64a3bb0b6"), + new EcdhTestVector( + "secp256r1", + "3059301306072a8648ce3d020106082a8648ce3d030107034200044b3b0a5231" + + "76309f259498c55e3a9be45c9fb65ad4e60d6064e04b89c1bd0a1835039219c1" + + "22b89e2b539bb16d3afced502137f02944c374863137035fd3f1ae", + new BigInteger("051a995be2a8499e2c9331b3b5f3c012048bb02a1a6f044ed93d9bd295fcec16", 16), + "33befba428b295b9a0123d3a848d91d1e9a5266959e036d1a25e28d83d06421f"), + new EcdhTestVector( + "secp384r1", + "3076301006072a8648ce3d020106052b8104002203620004c1d31b771bb123f4" + + "fb2b789a2880c57a68b3bbfa7da3d80b8325b73428bd2a4e79b55b57ac454f52" + + "8ac02b62d54dfc315b9ba04363e94b825767951a9338f5d1db4c6d3f0e9a15bc" + + "9b834fc11a01e4b310c22aba73766fd769ea684fbad5d9d2", + new BigInteger("ff65a2bf5e1347e2286fb29273fb118a76996038bea2fcfd2032e8663f7588e5" + + "3130d195b161eba39085abbc3e24bcef", 16), + "dbd85b2caaca6d69460c94bd9f99b3bd51404788a58334a18709a882050fe1bf" + + "a4dd74de6e4368c1243443e5f64b60c7"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b81040023038186000401ca6ec5476b" + + "ae3cf0f28f370ac3a9a0de2091418a590978bf87a6f1aeadebde98925e8fb42c" + + "d03d57ff9aeb9890646067a3095874828a392b80a88880e5f456e4d000493581" + + "376d20d711a487e0106a3fc047b91803ed154e274b26d858cf2f55e356b45765" + + "2101b925b7d36b542d2a3e33e01404fb4f944c3b8ef276b6f5082e591135", + new BigInteger("01f362c182f1eaae2920578a2f30c228e28b996e74d4bd799621300d5f2e6c69" + + "30204f00476732c95a79ae527503621edf633dbb87400740f54adc4430706221" + + "2f68", 16), + "0107b9c99c80e2bc834e10c44afe2d611aafe8aad0eb80384aefbd9bb8196ea3" + + "b5797bedac39de3362532c9b04aeb98a3e60034c3d2dcb4a43b8f8b44e9528d3" + + "eeb8"), + new EcdhTestVector( + "brainpoolp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d" + + "1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6c" + + "e94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7" + + "e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27" + + "e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745" + + "132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d71" + + "8c397aa3b561a6f7901e0e82974856a7020101034200048178776ff8332108da" + + "d4fa59bce3111133a30e33fa7f96d0211ec9fa4904dcca084de67f52fd720ccd" + + "ada5c49305200a6028793a83cbe692c08237ecd0572fa2", + new BigInteger("143be522a9d0420f6bd19b95ce3a5e19c61970c31f13448276546625e607e7c9", 16), + "3658b819481f00f74cfd76b9dcf82867c3c3186f948cbc75bf296c6d332aedf0"), + // vectors with extreme values for the shared secret + new EcdhTestVector( + "secp256r1", + "3059301306072a8648ce3d020106082a8648ce3d03010703420004983f80374a" + + "4730f9decd7221fa3ebb527d44f459b6c6afcf7de7069481400a748fb8733ba0" + + "8e01cd53d54af45975554d0dbd6d5f0acf0fd95692606347cace7e", + new BigInteger("56556c546751dee664ae71baa0189a2e69b1e1f8939a49ed7cc35d7ea98fbcc7", 16), + "0000000000000000000000000000000000000000000000000000000000000000"), + new EcdhTestVector( + "secp384r1", + "3076301006072a8648ce3d020106052b8104002203620004d64af08419f8a0aa" + + "5d830a2b0f42e6a27a3c17e0e98f64a1e7e10c6a41a308832dcd9a493db0cd43" + + "7e47063c1db6c967494c8460f03bf95ff619b7c7499e1bc08fd759fc44c4af3d" + + "03de541a719baf996b4f91a9af5bf08fa671af0899f91359", + new BigInteger("ee383acde7e5b3e6c246833e183c4272a1714a13097b4b57bc2eeecdccbd69b6" + + "cff435215a3c92b5d4e0b2c36444a7fa", 16), + "0000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000"), + new EcdhTestVector( + "secp384r1", + "3076301006072a8648ce3d020106052b81040022036200041c1ed3f66b6ae370" + + "411ac30fda63c784c5cbc3951a7cfe567d8bfa3ea535a2eb8c192d349e69ea2a" + + "39eb5013a5cf383cf91c82e81eee1a9bc97386e340e65b2b2d8cf2633b919a82" + + "10a638b8e2345cda054ce96efcaeee20dcce82d13d40eb6a", + new BigInteger("98f230ef0c0ab02c78179ba9ea3e1c8d16c3ec276665c432b9040b803dfff657" + + "a6c77512b6a602d416785016c3cd3da7", 16), + "0000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000002"), + new EcdhTestVector( + "secp384r1", + "3076301006072a8648ce3d020106052b8104002203620004d10b0df120b1324d" + + "8b76ee43065e4f4be63f68cf5b381ae79046920108a8f21cf8097bf313225b74" + + "1125eb5a66105ee445961b28ad1843613775c063a85319f1353d8bf2a217210e" + + "309f2c7c27b57d42fdc042abb00b37a0f3118cf74b4174f0", + new BigInteger("5b8e9af3c17fa0d683f3bc94f8685f33c0b616281f91b466cac9da0a0e085ba6" + + "f48aafcdb4fc13d55f1a33ac436f82bb", 16), + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + + "ffffffff0000000000000000fffffffe"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b810400230381860004008269c7d0ff" + + "febadbf5bdfa2adf0f378d0844268e5acb57d0157fe688488cef91256e15939d" + + "311aaf6479e29ef14de3981c3a5768c7b66693e956fa515d4a0c847c0054a32b" + + "4a8f615ba5550f204ebf1f7f02f7252b5ae564361eec468adf4d59caa4c4b424" + + "a30761d805d521c2e1f1dfde385e9146624cb2b84f94888730acbfbf1294", + new BigInteger("019ad2de5943f5112021a3215cee84c4e8d40e188641419a5b7958636f1843d0" + + "cbda4747aad69fd806b333b82b095d0f10bda8dbeca7ee9f67d09caffb4869e4" + + "1172", 16), + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b810400230381860004003b0d698705" + + "0fad0f76ac1ac7a1c7e91e24addf821c06ae0844a3f1b6338c111a32a94a5369" + + "fdf8fd1cc137314c7d7a99dfabba1cc92f10026e45388714fe453ed50015e59a" + + "c4bab161635e0df0f5553ee6112fc60f744ffc607965975c0843f7a893441c4f" + + "e5e6e290426dd219ecbc159f39302b52b37b69a890e9fc4cf70eba39bbf6", + new BigInteger("0147492d3019808024569dc81b0e6aef9f27bfd43e009e8b4b6b0512b220490e" + + "08f98324b16d3ed91a54d391f92973f5376c66b9f8a9cbf893b0900968fd8d6e" + + "5e7d", 16), + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0001"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b81040023038186000401bb2936bfc5" + + "8f1e9819d62ed2a38a0ce618f000546fe8af4983d8dbbda7b7ae914a656ac540" + + "7c153f6edacb170fd2129d126d987d5032c7a31540bb6a4e93f8af15015c23ce" + + "1263e691903cd2c859d883c980fada91b764aef7e5a20fb22bcf5949e62c8082" + + "c8245bcf8686a6a39b7ef2eec49b1a047b73aeb06e3793c1d01fa24fd156", + new BigInteger("5a5f98ceb2f856685c51ba714d5e1db06d1e6542a8d02b9c13efeeb1f3e6613d" + + "8ef83e49748cb63aad268ba68c9295c507dac125f51ba75c82f6029dcc14d4ab" + + "16", 16), + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0002"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b81040023038186000401ce7a5356fd" + + "002ff3d9a193dd910795b56f8bd2f975367d982d27e04b4e0935425fdef6b3e1" + + "6fac26a898a757ddbfb01a45236a8a06ead9db3dff644ed87a7f09310000c862" + + "7374a123b1c0fdf7efaaee362fa7fdeb1c56bd787e81484d21a818ff49552704" + + "af2d2fe714a1576299ff6d3745349cdb463e8c003641c13c870391cfd360", + new BigInteger("c5dd96d1f0aa141f184d0a749809dc0749a0629b9b7d99d1cbe40c14204d70c7" + + "f63413756040a4c2a67551df6723c4b784ace44d7e35f46233c78b2c7548594b" + + "3d", 16), + "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "fffd"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b81040023038186000400d4574ad46e" + + "42824b7738f0ed19f0dbec65e743ed6a1798e8168546713a929c97cb8b2f3c20" + + "928bed9fad88319ef216e42c7a82707befead2b21000e06e6ca37709004848c1" + + "34a7fa6d0f8cd9aa237b84ffa02cb3bc8d84b8022153a3e01248dfc87403e8f3" + + "f1b70b52b7eabffd01fe1b4101fa901494a2067e2321a47e87cce45eecfd", + new BigInteger("01ac34343b1814a092e48f1c60de0bacced8c328246f103428ab0ce6611807e6" + + "90022dbc6bc558265b917dc513152cd1661b30e3b62a2cc2bf9f909e3fd51918" + + "de5b", 16), + "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "fffe"), + new EcdhTestVector( + "brainpoolp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d" + + "1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6c" + + "e94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7" + + "e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27" + + "e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745" + + "132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d71" + + "8c397aa3b561a6f7901e0e82974856a70201010342000498703a894131de3f81" + + "5836bdb1d5a03e59fbf50ffde6575ee690e9ebf6a32e785ad50d1eb00062a9b8" + + "176ba32f06f3908f82a3ddd9da10eafcac61f57a180bcb", + new BigInteger("17617237e4ec2629d798a81ca086c1a73494e70619dd7b77cb7360174de82107", 16), + "0000000000000000000000000000000000000000000000000000000000000001"), + new EcdhTestVector( + "brainpoolp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d" + + "1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6c" + + "e94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7" + + "e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27" + + "e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745" + + "132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d71" + + "8c397aa3b561a6f7901e0e82974856a702010103420004055f1b89b08c1c4a0f" + + "96ff15dd284bdad79b90636ce73c461cb6da001e19638c07490bed6a644e944a" + + "c3e8684c4d5cf469a3f5b039690cba52dc0dccb095e61e", + new BigInteger("7988ceedd4ce4f516f083261dc0dbb4d59c71b058bf00876135fb1d5e72a1cea", 16), + "0000000000000000000000000000000000000000000000000000000000000002"), + new EcdhTestVector( + "brainpoolp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d" + + "1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6c" + + "e94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7" + + "e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27" + + "e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745" + + "132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d71" + + "8c397aa3b561a6f7901e0e82974856a70201010342000424f99dbc3d8f4989f2" + + "43662e67de0f8d03d0f84031caa553f4a3ccc1c999de1e43530fcd456a5d83d5" + + "11aedc8bda7c2b18cc509cabe47e76d46501fd82ebbfae", + new BigInteger("844649c38c375c5f4959b129c6510e54f71a60b91d1b09a7b1a8dd0e954da186", 16), + "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5376"), + // vectors with extreme values for the public key + new EcdhTestVector( + "secp256r1", + "3059301306072a8648ce3d020106082a8648ce3d030107034200040000000000" + + "00000000000000000000000000000000000000000000000000000066485c780e" + + "2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4", + new BigInteger("2e0a2c5159af006f28f5b51e55ce9270f17a431ebefee2d95bf2f954c3c460c5", 16), + "bb4b8e7b1b5d766d7e6d3de41e0ab0703cadcca4e039f310e3ed0004e2c1ba67"), + new EcdhTestVector( + "secp384r1", + "3076301006072a8648ce3d020106052b81040022036200040000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000003cf99ef04f51a5ea630ba3f9f960dd593a14c9be39fd2bd2" + + "15d3b4b08aaaf86bbf927f2c46e52ab06fb742b8850e521e", + new BigInteger("b0a8c4804a2b9769216a51b51ece43391cf3f66c383a748d54f1c15f27bbf041" + + "a3b9470a6d49f8abe9e6b4db6bd7c59f", 16), + "6598237fdfd3f38e00c3c58a3045b9d54c510f0f5523293af1966635f2ddf963" + + "87b12065ad8e1a5b72618e6441c72841"), + new EcdhTestVector( + "secp384r1", + "3076301006072a8648ce3d020106052b8104002203620004ffffffffffffffff" + + "fffffffffffffffffffffffffffffffffffffffffffffffeffffffff00000000" + + "00000000fffffffe732152442fb6ee5c3e6ce1d920c059bc623563814d79042b" + + "903ce60f1d4487fccd450a86da03f3e6ed525d02017bfdb3", + new BigInteger("135b5751b27de8fe0e34d452ad81c4ca90def546275c349f467aabd24e039b75" + + "28c473bc5732cb96921d01e6ca11739a", 16), + "ef5ceb524843eb0277f574b278b09f82670dbcdacbe51a646441a45ebdfa4976" + + "1fb3b534bfccd957edb99e9a4e329467"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b810400230381860004000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000d20ec9" + + "fea6b577c10d26ca1bb446f40b299e648b1ad508aad068896fee3f8e614bc630" + + "54d5772bf01a65d412e0bcaa8e965d2f5d332d7f39f846d440ae001f4f87", + new BigInteger("7ca82bb7bdd0ab3805e1d25ce49f71780e93a0314f579a474d0b0f81812c8365" + + "bc3917eb00208a1cfdb44cdc53f112930560e86bcad563d0bd4ff951f2c41454" + + "f6", 16), + "00d6283f6a7b59628920dd3afe97a5021c79e26c71adf5c0774cedaaf5b25b92" + + "ed2776cfefbe95e467a15032c221064ff19b1207183f0ca0c594b6a83ca0e3f3" + + "2250"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b810400230381860004000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000010010e59b" + + "e93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec6" + + "36ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564", + new BigInteger("011cf3abed354498f6922af2ddc9d74b2bb829bee79cc272c7b154f16a720c29" + + "429bb354bb034549e33be5b84ffb6da99a0c28bb37fa44f78cce5feb871370e1" + + "2c93", 16), + "00e51b94872c9cb3831bac48e9e4cbc6b4eafdc09ce51f43d0ff118b5d429f20" + + "b88261dbfc9636ecf081cdcf1b1336425a39841cf1ff742bc3d5553a709cd0a7" + + "3a13"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b81040023038186000401ffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffd0010e59b" + + "e93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03df47849bf550ec6" + + "36ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c832e843564", + new BigInteger("011c2b1a82cd320924e757b4259e5f7c0455efe3f05d316c9705b5071fdbd59e" + + "db59ee938b95a67727ca01ffe5155baf5eff83ae5ec4a56770a50475b017a762" + + "30cf", 16), + "000adf30396bda59d36fc307a4f43f594806f3a46373f3e4af6516e67f99d981" + + "1c0496f49527895fa7738423f6429318f54afa6841cb4692e15016fe49fc7c82" + + "509d"), + new EcdhTestVector( + "secp521r1", + "30819b301006072a8648ce3d020106052b81040023038186000401ffffffffff" + + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00d9254f" + + "df800496acb33790b103c5ee9fac12832fe546c632225b0f7fce3da4574b1a87" + + "9b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051d6aa505acf", + new BigInteger("01e1603fe7e275673aeb8b3f105f4058e073b4c37d2f0ae2bd66b189454e1b41" + + "c442c3f35f085eae3aa37eefffe76736440f9b3fd2e3931d468b6d90e560bc0f" + + "35f5", 16), + "0158694585e55f1289e410fdeeed82940b3029dd8207dcb4de407278a6328d5e" + + "b904262419f1ef2ecacb415872f0c9d64df82b1241cd780bd0abc9e26ceebadf" + + "44e7"), + new EcdhTestVector( + "brainpoolp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d" + + "1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6c" + + "e94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7" + + "e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27" + + "e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745" + + "132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d71" + + "8c397aa3b561a6f7901e0e82974856a702010103420004000000000000000000" + + "000000000000000000000000000000000000000000000109e0e9e8d98fb89da2" + + "a32b2c7618b26bb99b920f02a5e831a142e6c8673110cd", + new BigInteger("61c2be000b5888035bfde07d532b36d91cc347f556d87c7a01397f4cde29c6e4", 16), + "3db56c93e51a0b5b17a8009be010be6eecca6b7e0b587753cb8bc850869a710d"), + new EcdhTestVector( + "brainpoolp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d" + + "1f6e5377304404207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6c" + + "e94a4b44f330b5d9042026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7" + + "e1ce6bccdc18ff8c07b60441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27" + + "e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745" + + "132ded8e545c1d54c72f046997022100a9fb57dba1eea9bc3e660a909d838d71" + + "8c397aa3b561a6f7901e0e82974856a702010103420004a9fb57dba1eea9bc3e" + + "660a909d838d726e3bf623d52620282013481d1f6e537613a0346db14d55d1bc" + + "c27079b68864ac32885b5bdfc3c9db6f85a35d3df4c39b", + new BigInteger("8527b0540fc10b025a6e0892439c59a889a52e57a0f81b4df41442869c524873", 16), + "a01ed9d4f5a0884db2a232dd5369d6014bfe1f2f6a6d05a757e7a078b71a1f54"), + }; + + /** Test vectors */ + public static class EcPublicKeyTestVector { + final String comment; + final String encoded; // hexadecimal representation of the X509 encoding + final BigInteger p; // characteristic of the field + final BigInteger n; // order of the subgroup + final BigInteger a; // parameter a of the Weierstrass representation + final BigInteger b; // parameter b of the Weierstrass represnetation + final BigInteger gx; // x-coordinate of the generator + final BigInteger gy; // y-coordainat of the generator + final Integer h; // cofactor: may be null + final BigInteger pubx; // x-coordinate of the public point + final BigInteger puby; // y-coordinate of the public point + + public EcPublicKeyTestVector( + String comment, + String encoded, + BigInteger p, + BigInteger n, + BigInteger a, + BigInteger b, + BigInteger gx, + BigInteger gy, + Integer h, + BigInteger pubx, + BigInteger puby) { + this.comment = comment; + this.encoded = encoded; + this.p = p; + this.n = n; + this.a = a; + this.b = b; + this.gx = gx; + this.gy = gy; + this.h = h; + this.pubx = pubx; + this.puby = puby; + } + + /** + * Returns this key as ECPublicKeySpec or null if the key cannot be represented as + * ECPublicKeySpec. The later happens for example if the order of cofactor are not positive. + */ + public ECPublicKeySpec getSpec() { + try { + ECFieldFp fp = new ECFieldFp(p); + EllipticCurve curve = new EllipticCurve(fp, a, b); + ECPoint g = new ECPoint(gx, gy); + // ECParameterSpec requires that the cofactor h is specified. + if (h == null) { + return null; + } + ECParameterSpec params = new ECParameterSpec(curve, g, n, h); + ECPoint pubPoint = new ECPoint(pubx, puby); + ECPublicKeySpec pub = new ECPublicKeySpec(pubPoint, params); + return pub; + } catch (Exception ex) { + System.out.println(comment + " throws " + ex.toString()); + return null; + } + } + + public X509EncodedKeySpec getX509EncodedKeySpec() { + return new X509EncodedKeySpec(TestUtil.hexToBytes(encoded)); + } + } + + public static final EcPublicKeyTestVector EC_VALID_PUBLIC_KEY = + new EcPublicKeyTestVector( + "unmodified", + "3059301306072a8648ce3d020106082a8648ce3d03010703420004cdeb39edd0" + + "3e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b84" + + "29598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)); + + public static final EcPublicKeyTestVector[] EC_MODIFIED_PUBLIC_KEYS = { + // Modified keys + new EcPublicKeyTestVector( + "public point not on curve", + "3059301306072a8648ce3d020106082a8648ce3d03010703420004cdeb39edd0" + + "3e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b84" + + "29598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebaca", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebaca", 16)), + new EcPublicKeyTestVector( + "public point = (0,0)", + "3059301306072a8648ce3d020106082a8648ce3d030107034200040000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("0"), + new BigInteger("0")), + new EcPublicKeyTestVector( + "order = 1", + "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f502010102010103420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("01", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "order = 26959946660873538060741835960514744168612397095220107664918121663170", + "3082012f3081e806072a8648ce3d02013081dc020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5021d00ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac202010103420004cdeb39edd03e2b1a11a5e134ec" + + "99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b49bbb85c" + + "3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "generator = (0,0)", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b04410400000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255102010103420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("0"), + new BigInteger("0"), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "generator not on curve", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f7022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255102010103420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f7", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "cofactor = 2", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255102010203420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 2, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "cofactor = None", + "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255103420004cdeb39edd03e2b1a11a5e134" + + "ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b49bbb8" + + "5c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + null, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "modified prime", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100fd091059a6893635f900e9449d63f572b2aebc4cff7b4e5e33f1b200" + + "e8bbc1453044042002f6efa55976c9cb06ff16bb629c0a8d4d5143b40084b1a1" + + "cc0e4dff17443eb704205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441040000000000000000000006597fa94b1fd90000" + + "000000000000000000000000021b8c7dd77f9a95627922eceefea73f028f1ec9" + + "5ba9b8fa95a3ad24bdf9fff414022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255102010103420004000000000000000000" + + "0006597fa94b1fd90000000000000000000000000000021b8c7dd77f9a956279" + + "22eceefea73f028f1ec95ba9b8fa95a3ad24bdf9fff414", + new BigInteger("fd091059a6893635f900e9449d63f572b2aebc4cff7b4e5e33f1b200e8bbc145", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("06597fa94b1fd9000000000000000000000000000002", 16), + new BigInteger("1b8c7dd77f9a95627922eceefea73f028f1ec95ba9b8fa95a3ad24bdf9fff414", 16), + 1, + new BigInteger("06597fa94b1fd9000000000000000000000000000002", 16), + new BigInteger("1b8c7dd77f9a95627922eceefea73f028f1ec95ba9b8fa95a3ad24bdf9fff414", 16)), + new EcPublicKeyTestVector( + "using secp224r1", + "304e301006072a8648ce3d020106052b81040021033a0004074f56dc2ea648ef" + + "89c3b72e23bbd2da36f60243e4d2067b70604af1c2165cec2f86603d60c8a611" + + "d5b84ba3d91dfe1a480825bcc4af3bcf", + new BigInteger("ffffffffffffffffffffffffffffffff000000000000000000000001", 16), + new BigInteger("ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d", 16), + new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffffffffffe", 16), + new BigInteger("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 16), + new BigInteger("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 16), + new BigInteger("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 16), + 1, + new BigInteger("074f56dc2ea648ef89c3b72e23bbd2da36f60243e4d2067b70604af1", 16), + new BigInteger("c2165cec2f86603d60c8a611d5b84ba3d91dfe1a480825bcc4af3bcf", 16)), + new EcPublicKeyTestVector( + "a = 0", + "308201143081cd06072a8648ce3d02013081c1020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30250401000420f104880c3980129c7efa19b6b0cb04e547b8d0fc0b" + + "95f4946496dd4ac4a7c440044104cdeb39edd03e2b1a11a5e134ec99d5f25f21" + + "673d403f3ecb47bd1fa676638958ea58493b8429598c0b49bbb85c3303ddb155" + + "3c3b761c2caacca71606ba9ebac8022100ffffffff00000000ffffffffffffff" + + "ffbce6faada7179e84f3b9cac2fc63255102010103420004cdeb39edd03e2b1a" + + "11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c" + + "0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("0"), + new BigInteger("f104880c3980129c7efa19b6b0cb04e547b8d0fc0b95f4946496dd4ac4a7c440", 16), + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "new curve with generator of order 3 that is also on secp256r1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff3044042046dc879a5c2995d0e6f682468ea95791b7bbd0225cfdb251" + + "3fb10a737afece170420bea6c109251bfe4acf2eeda7c24c4ab70a1473335dec" + + "28b244d4d823d15935e2044104701c05255026aa4630b78fc6b769e388059ab1" + + "443cbdd1f8348bedc3be589dc34cfdab998ad27738ae382aa013986ade0f4859" + + "2a9a1ae37ca61d25ec5356f1bd022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255102010103420004701c05255026aa4630" + + "b78fc6b769e388059ab1443cbdd1f8348bedc3be589dc3b3025465752d88c851" + + "c7d55fec679521f0b7a6d665e51c8359e2da13aca90e42", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("46dc879a5c2995d0e6f682468ea95791b7bbd0225cfdb2513fb10a737afece17", 16), + new BigInteger("bea6c109251bfe4acf2eeda7c24c4ab70a1473335dec28b244d4d823d15935e2", 16), + new BigInteger("701c05255026aa4630b78fc6b769e388059ab1443cbdd1f8348bedc3be589dc3", 16), + new BigInteger("4cfdab998ad27738ae382aa013986ade0f48592a9a1ae37ca61d25ec5356f1bd", 16), + 1, + new BigInteger("701c05255026aa4630b78fc6b769e388059ab1443cbdd1f8348bedc3be589dc3", 16), + new BigInteger("b3025465752d88c851c7d55fec679521f0b7a6d665e51c8359e2da13aca90e42", 16)), + // Invalid keys + new EcPublicKeyTestVector( + "order = -1157920892103562487626974469494075735299969552241357603" + + "42422259061068512044369", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f50221ff00000000ffffffff0000000000000000" + + "4319055258e8617b0c46353d039cdaaf02010103420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger( + "-115792089210356248762697446949407573529996955224135760342422259061068512044369"), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "order = 0", + "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f502010002010103420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("0"), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "cofactor = -1", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc6325510201ff03420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + -1, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + new EcPublicKeyTestVector( + "cofactor = 0", + "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d01" + + "01022100ffffffff00000001000000000000000000000000ffffffffffffffff" + + "ffffffff30440420ffffffff00000001000000000000000000000000ffffffff" + + "fffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53" + + "b0f63bce3c3e27d2604b0441046b17d1f2e12c4247f8bce6e563a440f277037d" + + "812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33" + + "576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffff" + + "bce6faada7179e84f3b9cac2fc63255102010003420004cdeb39edd03e2b1a11" + + "a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958ea58493b8429598c0b" + + "49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", + new BigInteger("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 16), + new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), + new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + new BigInteger("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16), + new BigInteger("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16), + 0, + new BigInteger("cdeb39edd03e2b1a11a5e134ec99d5f25f21673d403f3ecb47bd1fa676638958", 16), + new BigInteger("ea58493b8429598c0b49bbb85c3303ddb1553c3b761c2caacca71606ba9ebac8", 16)), + }; + + /** Checks that key agreement using ECDH works. */ + public void testBasic() throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + keyGen.initialize(ecSpec); + KeyPair keyPairA = keyGen.generateKeyPair(); + KeyPair keyPairB = keyGen.generateKeyPair(); + + KeyAgreement kaA = KeyAgreement.getInstance("ECDH"); + KeyAgreement kaB = KeyAgreement.getInstance("ECDH"); + kaA.init(keyPairA.getPrivate()); + kaB.init(keyPairB.getPrivate()); + kaA.doPhase(keyPairB.getPublic(), true); + kaB.doPhase(keyPairA.getPublic(), true); + byte[] kAB = kaA.generateSecret(); + byte[] kBA = kaB.generateSecret(); + assertEquals(TestUtil.bytesToHex(kAB), TestUtil.bytesToHex(kBA)); + } + + public void testVectors() throws Exception { + KeyAgreement ka = KeyAgreement.getInstance("ECDH"); + for (EcdhTestVector t : ECDH_TEST_VECTORS) { + try { + ka.init(t.getPrivateKey()); + ka.doPhase(t.getPublicKey(), true); + byte[] shared = ka.generateSecret(); + assertEquals("Curve:" + t.curvename, TestUtil.bytesToHex(shared), t.shared); + } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) { + // Skipped, because the provider does not support the curve. + } + } + } + + public void testDecode() throws Exception { + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPublicKey key1 = (ECPublicKey) kf.generatePublic(EC_VALID_PUBLIC_KEY.getSpec()); + ECPublicKey key2 = (ECPublicKey) kf.generatePublic(EC_VALID_PUBLIC_KEY.getX509EncodedKeySpec()); + ECParameterSpec params1 = key1.getParams(); + ECParameterSpec params2 = key2.getParams(); + assertEquals(params1.getCofactor(), params2.getCofactor()); + assertEquals(params1.getCurve(), params2.getCurve()); + assertEquals(params1.getGenerator(), params2.getGenerator()); + assertEquals(params1.getOrder(), params2.getOrder()); + assertEquals(key1.getW(), key2.getW()); + } + + /** + * This test modifies the order of group in the public key. A severe bug would be an + * implementation that leaks information whether the private key is larger than the order given in + * the public key. Also a severe bug would be to reduce the private key modulo the order given in + * the public key parameters. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testModifiedPublic(String algorithm) throws Exception { + KeyAgreement ka; + try { + ka = KeyAgreement.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + System.out.println("testWrongOrder: " + algorithm + " not supported"); + return; + } + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + keyGen.initialize(EcUtil.getNistP256Params()); + ECPrivateKey priv = (ECPrivateKey) keyGen.generateKeyPair().getPrivate(); + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPublicKey validKey = (ECPublicKey) kf.generatePublic(EC_VALID_PUBLIC_KEY.getSpec()); + ka.init(priv); + ka.doPhase(validKey, true); + String expected = TestUtil.bytesToHex(ka.generateSecret()); + for (EcPublicKeyTestVector test : EC_MODIFIED_PUBLIC_KEYS) { + try { + X509EncodedKeySpec spec = test.getX509EncodedKeySpec(); + ECPublicKey modifiedKey = (ECPublicKey) kf.generatePublic(spec); + ka.init(priv); + ka.doPhase(modifiedKey, true); + String shared = TestUtil.bytesToHex(ka.generateSecret()); + // The implementation did not notice that the public key was modified. + // This is not nice, but at the moment we only fail the test if the + // modification was essential for computing the shared secret. + // + // BouncyCastle v.1.53 fails this test, for ECDHC with modified order. + // This implementation reduces the product s*h modulo the order given + // in the public key. An attacker who can modify the order of the public key + // and who can learn whether such a modification changes the shared secret is + // able to learn the private key with a simple binary search. + assertEquals("algorithm:" + algorithm + " test:" + test.comment, expected, shared); + } catch (GeneralSecurityException ex) { + // OK, since the public keys have been modified. + System.out.println("testModifiedPublic:" + test.comment + " throws " + ex.toString()); + } + } + } + + /** + * This is a similar test as testModifiedPublic. However, this test uses test vectors + * ECPublicKeySpec + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testModifiedPublicSpec(String algorithm) throws Exception { + KeyAgreement ka; + try { + ka = KeyAgreement.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + System.out.println("testWrongOrder: " + algorithm + " not supported"); + return; + } + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + keyGen.initialize(EcUtil.getNistP256Params()); + ECPrivateKey priv = (ECPrivateKey) keyGen.generateKeyPair().getPrivate(); + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPublicKey validKey = (ECPublicKey) kf.generatePublic(EC_VALID_PUBLIC_KEY.getSpec()); + ka.init(priv); + ka.doPhase(validKey, true); + String expected = TestUtil.bytesToHex(ka.generateSecret()); + for (EcPublicKeyTestVector test : EC_MODIFIED_PUBLIC_KEYS) { + ECPublicKeySpec spec = test.getSpec(); + if (spec == null) { + // The constructor of EcPublicKeySpec performs some very minor validity checks. + // spec == null if one of these validity checks fails. Of course such a failure is OK. + continue; + } + try { + ECPublicKey modifiedKey = (ECPublicKey) kf.generatePublic(spec); + ka.init(priv); + ka.doPhase(modifiedKey, true); + String shared = TestUtil.bytesToHex(ka.generateSecret()); + // The implementation did not notice that the public key was modified. + // This is not nice, but at the moment we only fail the test if the + // modification was essential for computing the shared secret. + // + // BouncyCastle v.1.53 fails this test, for ECDHC with modified order. + // This implementation reduces the product s*h modulo the order given + // in the public key. An attacker who can modify the order of the public key + // and who can learn whether such a modification changes the shared secret is + // able to learn the private key with a simple binary search. + assertEquals("algorithm:" + algorithm + " test:" + test.comment, expected, shared); + } catch (GeneralSecurityException ex) { + // OK, since the public keys have been modified. + System.out.println("testModifiedPublic:" + test.comment + " throws " + ex.toString()); + } + } + } + + public void testModifiedPublic() throws Exception { + testModifiedPublic("ECDH"); + testModifiedPublic("ECDHC"); + } + + public void testModifiedPublicSpec() throws Exception { + testModifiedPublicSpec("ECDH"); + testModifiedPublicSpec("ECDHC"); + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testDistinctCurves(String algorithm, ECPrivateKey priv, ECPublicKey pub) + throws Exception { + KeyAgreement kaA; + try { + kaA = KeyAgreement.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + System.out.println("Algorithm not supported: " + algorithm); + return; + } + byte[] shared; + try { + kaA.init(priv); + kaA.doPhase(pub, true); + shared = kaA.generateSecret(); + } catch (InvalidKeyException ex) { + // This is expected. + return; + } + // Printing some information to determine what might have gone wrong: + // E.g., if the generated secret is the same as the x-coordinate of the public key + // then it is likely that the ECDH computation was using a fake group with small order. + // Such a situation is probably exploitable. + // This probably is exploitable. If the curve of the private key was used for the ECDH + // then the generated secret and the x-coordinate of the public key are likely + // distinct. + EllipticCurve pubCurve = pub.getParams().getCurve(); + EllipticCurve privCurve = priv.getParams().getCurve(); + ECPoint pubW = pub.getW(); + System.out.println("testDistinctCurves: algorithm=" + algorithm); + System.out.println( + "Private key: a=" + + privCurve.getA() + + " b=" + + privCurve.getB() + + " p" + + EcUtil.getModulus(privCurve)); + System.out.println(" s =" + priv.getS()); + System.out.println( + "Public key: a=" + + pubCurve.getA() + + " b=" + + pubCurve.getB() + + " p" + + EcUtil.getModulus(pubCurve)); + System.out.println(" w = (" + pubW.getAffineX() + ", " + pubW.getAffineY() + ")"); + System.out.println( + " = (" + + pubW.getAffineX().toString(16) + + ", " + + pubW.getAffineY().toString(16) + + ")"); + System.out.println("generated shared secret:" + TestUtil.bytesToHex(shared)); + fail("Generated secret with distinct Curves using " + algorithm); + } + + /** + * This test modifies the order of group in the public key. A severe bug would be an + * implementation that leaks information whether the private key is larger than the order given in + * the public key. Also a severe bug would be to reduce the private key modulo the order given in + * the public key parameters. + */ + // TODO(bleichen): This can be merged with testModifiedPublic once this is fixed. + @SuppressWarnings("InsecureCryptoUsage") + public void testWrongOrder(String algorithm, ECParameterSpec spec) throws Exception { + KeyAgreement ka; + try { + ka = KeyAgreement.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + System.out.println("testWrongOrder: " + algorithm + " not supported"); + return; + } + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + ECPrivateKey priv; + ECPublicKey pub; + try { + keyGen.initialize(spec); + priv = (ECPrivateKey) keyGen.generateKeyPair().getPrivate(); + pub = (ECPublicKey) keyGen.generateKeyPair().getPublic(); + } catch (GeneralSecurityException ex) { + // This is OK, since not all provider support Brainpool curves + System.out.println("testWrongOrder: could not generate keys for curve"); + return; + } + // Get the shared secret for the unmodified keys. + ka.init(priv); + ka.doPhase(pub, true); + byte[] shared = ka.generateSecret(); + // Generate a modified public key. + ECParameterSpec modifiedParams = + new ECParameterSpec( + spec.getCurve(), spec.getGenerator(), spec.getOrder().shiftRight(16), 1); + ECPublicKeySpec modifiedPubSpec = new ECPublicKeySpec(pub.getW(), modifiedParams); + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPublicKey modifiedPub; + try { + modifiedPub = (ECPublicKey) kf.generatePublic(modifiedPubSpec); + } catch (GeneralSecurityException ex) { + // The provider does not support non-standard curves or did a validity check. + // Both would be correct. + System.out.println("testWrongOrder: can't modify order."); + return; + } + byte[] shared2; + try { + ka.init(priv); + ka.doPhase(modifiedPub, true); + shared2 = ka.generateSecret(); + } catch (GeneralSecurityException ex) { + // This is the expected behavior + System.out.println("testWrongOrder:" + ex.toString()); + return; + } + // TODO(bleichen): Getting here is already a bug and we might flag this later. + // At the moment we are only interested in really bad behavior of a library, that potentially + // leaks the secret key. This is the case when the shared secrets are different, since this + // suggests that the implementation reduces the multiplier modulo the given order of the curve + // or some other behaviour that is dependent on the private key. + // An attacker who can check whether a DH computation was done correctly or incorrectly because + // of modular reduction, can determine the private key, either by a binary search or by trying + // to guess the private key modulo some small "order". + // BouncyCastle v.1.53 fails this test, and leaks the private key. + System.out.println( + "Generated shared secret with a modified order:" + + algorithm + + "\n" + + "expected:" + + TestUtil.bytesToHex(shared) + + " computed:" + + TestUtil.bytesToHex(shared2)); + assertEquals( + "Algorithm:" + algorithm, TestUtil.bytesToHex(shared), TestUtil.bytesToHex(shared2)); + } + + public void testWrongOrderEcdh() throws Exception { + testWrongOrder("ECDH", EcUtil.getNistP256Params()); + testWrongOrder("ECDH", EcUtil.getBrainpoolP256r1Params()); + } + + public void testWrongOrderEcdhc() throws Exception { + testWrongOrder("ECDHC", EcUtil.getNistP256Params()); + testWrongOrder("ECDHC", EcUtil.getBrainpoolP256r1Params()); + } +} diff --git a/java/com/google/security/wycheproof/testcases/EcdsaTest.java b/java/com/google/security/wycheproof/testcases/EcdsaTest.java new file mode 100644 index 0000000..92058a7 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/EcdsaTest.java @@ -0,0 +1,902 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import com.google.security.wycheproof.WycheproofRunner.ProviderType; +import com.google.security.wycheproof.WycheproofRunner.SlowTest; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.util.Arrays; +import junit.framework.TestCase; + +/** + * Tests ECDSA against invalid signatures. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// Tested providers: +// SunEC: accepts a few alternative encodings and throws run time exceptions. +// The implementation does not protect against timing attacks. +// BC: accepts alternative encoding, and additional arguments +// AndroidOpenSSL: OK +// TODO(bleichen): +// - CVE-2015-2730: Firefox failed to handle some signatures correctly because of incorrect +// point multiplication. (I don't have enough information here.) +public class EcdsaTest extends TestCase { + // ECDSA-Key1 + static final String MESSAGE = "Hello"; + static final String CURVE = "secp256r1"; + static final BigInteger PubX = + new BigInteger( + "33903964965861532023650245008903090201819051686264021958530366090984128098564"); + static final BigInteger PubY = + new BigInteger( + "113542129898393725739068316260085522189065290079050903091108740065052129055287"); + + // Valid signatures for MESSAGE + static final String[] VALID_SIGNATURES = { + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + }; + + /** + * The following test vectors contain a valid signature that use alternative BER encoding. + * Whether such signatures are accepted as valid or rejected depends on the implementation. + * Allowing alternative BER encodings is in many cases benign. However, there are cases where this + * kind of signature malleability was a problem. See for example + * https://en.bitcoin.it/wiki/Transaction_Malleability + */ + // NOTE(bleichen): The following test vectors were generated with some python code. + // New test vectors should best be done by extending this code. Some of the signatures + // can be moved to INVALID_SIGNATURES, when b/31572415 is fixed. + static final String[] MODIFIED_SIGNATURES = { + // BER:long form encoding of length + "308145022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d" + + "491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e762" + + "85cd59f43260ecce", + "304602812100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d" + + "491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e762" + + "85cd59f43260ecce", + "3046022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f028120747291dd2f3f44af7ace68ea33431d6f94e418c106a6e762" + + "85cd59f43260ecce", + // BER:length contains leading 0 + "30820045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + "30470282002100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f02820020747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // BER:prepending 0's to integer + "30470223000000b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f02220000747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // NOTE (bleichen): belongs into INVALID_SIGNATURES. We only keep these + // sigantures here because of b/31572415. + // length = 2**31 - 1 + "30847fffffff022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "304902847fffffff00b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "3049022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f02847fffffff747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + }; + + /** + * Test vectors with invalid signatures. + * The motivation for these test vectors are previously broken implementations. E.g. + * <ul> + * <li> The implementation of DSA in gpg4browsers accepted signatures with r=1 and s=q as valid. + * Similar bugs in ECDSA are thinkable, hence the test vectors contain a number of tests with + * edge case integers. + * <li> CVE-2013-2944: strongSwan 5.0.4 accepts invalid ECDSA signatures when openssl is used. + * (Not sure if the following interpretation is correct, because of missing details). + * OpenSSLs error codes are easy to misinterpret. For many functions + * the result can be 0 (verification failed), 1 (verification succeded) + * or -1 (invalid format). A simple <code>if (result) { ... }</code> will be incorrect in + * such situations. The test vectors below contain incorrectly encoded signatures. + * </ul> + * <p> {@link java.security.Signature#verify(byte[])} should either return false or throw a + * SignatureException. Other behaviour such as throwing a RuntimeException might allow a denial + * of service attack: + * <ul> + * <li> CVE-2016-5546: OpenJDK8 throwed an OutOfmemoryError on some signatures. + * </ul> + * Some of the test vectors were derived from a valid signature by corrupting the DER encoding. + * If providers accepts such modified signatures for legacy purpose, then these signatures + * should be moved to MODIFIED_SIGNATURES. + */ + // NOTE(bleichen): The following test vectors were generated with some python code. New test + // vectors should best be done by extending the python code. + static final String[] INVALID_SIGNATURES = { + // wrong length + "3046022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3044022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022200b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022000b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0221747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f021f747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + // uint32 overflow in length + "30850100000045022100b7babae9332b54b8a3a05b7004579821a887a1b21465" + + "f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c1" + + "06a6e76285cd59f43260ecce", + "304a0285010000002100b7babae9332b54b8a3a05b7004579821a887a1b21465" + + "f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c1" + + "06a6e76285cd59f43260ecce", + "304a022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f02850100000020747291dd2f3f44af7ace68ea33431d6f94e418c1" + + "06a6e76285cd59f43260ecce", + // uint64 overflow in length + "3089010000000000000045022100b7babae9332b54b8a3a05b7004579821a887" + + "a1b21465f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f" + + "94e418c106a6e76285cd59f43260ecce", + "304e028901000000000000002100b7babae9332b54b8a3a05b7004579821a887" + + "a1b21465f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f" + + "94e418c106a6e76285cd59f43260ecce", + "304e022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0289010000000000000020747291dd2f3f44af7ace68ea33431d6f" + + "94e418c106a6e76285cd59f43260ecce", + // length = 2**32 - 1 + "3084ffffffff022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "30490284ffffffff00b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "3049022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0284ffffffff747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + // length = 2**64 - 1 + "3088ffffffffffffffff022100b7babae9332b54b8a3a05b7004579821a887a1" + + "b21465f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + "304d0288ffffffffffffffff00b7babae9332b54b8a3a05b7004579821a887a1" + + "b21465f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + "304d022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0288ffffffffffffffff747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + // removing sequence + "", + // appending 0's to sequence + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce0000", + // prepending 0's to sequence + "30470000022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // appending unused 0's + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce0000", + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f00000220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // appending null value + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce0500", + "3047022300b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f05000220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0222747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce0500", + // including garbage + "304949803045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "304925003045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "30473045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce0004deadbeef", + "304922254980022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "304922252500022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "304d2223022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0004deadbeef0220747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + "3049022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f222449800220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "3049022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f222425000220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "304d022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f22220220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce0004deadbeef", + // including undefined tags + "304daa00bb00cd003045022100b7babae9332b54b8a3a05b7004579821a887a1" + + "b21465f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + "304baa02aabb3045022100b7babae9332b54b8a3a05b7004579821a887a1b214" + + "65f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418" + + "c106a6e76285cd59f43260ecce", + "304d2229aa00bb00cd00022100b7babae9332b54b8a3a05b7004579821a887a1" + + "b21465f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + "304b2227aa02aabb022100b7babae9332b54b8a3a05b7004579821a887a1b214" + + "65f7db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418" + + "c106a6e76285cd59f43260ecce", + "304d022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f2228aa00bb00cd000220747291dd2f3f44af7ace68ea33431d6f94" + + "e418c106a6e76285cd59f43260ecce", + "304b022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f2226aa02aabb0220747291dd2f3f44af7ace68ea33431d6f94e418" + + "c106a6e76285cd59f43260ecce", + // changing tag value + "2e45022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3245022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "ff45022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045002100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045042100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045ff2100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0020747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0420747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3fff20747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + // dropping value of sequence + "3000", + // using composition + "304930010230442100b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "304922250201000220b7babae9332b54b8a3a05b7004579821a887a1b21465f7" + + "db8a3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + "3049022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f2224020174021f7291dd2f3f44af7ace68ea33431d6f94e418c106" + + "a6e76285cd59f43260ecce", + // truncate sequence + "3044022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ec", + "30442100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d491b" + + "39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd" + + "59f43260ecce", + // prepend empty sequence + "30473000022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // append empty sequence + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce3000", + // sequence of sequence + "30473045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a" + + "3d491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // truncated sequence + "3023022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d491b39fd2c3f", + // repeat element in sequence + "3067022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + // removing integer + "30220220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd59f43260ecce", + // appending 0's to integer + "3047022300b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f00000220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e7" + + "6285cd59f43260ecce", + "3047022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0222747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce0000", + // dropping value of integer + "302402000220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd59f43260ecce", + "3025022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d491b39fd2c3f0200", + // modify first byte of integer + "3045022101b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220757291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + // modify last byte of integer + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3e0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260eccf", + // truncate integer + "3044022000b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd" + + "59f43260ecce", + "30440220b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d491b" + + "39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd" + + "59f43260ecce", + "3044022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f021f747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ec", + "3044022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f021f7291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd" + + "59f43260ecce", + // leading ff in integer + "30460222ff00b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d" + + "491b39fd2c3f0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e762" + + "85cd59f43260ecce", + "3046022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f0221ff747291dd2f3f44af7ace68ea33431d6f94e418c106a6e762" + + "85cd59f43260ecce", + // infinity + "30250901800220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd59f43260ecce", + "3026022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d491b39fd2c3f090180", + // Vectors where r or s have been modified e.g. by adding or subtracting the order of the + // group or field and hence violate the range check for r and s required by ECDSA. + "30450221ff48454516ccd4ab475c5fa48ffba867de57785e4deb9a082475c2b6" + + "e4c602d3c10220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022101b7babae8332b54b9a3a05b7004579821656e9c5fbb7d96607df713" + + "de366051900220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3044022048454515ccd4ab485c5fa48ffba867de145f58fb92b1a6a9697c81a7" + + "c265f9120220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285cd" + + "59f43260ecce", + "3045022101b7babae8332b54b9a3a05b7004579821a887a1b31465f7db8a3d49" + + "1b39fd2c3e0220747291dd2f3f44af7ace68ea33431d6f94e418c106a6e76285" + + "cd59f43260ecce", + "3045022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f02208b8d6e22d0c0bb5085319715ccbce2906b1be73ef959189d7a" + + "32a60bcd9f1332", + "3046022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f022101747291dc2f3f44b07ace68ea33431d6f51cb136eadbe85e7" + + "798724b72ec4121f", + "3046022100b7babae9332b54b8a3a05b7004579821a887a1b21465f7db8a3d49" + + "1b39fd2c3f022101747291dc2f3f44b07ace68ea33431d6f94e418c206a6e762" + + "85cd59f43260eccd", + // Signatures with special case values for r and s (such as 0 and 1). Such values often + // uncover implementation errors. + "3006020100020100", + "3006020100020101", + "30060201000201ff", + "3026020100022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "3026020100022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "3026020100022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "3026020100022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "3026020100022100ffffffff00000001000000000000000000000001000000000000000000000000", + "3008020100090380fe01", + "3006020101020100", + "3006020101020101", + "30060201010201ff", + "3026020101022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "3026020101022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "3026020101022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "3026020101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "3026020101022100ffffffff00000001000000000000000000000001000000000000000000000000", + "3008020101090380fe01", + "30060201ff020100", + "30060201ff020101", + "30060201ff0201ff", + "30260201ff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "30260201ff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "30260201ff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "30260201ff022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "30260201ff022100ffffffff00000001000000000000000000000001000000000000000000000000", + "30080201ff090380fe01", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020100", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325510201ff", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632551", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632550", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632552", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632551022100ffffffff00000001000000000000000000000000ffffffff" + + "ffffffffffffffff", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632551022100ffffffff0000000100000000000000000000000100000000" + + "0000000000000000", + "3028022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632551090380fe01", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550020100", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550020101", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325500201ff", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632550022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632551", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632550022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632550", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632550022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632552", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632550022100ffffffff00000001000000000000000000000000ffffffff" + + "ffffffffffffffff", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632550022100ffffffff0000000100000000000000000000000100000000" + + "0000000000000000", + "3028022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632550090380fe01", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552020100", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552020101", + "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325520201ff", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632552022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632551", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632552022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632550", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632552022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632552", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632552022100ffffffff00000001000000000000000000000000ffffffff" + + "ffffffffffffffff", + "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632552022100ffffffff0000000100000000000000000000000100000000" + + "0000000000000000", + "3028022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca" + + "c2fc632552090380fe01", + "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff020100", + "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff020101", + "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff0201ff", + "3046022100ffffffff00000001000000000000000000000000ffffffffffffff" + + "ffffffffff022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632551", + "3046022100ffffffff00000001000000000000000000000000ffffffffffffff" + + "ffffffffff022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632550", + "3046022100ffffffff00000001000000000000000000000000ffffffffffffff" + + "ffffffffff022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632552", + "3046022100ffffffff00000001000000000000000000000000ffffffffffffff" + + "ffffffffff022100ffffffff00000001000000000000000000000000ffffffff" + + "ffffffffffffffff", + "3046022100ffffffff00000001000000000000000000000000ffffffffffffff" + + "ffffffffff022100ffffffff0000000100000000000000000000000100000000" + + "0000000000000000", + "3028022100ffffffff00000001000000000000000000000000ffffffffffffff" + + "ffffffffff090380fe01", + "3026022100ffffffff00000001000000000000000000000001000000000000000000000000020100", + "3026022100ffffffff00000001000000000000000000000001000000000000000000000000020101", + "3026022100ffffffff000000010000000000000000000000010000000000000000000000000201ff", + "3046022100ffffffff0000000100000000000000000000000100000000000000" + + "0000000000022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632551", + "3046022100ffffffff0000000100000000000000000000000100000000000000" + + "0000000000022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632550", + "3046022100ffffffff0000000100000000000000000000000100000000000000" + + "0000000000022100ffffffff00000000ffffffffffffffffbce6faada7179e84" + + "f3b9cac2fc632552", + "3046022100ffffffff0000000100000000000000000000000100000000000000" + + "0000000000022100ffffffff00000001000000000000000000000000ffffffff" + + "ffffffffffffffff", + "3046022100ffffffff0000000100000000000000000000000100000000000000" + + "0000000000022100ffffffff0000000100000000000000000000000100000000" + + "0000000000000000", + "3028022100ffffffff0000000100000000000000000000000100000000000000" + + "0000000000090380fe01", + }; + + /** + * Determines the Hash name from the ECDSA algorithm. There is a small inconsistency in the naming + * of algorithms. The Oracle standard use no hyphen in SHA256WithECDSA but uses a hyphen in the + * message digest, i.e., SHA-256. + */ + public String getHashAlgorithm(String ecdsaAlgorithm) { + ecdsaAlgorithm = ecdsaAlgorithm.toUpperCase(); + int idx = ecdsaAlgorithm.indexOf("WITH"); + if (idx > 0) { + if (ecdsaAlgorithm.startsWith("SHA")) { + return "SHA-" + ecdsaAlgorithm.substring(3, idx); + } else { + return ecdsaAlgorithm.substring(0, idx); + } + } + return ""; + } + + /** + * Extract the integer r from an ECDSA signature. This method implicitely assumes that the ECDSA + * signature is DER encoded. and that the order of the curve is smaller than 2^1024. + */ + BigInteger extractR(byte[] signature) throws Exception { + int startR = (signature[1] & 0x80) != 0 ? 3 : 2; + int lengthR = signature[startR + 1]; + return new BigInteger(Arrays.copyOfRange(signature, startR + 2, startR + 2 + lengthR)); + } + + BigInteger extractS(byte[] signature) throws Exception { + int startR = (signature[1] & 0x80) != 0 ? 3 : 2; + int lengthR = signature[startR + 1]; + int startS = startR + 2 + lengthR; + int lengthS = signature[startS + 1]; + return new BigInteger(Arrays.copyOfRange(signature, startS + 2, startS + 2 + lengthS)); + } + + /** Extract the k that was used to sign the signature. */ + BigInteger extractK(byte[] signature, BigInteger h, ECPrivateKey priv) throws Exception { + BigInteger x = priv.getS(); + BigInteger n = priv.getParams().getOrder(); + BigInteger r = extractR(signature); + BigInteger s = extractS(signature); + BigInteger k = x.multiply(r).add(h).multiply(s.modInverse(n)).mod(n); + return k; + } + + public ECPublicKeySpec publicKey1() throws Exception { + ECParameterSpec params = EcUtil.getNistP256Params(); + ECPoint w = new ECPoint(PubX, PubY); + return new ECPublicKeySpec(w, params); + } + + public void testVectors( + String[] signatures, + ECPublicKeySpec pubSpec, + String message, + String algorithm, + String signatureType, + boolean isValidDER, + boolean isValidBER) + throws Exception { + byte[] messageBytes = message.getBytes("UTF-8"); + Signature verifier = Signature.getInstance(algorithm); + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPublicKey pub = (ECPublicKey) kf.generatePublic(pubSpec); + int errors = 0; + for (String signature : signatures) { + byte[] signatureBytes = TestUtil.hexToBytes(signature); + verifier.initVerify(pub); + verifier.update(messageBytes); + boolean verified = false; + try { + verified = verifier.verify(signatureBytes); + } catch (SignatureException ex) { + // verify can throw SignatureExceptions if the signature is malformed. + // We don't flag these cases and simply consider the signature as invalid. + verified = false; + } + if (!verified && isValidDER) { + System.out.println(signatureType + " was not verified:" + signature); + errors++; + } + if (verified && !isValidBER) { + System.out.println(signatureType + " was verified:" + signature); + errors++; + } + } + assertEquals(0, errors); + } + + public void testValidSignatures() throws Exception { + testVectors( + VALID_SIGNATURES, publicKey1(), "Hello", "SHA256WithECDSA", "Valid ECDSA signature", + true, true); + } + + public void testModifiedSignatures() throws Exception { + testVectors( + MODIFIED_SIGNATURES, + publicKey1(), + "Hello", + "SHA256WithECDSA", + "Modified ECDSA signature", + false, + true); + } + + public void testInvalidSignatures() throws Exception { + testVectors( + INVALID_SIGNATURES, + publicKey1(), + "Hello", + "SHA256WithECDSA", + "Invalid ECDSA signature", + false, + false); + } + + /** + * This test checks the basic functionality of ECDSA. It can also be used to generate simple test + * vectors. + */ + public void testBasic() throws Exception { + String algorithm = "SHA256WithECDSA"; + String hashAlgorithm = "SHA-256"; + String message = "Hello"; + String curve = "secp256r1"; + + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + keyGen.initialize(ecSpec); + KeyPair keyPair = keyGen.generateKeyPair(); + ECPublicKey pub = (ECPublicKey) keyPair.getPublic(); + ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate(); + + byte[] messageBytes = message.getBytes("UTF-8"); + Signature signer = Signature.getInstance(algorithm); + Signature verifier = Signature.getInstance(algorithm); + signer.initSign(priv); + signer.update(messageBytes); + byte[] signature = signer.sign(); + verifier.initVerify(pub); + verifier.update(messageBytes); + assertTrue(verifier.verify(signature)); + + // Extract some parameters. + byte[] rawHash = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + ECParameterSpec params = priv.getParams(); + + // Print keys and signature, so that it can be used to generate new test vectors. + System.out.println("Message:" + message); + System.out.println("Hash:" + TestUtil.bytesToHex(rawHash)); + System.out.println("Curve:" + curve); + System.out.println("Order:" + params.getOrder().toString()); + System.out.println("Private key:"); + System.out.println("S:" + priv.getS().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(priv.getEncoded())); + System.out.println("Public key:"); + ECPoint w = pub.getW(); + System.out.println("X:" + w.getAffineX().toString()); + System.out.println("Y:" + w.getAffineY().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(pub.getEncoded())); + System.out.println("Signature:" + TestUtil.bytesToHex(signature)); + System.out.println("r:" + extractR(signature).toString()); + System.out.println("s:" + extractS(signature).toString()); + } + + /** Checks whether the one time key k in ECDSA is biased. */ + public void testBias(String algorithm, String curve, ECParameterSpec ecParams) throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + try { + keyGen.initialize(ecParams); + } catch (InvalidAlgorithmParameterException ex) { + System.out.println("This provider does not support curve:" + curve); + return; + } + KeyPair keyPair = keyGen.generateKeyPair(); + ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate(); + // If we throw a fair coin tests times then the probability that + // either heads or tails appears less than mincount is less than 2^{-32}. + // Therefore the test below is not expected to fail unless the generation + // of the one time keys is indeed biased. + final int tests = 1024; + final int mincount = 410; + + String hashAlgorithm = getHashAlgorithm(algorithm); + String message = "Hello"; + byte[] messageBytes = message.getBytes("UTF-8"); + byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + + // TODO(bleichen): Truncate the digest if the digest size is larger than the + // curve size. + BigInteger h = new BigInteger(1, digest); + BigInteger q = priv.getParams().getOrder(); + BigInteger qHalf = q.shiftRight(1); + + Signature signer = Signature.getInstance(algorithm); + signer.initSign(priv); + int countLsb = 0; // count the number of k's with msb set + int countMsb = 0; // count the number of k's with lsb set + for (int i = 0; i < tests; i++) { + signer.update(messageBytes); + byte[] signature = signer.sign(); + BigInteger k = extractK(signature, h, priv); + if (k.testBit(0)) { + countLsb++; + } + if (k.compareTo(qHalf) == 1) { + countMsb++; + } + } + System.out.println( + signer.getProvider().getName() + + " curve:" + + curve + + " countLsb:" + + countLsb + + " countMsb:" + + countMsb); + if (countLsb < mincount || countLsb > tests - mincount) { + fail("Bias detected in the least significant bit of k:" + countLsb); + } + if (countMsb < mincount || countMsb > tests - mincount) { + fail("Bias detected in the most significant bit of k:" + countMsb); + } + } + + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.CONSCRYPT, ProviderType.OPENJDK, + ProviderType.SPONGY_CASTLE}) + public void testBiasAll() throws Exception { + testBias("SHA256WithECDSA", "secp256r1", EcUtil.getNistP256Params()); + testBias("SHA224WithECDSA", "secp224r1", EcUtil.getNistP224Params()); + testBias("SHA384WithECDSA", "secp384r1", EcUtil.getNistP384Params()); + testBias("SHA512WithECDSA", "secp521r1", EcUtil.getNistP521Params()); + testBias("SHA256WithECDSA", "brainpoolP256r1", EcUtil.getBrainpoolP256r1Params()); + } + + /** + * Tests for a potential timing attack. This test checks if there is a correlation between the + * timing of signature generation and the size of the one-time key k. This is for example the case + * if a double and add method is used for the point multiplication. The test fails if such a + * correlation can be shown with high confidence. Further analysis will be necessary to determine + * how easy it is to exploit the bias in a timing attack. + */ + // TODO(bleichen): Determine if there are exploitable providers. + // + // SunEC currently fails this test. Since ECDSA typically is used with EC groups whose order + // is 224 bits or larger, it is unclear whether the same attacks that apply to DSA are practical. + // + // The ECDSA implementation in BouncyCastle leaks information about k through timing too. + // The test has not been optimized to detect this bias. It would require about 5'000'000 samples, + // which is too much for a simple unit test. + // + // BouncyCastle uses FixedPointCombMultiplier for ECDSA. This is a method using + // precomputation. The implementation is not constant time, since the precomputation table + // contains the point at infinity and adding this point is faster than ordinary point additions. + // The timing leak only has a small correlation to the size of k and at the moment it is is very + // unclear if the can be exploited. (Randomizing the precomputation table by adding the same + // random point to each element in the table and precomputing the necessary offset to undo the + // precomputation seems much easier than analyzing this.) + public void testTiming(String algorithm, String curve, ECParameterSpec ecParams) + throws Exception { + ThreadMXBean bean = ManagementFactory.getThreadMXBean(); + if (!bean.isCurrentThreadCpuTimeSupported()) { + System.out.println("getCurrentThreadCpuTime is not supported. Skipping"); + return; + } + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC"); + try { + keyGen.initialize(ecParams); + } catch (InvalidAlgorithmParameterException ex) { + System.out.println("This provider does not support curve:" + curve); + return; + } + KeyPair keyPair = keyGen.generateKeyPair(); + ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate(); + + String message = "Hello"; + String hashAlgorithm = getHashAlgorithm(algorithm); + byte[] messageBytes = message.getBytes("UTF-8"); + byte[] digest = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + BigInteger h = new BigInteger(1, digest); + Signature signer = Signature.getInstance(algorithm); + signer.initSign(priv); + // The number of samples used for the test. This number is a bit low. + // I.e. it just barely detects that SunEC leaks information about the size of k. + int samples = 50000; + long[] timing = new long[samples]; + BigInteger[] k = new BigInteger[samples]; + for (int i = 0; i < samples; i++) { + long start = bean.getCurrentThreadCpuTime(); + signer.update(messageBytes); + byte[] signature = signer.sign(); + timing[i] = bean.getCurrentThreadCpuTime() - start; + k[i] = extractK(signature, h, priv); + } + long[] sorted = Arrays.copyOf(timing, timing.length); + Arrays.sort(sorted); + double n = priv.getParams().getOrder().doubleValue(); + double expectedAverage = n / 2; + double maxSigma = 0; + System.out.println("testTiming algorithm:" + algorithm); + for (int idx = samples - 1; idx > 10; idx /= 2) { + long cutoff = sorted[idx]; + int count = 0; + BigInteger total = BigInteger.ZERO; + for (int i = 0; i < samples; i++) { + if (timing[i] <= cutoff) { + total = total.add(k[i]); + count += 1; + } + } + double expectedStdDev = n / Math.sqrt(12 * count); + double average = total.doubleValue() / count; + // Number of standard deviations that the average is away from + // the expected value: + double sigmas = (expectedAverage - average) / expectedStdDev; + if (sigmas > maxSigma) { + maxSigma = sigmas; + } + System.out.println( + "count:" + + count + + " cutoff:" + + cutoff + + " relative average:" + + (average / expectedAverage) + + " sigmas:" + + sigmas); + } + // Checks if the signatures with a small timing have a biased k. + // We use 7 standard deviations, so that the probability of a false positive is smaller + // than 10^{-10}. + if (maxSigma >= 7) { + fail("Signatures with short timing have a biased k"); + } + } + + @SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.CONSCRYPT, ProviderType.OPENJDK, + ProviderType.SPONGY_CASTLE}) + public void testTimingAll() throws Exception { + testTiming("SHA256WithECDSA", "secp256r1", EcUtil.getNistP256Params()); + // TODO(bleichen): crypto libraries sometimes use optimized code for curves that are frequently + // used. Hence it would make sense to test distinct curves. But at the moment testing many + // curves is not practical since one test alone is already quite time consuming. + // testTiming("SHA224WithECDSA", "secp224r1", EcUtil.getNistP224Params()); + // testTiming("SHA384WithECDSA", "secp384r1", EcUtil.getNistP384Params()); + // testTiming("SHA512WithECDSA", "secp521r1", EcUtil.getNistP521Params()); + // testTiming("SHA256WithECDSA", "brainpoolP256r1", EcUtil.getBrainpoolP256r1Params()); + } +} diff --git a/java/com/google/security/wycheproof/testcases/EciesTest.java b/java/com/google/security/wycheproof/testcases/EciesTest.java new file mode 100644 index 0000000..bd29bf8 --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/EciesTest.java @@ -0,0 +1,335 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.nio.ByteBuffer; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECGenParameterSpec; +import java.util.Arrays; +import java.util.HashSet; +import javax.crypto.Cipher; +import junit.framework.TestCase; + +/** + * Testing ECIES. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// Tested providers: +// BouncyCastle v 1.52: IESCipher is amazingly buggy, both from a crypto +// viewpoint and from an engineering viewpoint. It uses encryption modes that are completely +// inapproriate for ECIES or DHIES (i.e. ECB), the CBC implementation distinguishes between +// padding and MAC failures allowing adaptive chosen-ciphertext attacks. The implementation +// allows to specify paddings, but ignores them, encryption using ByteBuffers doesn't even work +// without exceptions, indicating that this hasn't even tested. +// +// <p>TODO(bleichen): +// - compressed points, +// - maybe again CipherInputStream, CipherOutputStream, +// - BouncyCastle has a KeyPairGenerator for ECIES. Is this one different from EC? +public class EciesTest extends TestCase { + + int expectedCiphertextLength(String algorithm, int coordinateSize, int messageLength) + throws Exception { + switch (algorithm.toUpperCase()) { + case "ECIESWITHAES-CBC": + // Uses the encoding + // 0x04 || coordinate x || coordinate y || PKCS5 padded ciphertext || 20-byte HMAC-digest. + return 1 + (2 * coordinateSize) + (messageLength - messageLength % 16 + 16) + 20; + default: + fail("Not implemented"); + } + return -1; + } + + /** + * Check that key agreement using ECIES works. This example does not specify an IESParametersSpec. + * BouncyCastle v.1.52 uses the following algorithms: KDF2 with SHA1 for the key derivation + * AES-CBC with PKCS #5 padding. HMAC-SHA1 with a 20 byte digest. The AES and the HMAC key are + * both 128 bits. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testEciesBasic() throws Exception { + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + KeyPairGenerator kf = KeyPairGenerator.getInstance("EC"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + PrivateKey priv = keyPair.getPrivate(); + PublicKey pub = keyPair.getPublic(); + byte[] message = "Hello".getBytes("UTF-8"); + Cipher ecies = Cipher.getInstance("ECIESwithAES-CBC"); + ecies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = ecies.doFinal(message); + System.out.println("testEciesBasic:" + TestUtil.bytesToHex(ciphertext)); + ecies.init(Cipher.DECRYPT_MODE, priv, ecies.getParameters()); + byte[] decrypted = ecies.doFinal(ciphertext); + assertEquals(TestUtil.bytesToHex(message), TestUtil.bytesToHex(decrypted)); + } + + /** + * ECIES does not allow encryption modes and paddings. If this test fails then we should add + * additional tests covering the new algorithms. + */ + // TODO(bleichen): This test describes BouncyCastles behaviour, but not necessarily what we + // expect. + @SuppressWarnings("InsecureCryptoUsage") + public void testInvalidNames() throws Exception { + String[] invalidNames = + new String[] { + "ECIESWITHAES/CBC/PKCS5PADDING", + "ECIESWITHAES/CBC/PKCS7PADDING", + "ECIESWITHAES/DHAES/NOPADDING", + "ECIESWITHDESEDE/DHAES/NOPADDING", + "ECIESWITHAES/ECB/NOPADDING", + "ECIESWITHAES/CTR/NOPADDING", + }; + for (String algorithm : invalidNames) { + try { + Cipher.getInstance(algorithm); + fail("unexpected algorithm:" + algorithm); + } catch (NoSuchAlgorithmException ex) { + // this is expected + } + } + } + + /** Here are a few names that BouncyCastle accepts. */ + // TODO(bleichen): This test describes BouncyCastles behaviour, but not necessarily what we + // expect. + @SuppressWarnings("InsecureCryptoUsage") + public void testValidNames() throws Exception { + String[] validNames = + new String[] { + "ECIES/DHAES/PKCS7PADDING", + "ECIESWITHAES-CBC/NONE/NOPADDING", + }; + for (String algorithm : validNames) { + Cipher.getInstance(algorithm); + } + } + + /** + * BouncyCastle has a key generation algorithm "ECIES". This test checks that the result are + * ECKeys in both cases. + */ + public void testKeyGeneration() throws Exception { + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + KeyPairGenerator kf = KeyPairGenerator.getInstance("ECIES"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate(); + ECPublicKey pub = (ECPublicKey) keyPair.getPublic(); + } + + /** + * Tries to decrypt ciphertexts where the symmetric part has been randomized. + * If this randomization leads to distinguishable exceptions then this may indicate that the + * implementation is vulnerable to a padding attack. + * + * Problems detected: + * <ul> + * <li> CVE-2016-1000345 BouncyCastle before v.1.56 is vulnerable to a padding oracle attack. + * </ul> + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testExceptions(String algorithm) throws Exception { + Cipher ecies; + try { + ecies = Cipher.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + // Allowing to skip the algorithm + System.out.println("No implementation for:" + algorithm); + return; + } + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + final int kemSize = 65; + KeyPairGenerator kf = KeyPairGenerator.getInstance("EC"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + PrivateKey priv = keyPair.getPrivate(); + PublicKey pub = keyPair.getPublic(); + byte[] message = new byte[40]; + ecies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = ecies.doFinal(message); + System.out.println(TestUtil.bytesToHex(ciphertext)); + ecies.init(Cipher.DECRYPT_MODE, priv, ecies.getParameters()); + HashSet<String> exceptions = new HashSet<String>(); + for (int byteNr = kemSize; byteNr < ciphertext.length; byteNr++) { + for (int bit = 0; bit < 8; bit++) { + byte[] corrupt = Arrays.copyOf(ciphertext, ciphertext.length); + corrupt[byteNr] ^= (byte) (1 << bit); + ecies.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); + try { + ecies.doFinal(corrupt); + fail("Decrypted:" + TestUtil.bytesToHex(corrupt)); + } catch (Exception ex) { + String exception = ex.toString(); + if (exceptions.add(exception)) { + System.out.println(algorithm + ":" + exception); + } + } + } + } + assertEquals(1, exceptions.size()); + } + + public void testEciesCorruptDefault() throws Exception { + testExceptions("ECIES"); + } + + @SuppressWarnings("InsecureCryptoUsage") + public void testModifyPoint() throws Exception { + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + KeyPairGenerator kf = KeyPairGenerator.getInstance("EC"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + PrivateKey priv = keyPair.getPrivate(); + PublicKey pub = keyPair.getPublic(); + byte[] message = "This is a long text since we need 32 bytes.".getBytes("UTF-8"); + Cipher ecies = Cipher.getInstance("ECIESwithAES-CBC"); + ecies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = ecies.doFinal(message); + ciphertext[2] ^= (byte) 1; + ecies.init(Cipher.DECRYPT_MODE, priv, ecies.getParameters()); + try { + ecies.doFinal(ciphertext); + fail("This should not work"); + } catch (GeneralSecurityException ex) { + // This is as expected + // Bouncy Castle 1.56 throws this exception + } catch (Exception ex) { + fail("Expected subclass of java.security.GeneralSecurityException, but got: " + + ex.getClass().getName()); + } + } + + /** + * This test tries to detect ECIES implementations using ECB. This is insecure and also violates + * the claims of ECIES, since ECIES is secure agains adaptive chosen-ciphertext attacks. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testNotEcb(String algorithm) throws Exception { + Cipher ecies; + try { + ecies = Cipher.getInstance(algorithm); + } catch (NoSuchAlgorithmException ex) { + // This test is called with short algorithm names such as just "ECIES". + // Requiring full names is typically a good practice. Hence it is OK + // to not assigning default algorithms. + System.out.println("No implementation for:" + algorithm); + return; + } + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + KeyPairGenerator kf = KeyPairGenerator.getInstance("EC"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + PublicKey pub = keyPair.getPublic(); + byte[] message = new byte[512]; + ecies.init(Cipher.ENCRYPT_MODE, pub); + byte[] ciphertext = ecies.doFinal(message); + String block1 = TestUtil.bytesToHex(Arrays.copyOfRange(ciphertext, 241, 257)); + String block2 = TestUtil.bytesToHex(Arrays.copyOfRange(ciphertext, 257, 273)); + assertTrue("Ciphertext repeats:" + TestUtil.bytesToHex(ciphertext), !block1.equals(block2)); + } + + public void testDefaultEcies() throws Exception { + testNotEcb("ECIES"); + } + + /** + * Tests whether algorithmA is an alias of algorithmB by encrypting with algorithmA and decrypting + * with algorithmB. + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testIsAlias(String algorithmA, String algorithmB) throws Exception { + Cipher eciesA; + Cipher eciesB; + // Allowing tests to be skipped, because we don't want to encourage abbreviations. + try { + eciesA = Cipher.getInstance(algorithmA); + } catch (NoSuchAlgorithmException ex) { + System.out.println("Skipping because of:" + ex.toString()); + return; + } + try { + eciesB = Cipher.getInstance(algorithmB); + } catch (NoSuchAlgorithmException ex) { + System.out.println("Skipping because of:" + ex.toString()); + return; + } + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + KeyPairGenerator kf = KeyPairGenerator.getInstance("EC"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + byte[] message = "Hello".getBytes("UTF-8"); + eciesA.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); + byte[] ciphertext = eciesA.doFinal(message); + eciesB.init(Cipher.DECRYPT_MODE, keyPair.getPrivate(), eciesB.getParameters()); + byte[] decrypted = eciesB.doFinal(ciphertext); + assertEquals(TestUtil.bytesToHex(message), TestUtil.bytesToHex(decrypted)); + } + + /** Tests whether two distinct algorithm names implement the same cipher */ + public void testAlias() throws Exception { + testIsAlias("ECIESWITHAES-CBC", "ECIESWithAES-CBC"); + testIsAlias("ECIESWITHAES", "ECIESWithAES"); + // BouncyCastle v 1.52 ignores mode and padding and considers the following + // names as equivalent: + // testIsAlias("ECIES/DHAES/PKCS7PADDING", "ECIES"); + testIsAlias("ECIESWITHAES-CBC/NONE/PKCS7PADDING", "ECIESWITHAES-CBC/NONE/NOPADDING"); + } + + /** + * Cipher.doFinal(ByteBuffer, ByteBuffer) should be copy-safe according to + * https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html + * + * <p>This test tries to verify this. + */ + /* TODO(bleichen): There's no point to run this test as long as the previous basic test fails. + public void testByteBufferAlias() throws Exception { + byte[] message = "Hello".getBytes("UTF-8"); + String algorithm = "ECIESWithAES-CBC"; + ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); + KeyPairGenerator kf = KeyPairGenerator.getInstance("EC"); + kf.initialize(ecSpec); + KeyPair keyPair = kf.generateKeyPair(); + Cipher ecies = Cipher.getInstance(algorithm); + + int ciphertextLength = expectedCiphertextLength(algorithm, 32, message.length); + byte[] backingArray = new byte[ciphertextLength]; + ByteBuffer ptBuffer = ByteBuffer.wrap(backingArray); + ptBuffer.put(message); + ptBuffer.flip(); + + ecies.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); + ByteBuffer ctBuffer = ByteBuffer.wrap(backingArray); + ecies.doFinal(ptBuffer, ctBuffer); + ctBuffer.flip(); + + ecies.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); + byte[] decrypted = ecies.doFinal(backingArray, 0, ctBuffer.remaining()); + assertEquals(TestUtil.bytesToHex(message), TestUtil.bytesToHex(decrypted)); + } + */ +} diff --git a/java/com/google/security/wycheproof/testcases/RsaEncryptionTest.java b/java/com/google/security/wycheproof/testcases/RsaEncryptionTest.java new file mode 100644 index 0000000..a15d45d --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/RsaEncryptionTest.java @@ -0,0 +1,227 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.HashSet; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import junit.framework.TestCase; + +/** + * RSA encryption tests + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// TODO(bleichen): test vectors check special cases: +// - ciphertext too long +// - plaintext too long +// - ciphertext 0 +// - ciphertext == modulus timing attacks +public class RsaEncryptionTest extends TestCase { + + /** + * Providers that implement RSA with PKCS1Padding but not OAEP are outdated and should be avoided + * even if RSA is currently not used in a project. Such providers promote using an insecure + * cipher. There is a great danger that PKCS1Padding is used as a temporary workaround, but later + * stays in the project for much longer than necessary. + */ + public void testOutdatedProvider() throws Exception { + try { + Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + try { + Cipher.getInstance("RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING"); + } catch (NoSuchPaddingException | NoSuchAlgorithmException ex) { + fail("Provider " + c.getProvider().getName() + " is outdated and should not be used."); + } + } catch (NoSuchPaddingException | NoSuchAlgorithmException ex) { + System.out.println("RSA/ECB/PKCS1Padding is not implemented"); + } + } + + /** + * Tries decrypting random messages with a given algorithm. Counts the number of distinct error + * messages and expects this number to be 1. + * + * <p><b>References:</b> + * + * <ul> + * <li>Bleichenbacher, "Chosen ciphertext attacks against protocols based on the RSA encryption + * standard PKCS# 1" Crypto 98 + * <li>Manger, "A chosen ciphertext attack on RSA optimal asymmetric encryption padding (OAEP) + * as standardized in PKCS# 1 v2.0", Crypto 2001 This paper shows that OAEP is susceptible + * to a chosen ciphertext attack if error messages distinguish between different failure + * condidtions. + * <li>Bardou, Focardi, Kawamoto, Simionato, Steel, Tsay "Efficient Padding Oracle Attacks on + * Cryptographic Hardware", Crypto 2012 The paper shows that small differences on what + * information an attacker recieves can make a big difference on the number of chosen + * message necessary for an attack. + * <li>Smart, "Errors matter: Breaking RSA-based PIN encryption with thirty ciphertext validity + * queries" RSA conference, 2010 This paper shows that padding oracle attacks can be + * successful with even a small number of queries. + * </ul> + * + * <p><b>Some recent bugs:</b> CVE-2012-5081: Java JSSE provider leaked information through + * exceptions and timing. Both the PKCS #1 padding and the OAEP padding were broken: + * http://www-brs.ub.ruhr-uni-bochum.de/netahtml/HSS/Diss/MeyerChristopher/diss.pdf + * + * <p><b>What this test does not (yet) cover:</b> + * + * <ul> + * <li> A previous version of one of the provider leaked the block type. (when was this fixed?) + * <li> Some attacks require a large number of ciphertexts to be detected if random ciphertexts + * are used. Such problems require specifically crafted ciphertexts to run in a unit test. + * E.g. "Attacking RSA-based Sessions in SSL/TLS" by V. Klima, O. Pokorny, and T. Rosa: + * https://eprint.iacr.org/2003/052/ + * <li> Timing leakages because of differences in parsing the padding (e.g. CVE-2015-7827) Such + * differences are too small to be reliably detectable in unit tests. + * </ul> + */ + @SuppressWarnings("InsecureCryptoUsage") + public void testExceptions(String algorithm) throws Exception { + KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA"); + keygen.initialize(1024); + KeyPair keypair = keygen.genKeyPair(); + SecureRandom rand = new SecureRandom(); + Cipher c = Cipher.getInstance(algorithm); + byte[] ciphertext = new byte[1024 / 8]; + HashSet<String> exceptions = new HashSet<String>(); + final int samples = 1000; + for (int i = 0; i < samples; i++) { + rand.nextBytes(ciphertext); + ciphertext[0] &= (byte) 0x7f; + try { + c.init(Cipher.DECRYPT_MODE, keypair.getPrivate()); + c.doFinal(ciphertext); + } catch (Exception ex) { + exceptions.add(ex.toString()); + } + } + Cipher enc = Cipher.getInstance("RSA/ECB/NOPADDING"); + enc.init(Cipher.ENCRYPT_MODE, keypair.getPublic()); + c.init(Cipher.DECRYPT_MODE, keypair.getPrivate()); + byte[][] paddedKeys = generatePkcs1Vectors(1024 / 8); + for (int i = 0; i < paddedKeys.length; i++) { + ciphertext = enc.doFinal(paddedKeys[i]); + try { + c.doFinal(ciphertext); + } catch (Exception ex) { + exceptions.add(ex.toString()); + } + } + if (exceptions.size() > 1) { + System.out.println("Exceptions for " + algorithm); + for (String s : exceptions) { + System.out.println(s); + } + fail("Exceptions leak information about the padding for " + algorithm); + } + } + + /** + * Tests the exceptions for RSA decryption with PKCS1Padding. PKCS1Padding is susceptible to + * chosen message attacks. Nonetheless, to minimize the damage of such an attack an implementation + * should minimize the information about the failure in the padding. + */ + public void testExceptionsPKCS1() throws Exception { + testExceptions("RSA/ECB/PKCS1PADDING"); + } + + public void testGetExceptionsOAEP() throws Exception { + testExceptions("RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING"); + } + + /** + * Generates PKCS#1 invalid vectors + * @param rsaKeyLength + * @return + */ + private byte[][] generatePkcs1Vectors(int rsaKeyLength) { + // create plain padded keys + byte[][] plainPaddedKeys = new byte[13][]; + // no 0x00 byte to deliver a symmetric key + plainPaddedKeys[0] = getEK_NoNullByte(rsaKeyLength); + // 0x00 too early in the padding + plainPaddedKeys[1] = getEK_NullByteInPadding(rsaKeyLength); + // 0x00 too early in the PKCS#1 padding + plainPaddedKeys[2] = getEK_NullByteInPkcsPadding(rsaKeyLength); + // decrypted ciphertext starting with 0x17 0x02 + plainPaddedKeys[3] = getEK_WrongFirstByte(rsaKeyLength); + // decrypted ciphertext starting with 0x00 0x17 + plainPaddedKeys[4] = getEK_WrongSecondByte(rsaKeyLength); + // different lengths of the decrypted unpadded key + plainPaddedKeys[5] = getPaddedKey(rsaKeyLength, 0); + plainPaddedKeys[6] = getPaddedKey(rsaKeyLength, 1); + plainPaddedKeys[7] = getPaddedKey(rsaKeyLength, 8); + plainPaddedKeys[8] = getPaddedKey(rsaKeyLength, 16); + plainPaddedKeys[9] = getPaddedKey(rsaKeyLength, 96); + // the decrypted padded plaintext is shorter than RSA key + plainPaddedKeys[10] = getPaddedKey(rsaKeyLength - 1, 16); + plainPaddedKeys[11] = getPaddedKey(rsaKeyLength - 2, 16); + // just 0x00 bytes + plainPaddedKeys[12] = new byte[rsaKeyLength]; + return plainPaddedKeys; + } + + private byte[] getPaddedKey(int rsaKeyLength, int symmetricKeyLength) { + byte[] key = new byte[rsaKeyLength]; + // fill all the bytes with non-zero values + Arrays.fill(key, (byte) 42); + // set the first byte to 0x00 + key[0] = 0x00; + // set the second byte to 0x02 + key[1] = 0x02; + // set the separating byte + if(symmetricKeyLength != -1) { + key[rsaKeyLength - symmetricKeyLength - 1] = 0x00; + } + return key; + } + + private byte[] getEK_WrongFirstByte(int rsaKeyLength) { + byte[] key = getPaddedKey(rsaKeyLength, 16); + key[0] = 23; + return key; + } + + private byte[] getEK_WrongSecondByte(int rsaKeyLength) { + byte[] key = getPaddedKey(rsaKeyLength, 16); + key[1] = 23; + return key; + } + + private byte[] getEK_NoNullByte(int rsaKeyLength) { + byte[] key = getPaddedKey(rsaKeyLength, -1); + return key; + } + + private byte[] getEK_NullByteInPkcsPadding(int rsaKeyLength) { + byte[] key = getPaddedKey(rsaKeyLength, 16); + key[3] = 0x00; + return key; + } + + private byte[] getEK_NullByteInPadding(int rsaKeyLength) { + byte[] key = getPaddedKey(rsaKeyLength, 16); + key[11] = 0x00; + return key; + } +} diff --git a/java/com/google/security/wycheproof/testcases/RsaKeyTest.java b/java/com/google/security/wycheproof/testcases/RsaKeyTest.java new file mode 100644 index 0000000..b761dae --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/RsaKeyTest.java @@ -0,0 +1,1513 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import junit.framework.TestCase; + +/** + * Tests RSA keys. Signatures and encryption are tested in different tests. + * + * @author bleichen@google.com (Daniel Bleichenbacher) + */ +// TODO(bleichen): +// - Add checks for bad random numbers +// - expect keys with e=1 to be rejected +// - expect keys with e=0 to be rejected +// - document stuff +// - Maybe also check encodings of private keys. +// - Test multi prime RSA +// - Tests for alternative representations: +// many libraries sort the primes as: p > q (but not all) +// some libraries compute d mod lambda(n) +// paramaters p,q,... are not really required +// - checks for bad random number generation +public class RsaKeyTest extends TestCase { + + public static final String ENCODED_PUBLIC_KEY = + "30819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001"; + + /** + * Encodings of the public key from ENCODED_PUBLIC_KEY with modifications. + * This list so far has just a simple purpose: it is used to check whether parsing the key + * leads to some unexpected exceptions. I.e. it should not be possible to crash an + * application with an modified public key. + */ + public static final String[] MODIFIED_PUBLIC_KEY = { + // length contains leading 0 + "3082009f300d06092a864886f70d010101050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "3081a13082000d06092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f068200092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f06092a864886f70d0101010582000003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a0300d06092a864886f70d01010105000382008d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "30819f300d06092a864886f70d010101050003818d3082008902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101050003818d30818a0282008100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02820003" + + "010001", + // wrong length + "30a0300d06092a864886f70d010101050003818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "309e300d06092a864886f70d010101050003818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819f300e06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300c06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d060a2a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06082a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101050103818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819e300d06092a864886f70d0101010500038e0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d0101010500038c0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819d300d06092a864886f70d010101050003818b308a02818100ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "30819d300d06092a864886f70d010101050003818b308802818100ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "30819d300d06092a864886f70d010101050003818b308188028200ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "30819d300d06092a864886f70d010101050003818b308188028000ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02040100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02020100" + + "01", + // uint32 overflow in length + "3085010000009f300d06092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a43085010000000d06092a864886f70d010101050003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a43012068501000000092a864886f70d010101050003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a4301206092a864886f70d0101010585010000000003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a3300d06092a864886f70d01010105000385010000008d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a2300d06092a864886f70d01010105000381903085010000008902818100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "0203010001", + "3081a2300d06092a864886f70d010101050003819030818d0285010000008100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "0203010001", + "3081a3300d06092a864886f70d010101050003819130818e02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02850100" + + "000003010001", + // uint64 overflow in length + "308901000000000000009f300d06092a864886f70d010101050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a8308901000000000000000d06092a864886f70d010101050003818d0030" + + "818902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c5410" + + "0cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4" + + "d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984" + + "b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315ac" + + "f9a0b351a23f0203010001", + "3081a8301606890100000000000000092a864886f70d010101050003818d0030" + + "818902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c5410" + + "0cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4" + + "d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984" + + "b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315ac" + + "f9a0b351a23f0203010001", + "3081a8301606092a864886f70d010101058901000000000000000003818d0030" + + "818902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c5410" + + "0cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4" + + "d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984" + + "b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315ac" + + "f9a0b351a23f0203010001", + "3081a7300d06092a864886f70d0101010500038901000000000000008d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a6300d06092a864886f70d01010105000381943089010000000000000089" + + "02818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6" + + "e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f1" + + "09fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562" + + "517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0" + + "b351a23f0203010001", + "3081a6300d06092a864886f70d01010105000381943081910289010000000000" + + "00008100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6" + + "e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f1" + + "09fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562" + + "517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0" + + "b351a23f0203010001", + "3081a7300d06092a864886f70d010101050003819530819202818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02890100" + + "00000000000003010001", + // length = 2**32 - 1 + "3084ffffffff300d06092a864886f70d010101050003818d0030818902818100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "0203010001", + "3081a33084ffffffff06092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a330110684ffffffff2a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a3301106092a864886f70d0101010584ffffffff03818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a2300d06092a864886f70d01010105000384ffffffff0030818902818100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "0203010001", + "3081a1300d06092a864886f70d010101050003818f3084ffffffff02818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300d06092a864886f70d010101050003818f30818c0284ffffffff00ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a2300d06092a864886f70d010101050003819030818d02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0284ffff" + + "ffff010001", + // length = 2**64 - 1 + "3088ffffffffffffffff300d06092a864886f70d010101050003818d00308189" + + "02818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6" + + "e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f1" + + "09fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562" + + "517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0" + + "b351a23f0203010001", + "3081a73088ffffffffffffffff06092a864886f70d010101050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a730150688ffffffffffffffff2a864886f70d010101050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a7301506092a864886f70d0101010588ffffffffffffffff03818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a6300d06092a864886f70d01010105000388ffffffffffffffff00308189" + + "02818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6" + + "e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f1" + + "09fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562" + + "517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0" + + "b351a23f0203010001", + "3081a5300d06092a864886f70d01010105000381933088ffffffffffffffff02" + + "818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a5300d06092a864886f70d01010105000381933081900288ffffffffffff" + + "ffff00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a6300d06092a864886f70d010101050003819430819102818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0288ffff" + + "ffffffffffff010001", + // removing sequence + "", + "30819003818d0030818902818100ab9014dc47d44b6d260fc1fef9ab022042fd" + + "9566e9d7b60c54100cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb1" + + "67d8a44ab93d73c4d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e" + + "043b6fec81f9d984b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31" + + "dad83563f3a315acf9a0b351a23f0203010001", + // appending 0's to sequence + "3081a1300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00010000", + "3081a1300f06092a864886f70d0101010500000003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "010000", + // prepending 0's to sequence + "3081a10000300d06092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f000006092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a0300d06092a864886f70d010101050003818e30818b000002818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + // appending unused 0's + "30819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00010000", + "3081a1300d06092a864886f70d0101010500000003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f06092a864886f70d0101010000050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a0300d06092a864886f70d010101050003818e30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "010000", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f00000203" + + "010001", + // appending null value + "3081a1300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00010500", + "3081a1300f06092a864886f70d0101010500050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f060b2a864886f70d0101010500050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f06092a864886f70d0101010502050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300d06092a864886f70d010101050003818f0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00010500", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "010500", + "3081a0300d06092a864886f70d010101050003818e30818b02818300ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f05000203" + + "010001", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02050100" + + "010500", + // including garbage + "3081a4498030819f300d06092a864886f70d010101050003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a4250030819f300d06092a864886f70d010101050003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a230819f300d06092a864886f70d010101050003818d0030818902818100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "02030100010004deadbeef", + "3081a330114980300d06092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a330112500300d06092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a7300f300d06092a864886f70d01010105000004deadbeef03818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a33011260d498006092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a33011260d250006092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a73015260b06092a864886f70d0101010004deadbeef050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a3301106092a864886f70d01010125044980050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a3301106092a864886f70d01010125042500050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a7301506092a864886f70d010101250205000004deadbeef03818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a4300d06092a864886f70d0101010500238192498003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a4300d06092a864886f70d0101010500238192250003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a8300d06092a864886f70d010101050023819003818d0030818902818100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "02030100010004deadbeef", + "3081a3300d06092a864886f70d010101050003819130818e4980308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a3300d06092a864886f70d010101050003819130818e2500308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a7300d06092a864886f70d010101050003819530818c30818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "030100010004deadbeef", + "3081a3300d06092a864886f70d010101050003819130818e2281864980028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a3300d06092a864886f70d010101050003819130818e2281862500028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a7300d06092a864886f70d010101050003819530819222818402818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f00" + + "04deadbeef0203010001", + "3081a2300d06092a864886f70d010101050003819030818d02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f22074980" + + "0203010001", + "3081a2300d06092a864886f70d010101050003819030818d02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f22072500" + + "0203010001", + "3081a6300d06092a864886f70d010101050003819430819102818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f22050203" + + "0100010004deadbeef", + // including undefined tags + "3081a8aa00bb00cd0030819f300d06092a864886f70d010101050003818d0030" + + "818902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c5410" + + "0cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4" + + "d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984" + + "b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315ac" + + "f9a0b351a23f0203010001", + "3081a6aa02aabb30819f300d06092a864886f70d010101050003818d00308189" + + "02818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6" + + "e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f1" + + "09fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562" + + "517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0" + + "b351a23f0203010001", + "3081a73015aa00bb00cd00300d06092a864886f70d010101050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a53013aa02aabb300d06092a864886f70d010101050003818d0030818902" + + "818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a730152611aa00bb00cd0006092a864886f70d010101050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a53013260faa02aabb06092a864886f70d010101050003818d0030818902" + + "818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a7301506092a864886f70d0101012508aa00bb00cd00050003818d003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a5301306092a864886f70d0101012506aa02aabb050003818d0030818902" + + "818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a8300d06092a864886f70d0101010500238196aa00bb00cd0003818d0030" + + "818902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c5410" + + "0cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4" + + "d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984" + + "b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315ac" + + "f9a0b351a23f0203010001", + "3081a6300d06092a864886f70d0101010500238194aa02aabb03818d00308189" + + "02818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6" + + "e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f1" + + "09fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562" + + "517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0" + + "b351a23f0203010001", + "3081a7300d06092a864886f70d0101010500038195308192aa00bb00cd003081" + + "8902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a5300d06092a864886f70d0101010500038193308190aa02aabb30818902" + + "818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a7300d06092a864886f70d010101050003819530819222818aaa00bb00cd" + + "0002818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100c" + + "b6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0" + + "f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b5" + + "62517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9" + + "a0b351a23f0203010001", + "3081a5300d06092a864886f70d0101010500038193308190228188aa02aabb02" + + "818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1" + + "d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109" + + "fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b56251" + + "7e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b3" + + "51a23f0203010001", + "3081a6300d06092a864886f70d010101050003819430819102818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f220baa00" + + "bb00cd000203010001", + "3081a4300d06092a864886f70d010101050003819230818f02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f2209aa02" + + "aabb0203010001", + // changing tag value + "2e819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "32819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "ff819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f2e0d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f320d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819fff0d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d04092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d08092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300dff092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101030003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101070003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101ff0003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101050001818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101050005818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d0101010500ff818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819e300d06092a864886f70d010101050003818c2e818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c32818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818cff818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818900818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818904818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c308189ff818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f00030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f04030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23fff030100" + + "01", + // dropping value of sequence + "3000", + "308192300003818d0030818902818100ab9014dc47d44b6d260fc1fef9ab0220" + + "42fd9566e9d7b60c54100cb6e1d4edc98590467d0502c17fce69d00ac5efb40b" + + "2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236ff517cf84412e173679cfa" + + "e42e043b6fec81f9d984b562517e6febe1f72295dbc3fdfc19d3240aa7551556" + + "3f31dad83563f3a315acf9a0b351a23f0203010001", + // using composition + "3081a430013030819e0d06092a864886f70d010101050003818d003081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a33011300106300c092a864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a33011260d06012a0608864886f70d010101050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a4300d06092a864886f70d010101050023819203010003818c3081890281" + + "8100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4" + + "edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb" + + "5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e" + + "6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351" + + "a23f0203010001", + "3081a3300d06092a864886f70d010101050003819130818e3001023081888181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a3300d06092a864886f70d010101050003819130818e2281860201000281" + + "80ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + "3081a2300d06092a864886f70d010101050003819030818d02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f22070201" + + "0102020001", + // truncate sequence + "30819e300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00", + "30819e0d06092a864886f70d010101050003818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300c06092a864886f70d0101010503818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300c092a864886f70d010101050003818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819d300d06092a864886f70d010101050003818b30818802818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100", + "30819d300d06092a864886f70d010101050003818b308188818100ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + // prepend empty sequence + "3081a13000300d06092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300f300006092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a0300d06092a864886f70d010101050003818e30818b300002818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + // append empty sequence + "3081a1300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00013000", + "3081a1300f06092a864886f70d0101010500300003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "013000", + // sequence of sequence + "3081a230819f300d06092a864886f70d010101050003818d0030818902818100" + + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "0203010001", + "3081a1300f300d06092a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + "3081a1300d06092a864886f70d010101050003818f30818c30818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + // truncated sequence + "300f300d06092a864886f70d0101010500", + "30819d300b06092a864886f70d01010103818d0030818902818100ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "308199300d06092a864886f70d010101050003818730818402818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f", + // repeat element in sequence + "3082012f300d06092a864886f70d010101050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "01000103818d0030818902818100ab9014dc47d44b6d260fc1fef9ab022042fd" + + "9566e9d7b60c54100cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb1" + + "67d8a44ab93d73c4d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e" + + "043b6fec81f9d984b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31" + + "dad83563f3a315acf9a0b351a23f0203010001", + "3081a3300d06092a864886f70d010101050003819130818e02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "010203010001", + // long form encoding of length + "3081a030810d06092a864886f70d010101050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "3081a0300e0681092a864886f70d010101050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "3081a0300e06092a864886f70d01010105810003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "30819f300d06092a864886f70d010101050003818d30818a02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02810301" + + "0001", + // removing oid + "3081943002050003818d0030818902818100ab9014dc47d44b6d260fc1fef9ab" + + "022042fd9566e9d7b60c54100cb6e1d4edc98590467d0502c17fce69d00ac5ef" + + "b40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236ff517cf84412e17367" + + "9cfae42e043b6fec81f9d984b562517e6febe1f72295dbc3fdfc19d3240aa755" + + "15563f31dad83563f3a315acf9a0b351a23f0203010001", + // appending 0's to oid + "3081a1300f060b2a864886f70d0101010000050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + // prepending 0's to oid + "3081a1300f060b00002a864886f70d010101050003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + // dropping value of oid + "30819630040600050003818d0030818902818100ab9014dc47d44b6d260fc1fe" + + "f9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d0502c17fce69d00a" + + "c5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236ff517cf84412e1" + + "73679cfae42e043b6fec81f9d984b562517e6febe1f72295dbc3fdfc19d3240a" + + "a75515563f31dad83563f3a315acf9a0b351a23f0203010001", + // modify first byte of oid + "30819f300d06092b864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + // modify last byte of oid + "30819f300d06092a864886f70d010100050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + // truncate oid + "30819e300c06082a864886f70d0101050003818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300c0608864886f70d010101050003818d0030818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + // wrong oid + "30819b300906052b0e03021a050003818d0030818902818100ab9014dc47d44b" + + "6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d0502c1" + + "7fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236ff51" + + "7cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295dbc3fd" + + "fc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "30819f300d0609608648016503040201050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + // longer oid + "3081a0300e060a2a864886f70d01010101050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + // oid with modified node + "30819f300d06092a864886f70d010111050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "3081a33011060d2a864886f70d01018880808001050003818d00308189028181" + + "00ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4ed" + + "c98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a" + + "26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6f" + + "ebe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a2" + + "3f0203010001", + // large integer in oid + "3081a8301606122a864886f70d010182808080808080808001050003818d0030" + + "818902818100ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c5410" + + "0cb6e1d4edc98590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4" + + "d0f109fb5a26c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984" + + "b562517e6febe1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315ac" + + "f9a0b351a23f0203010001", + // oid with invalid node + "3081a0300e060a2a864886f70d010101e0050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "3081a0300e060a2a80864886f70d010101050003818d0030818902818100ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + // appending 0's to null + "3081a1300f06092a864886f70d0101010502000003818d0030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + // appending 0's to bit string + "3081a1300d06092a864886f70d010101050003818f0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00010000", + // prepending 0's to bit string + "3081a1300d06092a864886f70d010101050003818f00000030818902818100ab" + + "9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc985" + + "90467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2" + + "f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1" + + "f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02" + + "03010001", + // modify first byte of bit string + "30819f300d06092a864886f70d010101050003818d0130818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + // modify last byte of bit string + "30819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0000", + // truncate bit string + "30819e300d06092a864886f70d010101050003818c0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "00", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + // removing integer + "3018300d06092a864886f70d0101010500030730050203010001", + // appending 0's to integer + "3081a0300d06092a864886f70d010101050003818e30818b02818300ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f00000203" + + "010001", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02050100" + + "010000", + // prepending 0's to integer + "3081a0300d06092a864886f70d010101050003818e30818b028183000000ab90" + + "14dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590" + + "467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8" + + "823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f7" + + "2295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203" + + "010001", + "3081a0300d06092a864886f70d010101050003818e30818b02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02050000" + + "010001", + // dropping value of integer + "301a300d06092a864886f70d01010105000309300702000203010001", + "30819b300d06092a864886f70d010101050003818930818602818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0200", + // modify first byte of integer + "30819e300d06092a864886f70d010101050003818c30818902818101ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030000" + + "01", + // modify last byte of integer + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23e02030100" + + "01", + "30819e300d06092a864886f70d010101050003818c30818902818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02030100" + + "00", + // truncate integer + "30819d300d06092a864886f70d010101050003818b30818802818000ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a20203010001", + "30819d300d06092a864886f70d010101050003818b308188028180ab9014dc47" + + "d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d05" + + "02c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f8823236" + + "ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295db" + + "c3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203010001", + "30819d300d06092a864886f70d010101050003818b30818802818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02020100", + "30819d300d06092a864886f70d010101050003818b30818802818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f02020001", + // leading ff in integer + "30819f300d06092a864886f70d010101050003818d30818a028182ff00ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020301" + + "0001", + "30819f300d06092a864886f70d010101050003818d30818a02818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0204ff01" + + "0001", + // infinity + "301b300d06092a864886f70d0101010500030a30080901800203010001", + "30819c300d06092a864886f70d010101050003818a30818702818100ab9014dc" + + "47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc98590467d" + + "0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f88232" + + "36ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f72295" + + "dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f090180", + // n=0 + "301c300d06092a864886f70d0101010500030b0030080201000203010001", + // negative n + "30819f300d06092a864886f70d010101050003818d00308189028181ff546feb" + + "23b82bb492d9f03e010654fddfbd026a99162849f3abeff3491e2b12367a6fb9" + + "82fafd3e8031962ff53a104bf4d34e98275bb546c28c3b2f0ef604a5d93d077d" + + "cdc900ae8307bbed1e8c9863051bd1fbc490137e06267b4a9dae8190141e08dd" + + "6a243c0203e62cdbf558aaeaa9c0ce2527ca9c0c5cea53065f4cae5dc1020301" + + "0001", + // e=0 + "30819d300d06092a864886f70d010101050003818b0030818702818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020100", + // e=1 + "30819d300d06092a864886f70d010101050003818b0030818702818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020101", + // e=2 + "30819d300d06092a864886f70d010101050003818b0030818702818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f020102", + // negative e + "30819f300d06092a864886f70d010101050003818d0030818902818100ab9014" + + "dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9859046" + + "7d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26c2f882" + + "3236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6febe1f722" + + "95dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f0203fe" + + "ffff", + }; + + private void checkPrivateCrtKey(RSAPrivateCrtKey key, int expectedKeySize) throws Exception { + BigInteger p = key.getPrimeP(); + BigInteger q = key.getPrimeQ(); + BigInteger n = key.getModulus(); + BigInteger e = key.getPublicExponent(); + BigInteger d = key.getPrivateExponent(); + BigInteger dp = key.getPrimeExponentP(); + BigInteger dq = key.getPrimeExponentQ(); + BigInteger crtCoeff = key.getCrtCoefficient(); + + // Simple test that (n,d,e) is a valid RSA key. + assertEquals(n, p.multiply(q)); + assertEquals(expectedKeySize, n.bitLength()); + int certainty = 80; + assertTrue(p.isProbablePrime(certainty)); + assertTrue(q.isProbablePrime(certainty)); + // Very simple checks for weak random number generators. + RandomUtil.checkPrime(p); + RandomUtil.checkPrime(q); + assertTrue(d.bitLength() > expectedKeySize / 2); + // TODO(bleichen): Keys that are very imbalanced can be broken with elliptic curve factoring. + // Add other checks. E.g. for the size of dp and dq + assertTrue(p.bitLength() > 256); + assertTrue(q.bitLength() > 256); + BigInteger p1 = p.subtract(BigInteger.ONE); + BigInteger q1 = q.subtract(BigInteger.ONE); + BigInteger phi = p1.multiply(q1); + BigInteger order = phi.divide(p1.gcd(q1)); // maximal order of elements + assertEquals(BigInteger.ONE, d.multiply(e).mod(order)); + assertEquals(d.mod(p1), dp.mod(p1)); + assertEquals(d.mod(q1), dq.mod(q1)); + assertEquals(q.multiply(crtCoeff).mod(p), BigInteger.ONE); + } + + private void checkPublicKey(RSAPublicKey pub, RSAPrivateKey priv) { + assertEquals(pub.getModulus(), priv.getModulus()); + BigInteger e = pub.getPublicExponent(); + // Checks that e > 1. [CVE-1999-1444] + assertEquals(e.compareTo(BigInteger.ONE), 1); + } + + private void checkKeyPair(KeyPair keypair, int keySizeInBits) throws Exception { + RSAPublicKey pub = (RSAPublicKey) keypair.getPublic(); + RSAPrivateKey priv = (RSAPrivateKey) keypair.getPrivate(); + if (priv instanceof RSAPrivateCrtKey) { + checkPrivateCrtKey((RSAPrivateCrtKey) priv, keySizeInBits); + } else { + // Using a CRT key leads to 6-7 times better performance than not using the CRT. + // Such a perfomance loss makes a library almost useless. Thus we consider this + // a bug. + fail("Expecting an RSAPrivateCrtKey instead of " + priv.getClass().getName()); + } + checkPublicKey(pub, priv); + } + + public void testKeyGenerationSize(int keySizeInBits) throws Exception { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(keySizeInBits); + KeyPair keypair = keyGen.genKeyPair(); + checkKeyPair(keypair, keySizeInBits); + } + + public void testKeyGeneration() throws Exception { + testKeyGenerationSize(1024); + testKeyGenerationSize(2048); + } + + /** + * Checks whether decoding and again encoding an RSA public key results + * in the same encoding. + * This is a regression test. Failing this test implies that the encoding has changed. + * Such a failure does not need to be a bug, since several encoding for the same key are + * possible. + */ + public void testEncodeDecodePublic() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + byte[] encoded = TestUtil.hexToBytes(ENCODED_PUBLIC_KEY); + X509EncodedKeySpec spec = new X509EncodedKeySpec(encoded); + RSAPublicKey pub = (RSAPublicKey) kf.generatePublic(spec); + assertEquals("The test assumes that the public key is in X.509 format", + "X.509", pub.getFormat()); + assertEquals(ENCODED_PUBLIC_KEY, TestUtil.bytesToHex(pub.getEncoded())); + } + + /** + * Parses a list of modified encodings of an RSA public key. + * Expects that any modification either results in an InvalidKeySpecException + * or an altered PublicKey. + * This test has mostly "defense in depth" characteristic, since applications should + * never accept unauthenticated public keys. + */ + public void testModifiedPublicKeyDecoding() throws Exception { + KeyFactory kf = KeyFactory.getInstance("RSA"); + int cnt = 0; + for (String encoded : MODIFIED_PUBLIC_KEY) { + X509EncodedKeySpec spec = new X509EncodedKeySpec(TestUtil.hexToBytes(encoded)); + try { + RSAPublicKey unusedKey = (RSAPublicKey) kf.generatePublic(spec); + // TODO(bleichen): check the keys that are accepted. + // To decide whether a key should have been rejected or not the test vectors must be + // divided into several categories: + // - keys that use BER encoding: these are OK + // - keys that include additional fields or garbage: might be OK + // - keys where the modification does not change the values: are probably OK + // - keys with missing parameters: should be rejected + // - keys with impossible values (negative n, negative e): should be rejected. + } catch (InvalidKeySpecException ex) { + // expected + } catch (Exception ex) { + System.out.println("generatePublic throws:" + ex.getMessage() + " for " + encoded); + cnt++; + } + } + assertEquals(0, cnt); + } + + // TODO(bleichen): This test is only needed as long as there are open issues. + +} diff --git a/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java b/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java new file mode 100644 index 0000000..3d214fe --- /dev/null +++ b/java/com/google/security/wycheproof/testcases/RsaSignatureTest.java @@ -0,0 +1,1214 @@ +/** + * @license + * Copyright 2016 Google Inc. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.security.wycheproof; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.MessageDigest; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.RSAPublicKeySpec; +import junit.framework.TestCase; + +/** Tests RSA signature schemes. */ +// TODO(bleichen): +// - maybe add tests with invalid keys. +// - So far only PKCS #1 signatures are tested. But RSA-PSS becomes more popular. +// - document stuff +// - Join other RSA tests +public class RsaSignatureTest extends TestCase { + static final RSAPublicKeySpec RSA_KEY1 = + new RSAPublicKeySpec( + new BigInteger( + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f", + 16), + new BigInteger("65537")); + static final String ALGORITHM_KEY1 = "SHA256WithRSA"; + + /** + * Test signatures for RSA_KEY1 and MESSAGE = "Test". The first signature is valid. All other + * signatures are invalid. The signatures were generated by modifying the PKCS #1 padding in + * various ways. I.e. while the generation of the false signature did require the private RSA key, + * failing the test often is a sign that signatures can be forged. Such forgeries are much too + * frequent. The following list is just an incomplete selection of past vulnerabilities: + * <ul> + * <li> CVE-2006-4339: OpenSSL before 0.9.7 was vulnerable to signature forgeries. After the + * hasty patch OpenSSL still accepted at least 2^800 false 2048-bit signatures for each valid one. + * Even though unclear whether this was exploitable it was only fixed around 2014. + * <li> CVE-2006-4340: Mozilla NSS before 3.11.3. + * <li> CVE-2006-4790: GnuTLS before version 1.4.4. + * <li> CVE-2012-2388: StrongSwan + * <li> CVE-2016-1494: Python-RSA before version 3.3 failed to correclty verify RSA signatures. + * <li> BouncyCastle was vulnerable at least until version 1.47. The bug was silently fixed + * around 2012. + * <li> Berserk: http://www.intelsecurity.com/advanced-threat-research/berserk.html + * <li> Truncated comparison of hashes e.g.: http://wiibrew.org/wiki/Signing_bug + * <li> CVE-2016-5547: OpenJDK8 RSA signature's throws an OutOfMemoryError for some invalid + * signatures + * </ul> + */ + static final String[] SIGNATURES_KEY1 = { + // Message:Test + // Digest:sha256 + // Key size:1024 + + // Correct signature + // padding:3031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "68ea71ee1911687eb54b3d19cedcfd44719d0b24accccc59bdafd84e4eba48ef" + + "0be7f115e7073f9f273286a7dcee3b94cdbe208e30ae496987479d3aa12ab0e1" + + "2685ab592d7693a494e6ad27d526ed3ab5912c7f81e09983931794c2165c22fd" + + "859e0f9af1a93a4dfe144098c562731e6059d236b52cb865996c87a9baf7f103", + + // long form encoding of length + // padding:308131300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "52f46d508e31f030b17c537888585f919037562e15f1924543601a41f9b701ee" + + "416ad73d6576b4eaaa64e685289dc478751dfe2d7e588252bfe2d43f4b3a31c6" + + "c6c39a9df884a2fc2e45f09c2150a830974b1c9d26090830b37bf06f1d57be1d" + + "a34ebb016e9db7ce2c34e94872c89567ff6f2ab35a1a9fb6632e100c7d7af834", + // padding:303230810d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "3f34017b3172aaeec72d208308e9b83150699f86634b948847eab56f0169fef5" + + "1b5636a96866f4f0f4c649400489e047803a91f2b2f32ab715065e20770c4e27" + + "88946b85aca5c90efdd6a9458dd9b6f797f96a3de88d2e4896afe147d8c03899" + + "43828100061903a30eaff1dadd98d3e49dba56cdcfa5f215d9c615f974f4a0bc", + // padding:3032300e06810960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "1478337676aa47ca72ea7557facff06f6c777f56063f4487d345e43dc56a6bc5" + + "f8a891085d53a32c9d1c3cf7f469e7f56847b0b1b9b5b784526078271f21d055" + + "0afc40f81e2b8e8dec851d87511cace965edceb83cb96c8d6616e1ee75bb22c5" + + "4412fc942a6f71c9fc609a31a69d34b774a97c1ba4f85cca28d9993db8543f75", + // padding:3032300e06096086480165030402010581000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "77ba423e600bdd761ed10e7c00698a87fe1322f5f42b2902a0be7a24b1cf44f6" + + "13fa55edeb2ded0475f8e1a13e5368f9a2bfc4f2f926ef289a2207bf3689fc1c" + + "8ec3e5463064a7f51bbc993966cc4016319b7c95f282372f1ff848d7fca753a8" + + "1d905b3341b0fbf60ba186e750f3171cfc84288eff8742bda432bd6c8dc04f9f", + // padding:3032300d06096086480165030402010500048120532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "9460ee79bb990bc3fe28cfca92363e6ff6900e3b61b3a402f06024a72b7a65d6" + + "2094b4419e93900995eb121327f72b26b139bab3e5e2bd0c82e0cf6357f3b16f" + + "1c1dd4407a9a820f20e3baaa2259614d9ee3e015e1c1778befa13aff1e545ea1" + + "758cba4713631d63180a91b52df394294441642964a024f45b2251c90e002ec0", + + // length contains leading 0 + // padding:30820031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "96ac043d3cada45aed0dbdc4662dcf7855553a5effa1077048b51c7e9bfff7c2" + + "bb3486ea42894d4b4afb26a3b3bd32cb68d5c4d8ca2622f50d8c56fdc25baf83" + + "b9909ecb096419ddc13578dcc8121007f7204ee82c517ae03de70fa23ef23906" + + "02029a0cbc8a96c5b781d857dbf12802aa561f5f41ea35aa0babb91b9f891762", + // padding:30333082000d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "2a70643572a7cda975d9e2c0827837e60eaa78c297b1ff75b84f654a91fe3329" + + "4ccbeda52676ece50fcc03018151e66c24940bd0574ab85a6599231d587f4a6e" + + "0ae841cb6696e7dcfd182cb75001304e36887bc4fe3b373828f8b0e62ac2300a" + + "626c9e6a2cd05bb7910e74da2978dae1948f855b3b455cd30367160e21581cab", + // padding:3033300f0682000960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "27778e39b45dee1e7003f1d315d3466fc111791187ddc056784c158df92097e1" + + "23021e11918b6df8d905304db732e83d904bc914271b03def4ee129c3fc8adcc" + + "4f81b690e09e70e46c8b920093f304e64ecb7358740e976d28538a9eecf09ec1" + + "e1cd47df9107968207b21538cabe076bcc07c3862c46a793fcf638c70a972885", + // padding:3033300f0609608648016503040201058200000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "3a879e9f883b158908014f3617cae3315d47afdadd30840494f68d91c04dfe81" + + "bd16a40c7d21238cd1816928d989a232a3492325ab0f95d4426e3fb7d58c9908" + + "191dc557d8779dabb282287b7860c30e0796283428e0276447235809882ee990" + + "deb0f4312c01e7ddf0690406eeacb660acc6957bb670904cfd8d04df5e3ebda2", + // padding:3033300d0609608648016503040201050004820020532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "2b82155f363a3b283ae455f59e41c29dec2fbd8c7438b0e347aec5b38c7c895c" + + "b7d326870e4fbdb935fcbb561f223bd926dbe8b95ef5eaab27920dbe30c641e9" + + "9f526a9bc356af54198b459b59383135a82cd5b6edab7da0b1a51d939b2f9951" + + "e1432d637c4f04a3546ed9c890143ae364602b94eabdaa2a45e4bdf0b5bdfa71", + + // wrong length + // padding:3032300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "1dda56dc953aeee7fd76ae7166d92ab9e3d1d9759e76f8f1d7634a73cbf69e39" + + "d8249153d7c2d83c9664db13552f0c78df34b8a67e7b6c10bcc61b5ead7ba62c" + + "e0ec7ba8ac78d146f7e4cadee6f6250e0bc3100660e7afbe3afa17fa288d9754" + + "9b4c8cacc00ac5c942673485739f89c9e5e63ad2be97a8f2313f5c5b095e7542", + // padding:3030300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "692c143b82196a391a3546607336e6f3bc047412645cf0def0d62d1b42234c14" + + "da138bb7f451b45073bbda2aba23412e83bc40d4e7de3e0684f2cad7d059f2d6" + + "831aa3d2ece4964ca75cd41dce23c5ba495c15345b36947b4b5a051fe1b84e14" + + "8b5ae21f112d2245b1acbaeef9dc4a0c408829b9d2b1b5ab1d3a40af0a27b99e", + // padding:3031300e060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "66c31a45b2287425a20f65c3eba9cc58c370882f5fc62921935491fbd516df9b" + + "af9b28304a21d9008b61a92779ecfb3b0c03f6d74354f5159956e3fc1d35bd73" + + "76289378f05d7a71e05ab32794f2566a54635e8dc64740acbe10a293ceddbebe" + + "8499b520f406023a134eb9927ebb788b92488f036d109ec0a40ac52372e847b3", + // padding:3031300c060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "7b85536bdcda4ad3fc40129f2ff9dc85d9ec049913784064e735868664044627" + + "8a2006d93fb33429407597e5d8c783e3f7aee8a7791d69139f3c802a6547f01b" + + "f987415eec2447b0e8c4f3aee7ae2085d141fa34ca6634bc109dede93285d5c4" + + "0cfcd98bd47ceb9cc1890dfff53b7ebb8038533580c7a67fe14c0c422e20cd64", + // padding:3031300d060a60864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "5d77fba3cbb1905d83aa532fcc3227a95d7931bf0c2ab51f8118824de9dc029b" + + "d2470adf48b41c694ec7359d00a1336990c30ee368dd40bd681ba74794415d39" + + "97e7a756659397bf6abd44ca91c12a8580a3f5d1cdbc7f3be0c23c72334ce9b1" + + "419e6540dab73f5ff8ab57d0bbbe92b688bd3495f9344822b622042c2491bc41", + // padding:3031300d060860864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "7b5476fb78f389d1131764e7a13322f86008924c8c098f6d74f2df4dcc5a504c" + + "d786b3eaae33295cd1e87a2bbd1a06cb385674d465110a9a990d52de9a67f1c1" + + "3ecaaa86383d489423c084fae9ecd2e9b109f4f04b8c013e3409128f3a079c06" + + "8c1ad27bc2a20e76ad149325b7b0f0bd804a4e33949a98aac49076260702b0b0", + // padding:3031300d060960864801650304020105010420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "6034e1253e4860a29096e392076794cfcea166a30b340cc09f77baa5952c06d1" + + "48bd89b750c3112930ef210a50a7d3f6569da89912b5e50e824116e73a155369" + + "58f75779506d07e67ec9c0cd8de4b51dfbb0fe56926feed18ffbd83b0cdd50d5" + + "6326c54adf97e629378ae5f0f02fcda3da1aa98cb1d1990946edec711a85a0d8", + // padding:3031300d060960864801650304020105000421532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "a44cd265e1ecea83fc74e9eef746ef173277cc96f69a1798590ddee7ce5b5c34" + + "a82ad58a5c042db19005e04eec4159900ea764c0d008c52b94577d1c438661fb" + + "767902d9d1bbd6a90bdc4df685ec5951eac81d8b4dd36bceef7b6f919e85b6c9" + + "94c7cf22a804f15cebe63b77f47b3bc2c2aaa68c6362c27a574b849efafe72e9", + // padding:3031300d06096086480165030402010500041f532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "a160aa43f4873cada34bea5ccd2be9dce07940ee1c08eaad524a5019993bc753" + + "ce92cccada706b483f106ff20b327b35e7c83955ad3bbff3f26ced3489877d1b" + + "5bf285d61afcb30219c02a440da61030e301aadb901a525345d1a651a21c31a6" + + "2ac9fb71738c3e215a8941ca9a3c4910679c5e774530c28788f6eddd7a31c024", + + // uint32 overflow in length + // padding:30850100000031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20 + // a6ec113d682299550d7a6e0f345e25 + "1369c78f816a9baf027e255de0c258125be90f35b8daafee87f2ffef2d465e06" + + "94af4401cc5cdc7ca78b08d5688ceefbddc02abc5495d47c6829d696f8370ea4" + + "27e7e0225eaf22cda720bbb5881edd16b19bbf2ca86654c65b4ad481c13fb38a" + + "f00d77922f46b311f936c51f4610f6bdb514b366aa05f029c1e63e3cfcf9763d", + // padding:30363085010000000d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20 + // a6ec113d682299550d7a6e0f345e25 + "41d4c1ea43cb207af8bfc1552e31da7ca5744b68c4e00c3bf55f4edd4c81e91c" + + "01f44fa05290dbaa1fdcdcc775f6032a049b4965345c16aac6994b06cda9e038" + + "7dbff96cdb115e014f69bb057faca2f618c70a31edd0beaef7acdcc0fb7c83b2" + + "f07a8b9de48aa04b7c973920af5b8dc20aac343251ddf4c2277985c3db1dac2f", + // padding:303630120685010000000960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20 + // a6ec113d682299550d7a6e0f345e25 + "76bae6c330b9ab33aa9f2abe8559c51fb95f953a75e48053ab99078069214b50" + + "9dd1b5080ac6819e32912619372d71a9ff1a67449dd699e5bc6ec0e18d1893df" + + "b5bd571d933926d05b0d9fd7036ba4556e209369d1c57ec49cd9075e583c257c" + + "6fd4899c2a8bbb157547812cc692f264bf54712c71ee090b974d99b4d1629696", + // padding:303630120609608648016503040201058501000000000420532eaabd9574880dbf76b9b8cc00832c20 + // a6ec113d682299550d7a6e0f345e25 + "3480a5c22f092f259b5bc4fdb9a33c044c24a645b57d61920effde1dc0bbfe53" + + "738023f16025841f9323b40f72c11091941bbdfaf7c2fbf77ad6626dbd6a3b7a" + + "bb3ee916d96a922b11c86ce80ee67dec619bb98e9246d35a33b11b3a4e2a3a13" + + "0e8b57ed4bcdd4b4e73aec3f9e3d50d3db5e29cffeb186846c72d09468d018ed", + // padding:3036300d0609608648016503040201050004850100000020532eaabd9574880dbf76b9b8cc00832c20 + // a6ec113d682299550d7a6e0f345e25 + "5b3d3a198d4b36c6d9641db181fff59407a25bf1571f85e47bad1eaf13807987" + + "2b93b9eb51aae09b48d6f4ef56badd96a6584277d8f3c6e4a4e11275f72021b5" + + "0a1665ddaaa56a2a7caa7da6b4d502c5214e17042811154d411dd2197c250264" + + "bb69ba43adf668d4f7b81d932afa55e378214bb19ddeb431f702a91dd11e23bb", + + // uint64 overflow in length + // padding:3089010000000000000031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc + // 00832c20a6ec113d682299550d7a6e0f345e25 + "1cc5577d04e34550e7f3d136064547efa30b9413e2c423b5a320eaaaf11cbebb" + + "91e13bbe3874e4650e057a8e38c8a366c473f35e0de82b22f846721a09e3f279" + + "ebdf54c8df395a9041333f09cb7bed5291bc1842857c4ce6ad5a1c2c476c1efd" + + "dd5fe42824c25e0581aa7bb8f621d3b53566637c6266bb1bd0a5b7fb79c72616", + // padding:303a308901000000000000000d060960864801650304020105000420532eaabd9574880dbf76b9b8cc + // 00832c20a6ec113d682299550d7a6e0f345e25 + "6e56d1746105344b34fb8299d173f4a5032cbce3556ca9d1eee35f8b31818efc" + + "121a1a9599c24fef8531243016dd6288d67b4bf9fdbf2c90fba5b1661be03531" + + "b5e15385ea465d1376010f0af761e8fb1afff7823dcef8dc100d97c192e9a7d0" + + "3c82321d83fd8ecf67207c65cf182e1104ec5669536070cf1e3fe73c5e27edeb", + // padding:303a3016068901000000000000000960864801650304020105000420532eaabd9574880dbf76b9b8cc + // 00832c20a6ec113d682299550d7a6e0f345e25 + "37a413f9202591b8860cd9d68515ab522ae800e9a71793b479f1fb74ab8c9b07" + + "e72fe82dabe1189d028b813610e5e57c055af2d32837551fdb0cd93d7669a3c0" + + "2a14c460f4c92136a4d11cfb7dcc76401bb5b699fbc64d302736d68c3591ecd5" + + "9220107cd63f55c83edd38c4568e6f7749c0d9baebfb7c8ae1bf2179101745a9", + // padding:303a3016060960864801650304020105890100000000000000000420532eaabd9574880dbf76b9b8cc + // 00832c20a6ec113d682299550d7a6e0f345e25 + "9fa8aac224bb50697103d457e7fc870853b23670ee5b8c7395d68ed82b30db18" + + "ae34a569abdcdf19238ffca8f5e435327dbe605bdc1a6dd3eaa3c2beb33f0064" + + "2984a2034bf3b3e8de3ec7009e35069d5b27253c4aadcb4f163148e157252e3b" + + "9334abb6cf0299161c12908529f52de9416ec6218af7a6963fcc987c5024ea71", + // padding:303a300d060960864801650304020105000489010000000000000020532eaabd9574880dbf76b9b8cc + // 00832c20a6ec113d682299550d7a6e0f345e25 + "0f50bc6b1b94aeb6805dee51c92860693de47c4925ab90b57a46e0485a9afeed" + + "45083eade73bee684cd07048e632d1dd24aa2efc42c1f85e4fd7b7058dbeafb5" + + "3a3d5b1cb1e7dded3352c3c92ded891839263a501afaa78fedfd04546c43d16f" + + "7a52b800abc9ab1ef827ae0eb19d9b52def2435f1477a48dff61800b4db830e4", + + // length = 2**31 - 1 + // padding:30847fffffff300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "9dcc651cc0a1b4d406112c0d1ebd7a9fb5a2c9d9f9cffbeab2d2821e5ed01efa" + + "9d191665794649bd1f588b729e8fba1eaa37a5a736a5863973c338a92b2665d6" + + "ead13b72a19d2da778febb94b150e8d750340a3b856fca8b3b6e3cbfecb9c397" + + "c23f46912ba546ab0f64ed88404ce317f8fb2278b68950e9712d6b11f5cdfcaa", + // padding:303530847fffffff060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "0397d14205c2f52423ef69c874294dc2b37d5be5d5647f7e83f1dd6783cb41cc" + + "e52e6de1dc8c9e93ca1ef887d4c0ea79cd8b26391d638bbd8080bce830bf1bd7" + + "fb1de31346f28d609874fafd4a34fb7bee900441f55589ec3c5e190106d8816c" + + "adfcfb445834739cafaaa3903ed93cedc41a76aa0ce18fb49a3a73b7b5928735", + // padding:3035301106847fffffff60864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "2c3ffd881c1c0ce2e4c98282d6011179a89b1e84b17072bcbbb64164e5e05410" + + "d0414a1fdbbc04564f3d80f3891f28c3f02e92bf97b4339b5bd4699614e236d4" + + "223cef0688c44b297eb9c0e22246b4cb28983b102a446dc76671206c3b77af68" + + "97f2f445512abda37bc9c37257dd4f1c6f0e6ec40929eb6b0058682b9d2f6c66", + // padding:30353011060960864801650304020105847fffffff0420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "668bd06eafe953fca6a17b0da0f9006ceadb09ad904786b7530148df7eedc146" + + "d20a5472c39677d65e59934c00227fb662b3474596e6072f56d2c00c3d31e66f" + + "0da85f4670e75c3f2c910c0fec8c98bc31fb2eceff80350b78aec0d316e9bbb3" + + "31544d8a3d0b1649291396c717e350bebba3d3c3a0b1d55f010879b8c7b7d4f9", + // padding:3035300d0609608648016503040201050004847fffffff532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "87482257ae1d18d0357428b756ae35a48549536a3439ca3c148eee64f4c096d8" + + "96219097d55c14a25eb1490779f6b1471aed238cc0d6aaf265c12ac086d04de9" + + "b79a37518056dfacc12cb4916c17505fc7e2e6c1e0db720a286ea65bde4d3da1" + + "d2dcb8d0276e8ce73f3f923209149955285c602572cfd24c82e8d96d45f569e6", + + // length = 2**32 - 1 + // padding:3084ffffffff300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "03aadd447f36952dfe73ae89e5c656b7d37ec92535e547cca62a7747f3831f2f" + + "613c7dc094f3d5c4c6b9e02b21ed4626930ef3948b42ed41f4cf468d2474acad" + + "f1c75599c5619e4872e6d3dfd93abe92234165135ed265e0c0f64fddf23e50c1" + + "f9fdcede8778a8ca008ab00f8afa887da3f4699df9f1140953232f36d035b03f", + // padding:30353084ffffffff060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "31afd9a0d827755352b16de04de42e98a8c72f08919ed475530a00c762b8a03b" + + "de22634dd856a7eede4b4947d780cb3efe55775e16d7f46f209dbcb5569b2d94" + + "69cc271aa850f74960f7c741928055925349821e32e1e0fe5a040010a39a4b6a" + + "343f7f35c204106b3617e528a99dcaea8a93766adcfe7be31cdb98f7f7f14669", + // padding:303530110684ffffffff60864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "16ac0aa2d727ef5fbf0305259ee6fa40827c92419f819673fd64cc2dc2dbfe7c" + + "e1cfcf06e26d45f59cb3d9afd30d7a6265863fe856e0a0b1b9508b1e7a2dfb0f" + + "87f5ebfc444bbdae504abde7daa33bffb991551940df682c8e2c45edef0563b3" + + "4d4f11e1955e83c2145ee321165517d1532abd64dc613a280fc30670bba1f898", + // padding:3035301106096086480165030402010584ffffffff0420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "0fe0c75dae62462e66e7277b03c9113727419f7d4db7b2a567c0c189fb6328e1" + + "f73d5d44e2196b436f4c2f0f12950d419774c8a51c55f9b2217f904c4f03d5f5" + + "754174719dfb85f62795ef75e6d54e703bf231fd8472250f529f85294f29f6c5" + + "653ef585079c3b3d8f931da80a46c8afeef37696fb0e7986d413bb1996b8ad57", + // padding:3035300d060960864801650304020105000484ffffffff532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "9ef993e6ccf015b0b0de75b51213a1c3efcaf66bf83655287484ef28d9848062" + + "26a7af1704fa6a7fc02984b44449f83ae24761021e49ba6117505c1e609406b0" + + "02215de27d696643c3354fb48e6c64e7300944edaeb96e4872275f75532f5aab" + + "94358d4954522fc7903439e99223d8124e79a3f519050b6b576b77d5abe7c3e3", + + // length = 2**64 - 1 + // padding:3088ffffffffffffffff300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "97c602416f2131d34f2a57acecf26365a30c12f77e5beac095533848ce227302" + + "092c6f44b47f011d6eb0a91f8024d1935d8bb274c42b57875115a94281fd3cb1" + + "98f9334758d3200c1c721f6babef332c02a89968a7089f7783993bdd54f809f8" + + "372437798d2364040c1faabfb00faabf28cd6ae4ffea29ae2c08a6a7e6074700", + // padding:30393088ffffffffffffffff060960864801650304020105000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "2a970dc291a1dc935cca6985dda703bcc1ece2e40817ce8fa79b6e8fe84e1136" + + "86e6e65570d46bf22147bcbc389cb5f86f92dc185f556d15e7614cef119fcd73" + + "05a31fd2f8710812f35f9f0bd8a1a6e5be3163de644370c67181b7575635dfb9" + + "f717f78631d62db714b2a19cea7079ff13c8926ae0c601e4befb6541b02a7e20", + // padding:303930150688ffffffffffffffff60864801650304020105000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "6e16d110235cd11e32b114ca9dac0cd6a1b041a6d2c61941d49bb458241281f6" + + "2a4e2b1bf3cebc3e67e8c062ec67a51a599a553b09732e23e1d09fb2b20be7fd" + + "311a7122414d535651718a1421d4239276c227b96506729a09e3ff2779dd1c79" + + "de4d402623039b826e2bb4d26d1b56775fce14ed0203a9ebd8f042d981705a77", + // padding:3039301506096086480165030402010588ffffffffffffffff0420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "0716d252488e08f10a25cec94714e6105bd4e13ff019431190864cb0f4378d31" + + "5f4bd0fdf186e1f2d45a6e97eb04fb2013273e178ce4f82a0b67bf9d021b1d8a" + + "b73d753adf2073ee1ad6190b2163139db63778a3670b7cce23f45efb601bd596" + + "44a431cbe534ecdf4c4c58ed02ed03863ee32d296b5736c010305fec655b1a44", + // padding:3039300d060960864801650304020105000488ffffffffffffffff532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "03e52a2ed638bfb9184a0ee3698502af3a19bb959a984957de5101e6f7a62ccc" + + "c2ec2a6293fa9d76fabf3ce7e4bf35c65a5f864bc003686a1e05b57c5af6ad58" + + "8e05a5225479422d7b78c5bedddaec7f4b8c1e9ab7478c1ee253847324e02543" + + "4b76a01b82a40123ab31ec9862c6016885dc6cbfe97801503369fd3688bdaaf8", + + // removing sequence + // padding: + "5df1c4a701c6fc1f2daf6f4538f29c3452667424c05edcbdaba4a1678c8b5bc0" + + "e89656a0e48aef46642e0bb597813688904e9d74cbd377a3d9d2c965bd3ed06f" + + "136f10367ea3eecf89a97508389448a31ae0e79ed3725d0c4e99a516daa41164" + + "79bc53da5d7c2f26c7ec6310d4cb4174bb781405630a9b1c147b0e1da3a7faf9", + // padding:30220420532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 + "3e43837b92ebe4df08586fced3dce46aeb2fdb6ec2bd0c58e823f6e6363b9b67" + + "6786929d13ede60a8d8d0daaf71f0de8880ed0fdac8706eb2f324394145818b6" + + "41d1049cc7552bc6273d86e901099c78297381faec5c518fb6de429700f3bbfe" + + "f76cdecbb60088b9f2a77d75b8ff86f06cf23850e3183a267c0ea34f4f839015", + + // appending 0's to sequence + // padding:3033300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e250000 + "26d20fecdcf0b7d6a0472754aecbe115c39d580ce9d78b67d1a6395aa6ce6689" + + "bf6d0d96545341fbf04956a48c47f7d30bda017acb1d8e24ce596aacd3e05b1a" + + "fa571d19f5316142557f765e4c5d080bc5336b79e2c02d8833d076ac9d7794ff" + + "be85c66d0db97e1f5bd2ecb46afb15c19a8fe083fa593420e996a483c2a3a766", + // padding:3033300f0609608648016503040201050000000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "1163082ba8d48352df7eab96a0067539faff24374a630aa4393461a0aac71660" + + "6625d706699dfc22cf3aff89fcc278f83a0adac87aa0bf192dd86a97031515de" + + "1933a23849478ebed20e4203abfb47345bc18f38da5d45e829997b10107c5369" + + "99b2ce10b2781e1db03e10cc2bdbc2e0ff4c3db5d271ce83c1e7e267e7c1e107", + + // prepending 0's to sequence + // padding:30330000300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "0ded592bef1fa809841e0d7365e66af12f4239be0928656e7c49a043b9f2b18b" + + "9bd2dfe93a810c6e6c8ae6cb8a5c9d6e9d39a96a10b3bbdb92a7b8f575c2db48" + + "41c1b628160f956f54e0c58d3b6fd4d640b0a06d39476daba7be04b63a75f38b" + + "bf7517d9751d2b12d2dc00e44de7263275dce6b0c0af65d3c04878d6fc1be2ac", + // padding:3033300f0000060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "95a42e5d9bd9ad5a8579444e8167bdecec16116a7900117b298c82d5560f1d16" + + "e9fbe963764727fef9111f2465e66177b576bdb8c70a58e3df6ff69edd2d6827" + + "c97d626b09c24cc49f223cd5d2db2916c54fd8f2ac7301723449b1823f2ff48c" + + "56849f7d608312d4bb7a97f90ba218f99cb773fba0a34909618f5d25854d7687", + + // appending unused 0's + // padding:3031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e250000 + "2344c598a8905b350f20de5cf0cee60253729a54be45b0b19acc109ac15862ef" + + "ab2e7c96e92bc990ed6959a40d725c24c25c8d223a46f490905c1448d8dbf7c9" + + "c427bc2e896bdce6d2c1daabdc93ce177f9525ac69d899bded12443338834a16" + + "d885456057461740c5140cb9a89a017851f9e99e38c1727fe5ccad9a7a8709d6", + // padding:3033300d0609608648016503040201050000000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "a08cbe4009080f73cef03116ea949d1dbacce7025f7f61040fb4e052754d5b2d" + + "74c2dd06c0dfe1d09b97aa5739c809bec6d8cb27e852e9fef353bfa32964b994" + + "95a6dc63d6ce77460ac280c74c0cabdef794f74930f7f8827af1c6690d22ec2d" + + "f3af497837bbe900a890e3feeaca2c0d16b0017155390ff0396a35ecb62b5992", + // padding:3033300f0609608648016503040201000005000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "500df36bd7d0b56642e2d5dab6e4ec0b148e7b8673cfab40e45c5dad5efc469b" + + "3321ce027a3a7ff5689366a18a32267d161a1266491b055f11557c35bd0d4f43" + + "df11b8a26f7b13c54be423b87b30b1dca956151c3ec3df03b30918a413179b0e" + + "064bf434736b323408e3f1330743c8bdbbb9d466dc1e21710c12e2e3b638b172", + + // appending null value + // padding:3033300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e250500 + "11a382fe570e0cfeb515955b70ec89a9353cda0c5a5d3cfa3e16e41340eccaa1" + + "8ba21ad87c4a54a7131c4a7cf9afed68b1c1645568bab9b0fe7dfe0437abbe1f" + + "b6cf06bb690f46aa2eca034093ded661c38954341f3f35abe484015150307eca" + + "fd06d4309836771dfe29bfe56350d68725e0cd02b1479c6f99eeba2d59f40626", + // padding:3033300f0609608648016503040201050005000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "110f3f188df46da58cdd46b5d460ba3d2f8d00d907289634d52a3ce693eb232c" + + "d6db738c48c8aa22d923d4f81d55925b3d4ff29ad9869f97a244d37b860cbd46" + + "46c6318c041729a7aaf473b61a93cccd62fe223d1be00364f03d722f43c7beff" + + "98c3fde573e7e6a0ce7d4a2a4bcf279765e29769bd4f884ce41fb808ac3d541a", + // padding:3033300f060b608648016503040201050005000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "470416ee76f0bbdbd2812b533813e4463b799f4036e6955f3e174f6287e3c73d" + + "57c32875607e2eaf06d612cc85170ba5df31286edb645ae9ceb9e62064050f3e" + + "7f6b36fe8fdae7a3bd89b6acc523c923b9d3f3e5f57d80c9100b39dde75caf46" + + "adcae56668149ce0b80762bc459ac598241dd79c6b4fe0220ad53e3c591243fe", + // padding:3033300f0609608648016503040201050205000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "100714ee0d38c541c2632e96885a7ce0afcb22f0cbd84c556f19d1b44bce75a8" + + "fdf141e975dda1812b4465050d4615a51c3b9816606c7ac88d6b684df938e7a8" + + "852835dcf5bf0ee45f2e413290691832095af77eef0e7a86f72167dbb03758e6" + + "8561f7f06afc6e902ba19fad57e00cb43c0fb2a5ead689a146c79c9e6188bd85", + // padding:3033300d060960864801650304020105000422532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e250500 + "44eaf5ded57ac5c25c17eb31c2e071400b46b9022641347b2edb0b14efbd4eac" + + "5f71e4bfbe791e164c003667387e57ae22c6b00e69971d7245e381f6459e5f88" + + "d9dc0fdb385b777fe99e5e4d79aec057e41a1e457fe2b91a5f4a8878d2eaa1c3" + + "ad8393d281eca07ebd287364a19045029fa7ed0e62a21e5e42a88a52ea4abc8b", + + // including garbage + // padding:303549803031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "236a815c2441d111d254172149ab2429cc4e6caf3335579bf438f22723de0a4a" + + "5e532ed71f24c0fc6032c60aebb2b7e76cd0d14f262d1d9bba80a53dbdb12c9b" + + "89902fc5f5511125d21b7df32e9b303c4b393fd6add6ac7536901ea8ae5785dc" + + "fe90e85ad0c16146b1f15036c31d7758a364fb54cc1d183b8566bda592ba446c", + // padding:303525003031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "762d30b302cd76b021e237f28017e48488ff3bb30ff9e92db5b1e76eec2ee91c" + + "9af03e1c5038afc22591b1cd8cfae648a33ab77901f9f3736e50eea83f7c7a45" + + "46dc55c0265fb17dfdd30250fa3881e34e51b4f2e54554ad098eee952ec888e9" + + "11a0ea5df42c0560bcb4bdd718c88d834b534917e555c38fd1ec3593b2f25b39", + // padding:30333031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e250004deadbeef + "8cbf9d425abef67ff0a7fb648e70b82b1556ac80e46dcff37145b9041bee2bbb" + + "fa56817e04994c9cf1123c6df2aeeb1637595eb1e20adef51d657943fd67826a" + + "c5d5dfba106ae9cd243f12746917a446ce955034b46ceb0f4d542b7bcd06ad3e" + + "6e10899d5338e6d8caf3d4de3cbf45d45a58d946a64d0bc13e97a4ab4e6b6016", + // padding:303530114980300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "6477bd3337d601fe92e19e7f6b216f73eaca68aa408c5a570876ad8db6113505" + + "43d1dd458b511e3095e57996ca589c00f2beb6b6fe4564f4373571d904958acd" + + "1bcd33f57959a231bb126bb2b37bf1403d52836752198b6954567f07b31ed110" + + "5dcc50004e4cd7e897516c536c205b339ff0d35463ca6871ea5dce7a8daed8d7", + // padding:303530112500300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "975d07b7295268a8662aedbd2b65b5eb10bb496077f41b90d12d34ebc7e492f0" + + "c7f3a41d4164a279f06ea616f91968628be4ceecd4a554477bc76cc6b2e6bda4" + + "042dc253327c4b8fc40e9242cbc8b835114a7379a3081bae4b2803a99deb4a54" + + "0f8c149ca5db3a61c7bc9f61cd7e55521660a06603849896c791a18d1c7360e1", + // padding:3039300f300d060960864801650304020105000004deadbeef0420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "37352cd11eb5ff7380bfb7c0d3e8d9979ae7cb489a71c31a077d59496547b0c9" + + "5a760387ed50eefde0b762222f05a6033740f6e010693edf3ef8ab5f9c57f4eb" + + "1f6ccd83287dcc2e90857defe5ba4109bf79ad84ab069c85a25758d22536c688" + + "2919245fa2d7e7921b3635d984deeb6555cabdfc46a42c75875d55924c8bac62", + // padding:30353011260d4980060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "0c783603c7af53df27538b983fb7368e9f62d4552f008f2920a21cff3186d2ac" + + "7de451fe8c28b71d38c657c41c79174c84004deffc69e69cebf2aba2a43ccbf0" + + "52f6fbdc3c9d3683275913c4583dced686291bd1c0217a015d9ce732eb410c8b" + + "27f2fa7c9ff516a81577490f5bffc8121c7ac674caa464956942786c5dca6b4d", + // padding:30353011260d2500060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "1fb1960934683292a4c92cf3d582cd5fe68888a5b0f6c2e64538289da7f96a9e" + + "fcc36bdbf1fdc0cc0b3b36c6af608309de58c6151112f3a78599ade4a718b359" + + "547a4cac9a020e5e7e7117d1bfeb3ec21bfe9732825e624b27ddf8a946eb858b" + + "30461706f769a54b0478e0753388951d98129383590186b80836608f7e06c72f", + // padding:30393015260b06096086480165030402010004deadbeef05000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "7e4f953b288c20fd5bec56a00745db9be03590efcb637e2ce2119a0a1846e9f3" + + "8c0ebc5f2498ebde6217d81c9939b6d6a6f35ba54ee50d6313d3f2579751e7ae" + + "8d31ef4b0e99ca2e96c80459a7e5ff51f6f31e9c965be19097de13017c90037a" + + "a482d197c986f50bf2d5e1acb3f3024605e46d963410a4a623c898d0d773a78e", + // padding:3035301106096086480165030402012504498005000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "03e121f5766771a65a400b354f78ca27c9a04a25d4ab80fcd6ee91bbca3baf27" + + "752abe5cfb7959779644c064bdbaede14847fc035a3a19523d83cae3c31a64ef" + + "7538805e398e196ed8ee9ef6b3f58f10e7e16c95495f82ba430e5d997d165564" + + "44bb1447ebb17829ab879e61ac297ebfd4b94aa99b68b0b498d8e434d4fb3c6b", + // padding:3035301106096086480165030402012504250005000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "90a5d10e2e19f7e016d5126a3d3eb91432611ebfd411b07a4be15aa48c39df33" + + "f3a2855f1e150ad34c7f83973bd73eca6575dcbac4086aa0a38db3d6e6ee2e9f" + + "419768493fb4829f1f6d67f80359f82d95483d6057de17fd388ae46687c429de" + + "a4d9f7a286c95fb1b9df0f1ba40a4263307789952b1bd07cdcb3b5cef10d9d2e", + // padding:303930150609608648016503040201250205000004deadbeef0420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "a88d38e8c765b7e439f42294e71c1689a318ed5414efdf474196989829d4989f" + + "ce8910798f4d7873fb43d3a501fa15c8019813104e4699597246db66f96c838e" + + "45aa3596a1d26cbe9f6ee91c077422953b402f7e11f8768a2f132295bff79a0d" + + "10ab843cbcf2c921113992336638f4052446f52815328ba4946510a6b701d448", + // padding:3035300d06096086480165030402010500242449800420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "34508ce63c502b3f8185f7cc61c724185aab2c1bac68cf2a7e7f4234edcc0e38" + + "cd15f73e73d02431c62c28a2241f629382ac5e9329ab71dd7e9152b10bf86b55" + + "0c855aade6a5941ffacafb4bfd57066bd6e39bd0d8ecf57ad9a6f3ba48831800" + + "bd8e6e9773a0ba3770cfb9ae329bb4451f450ee35796b5578104b7ff5ae2dc31", + // padding:3035300d06096086480165030402010500242425000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "7f642b5702c331dd76b7ff66578a2c0547d91c556b7b9751443d911729fb5ce8" + + "426515ba068e2839cfdc956eb813c25d65a2d5213b59302c0ed5e6fb95c49002" + + "edb1605f8f622912fdc309d92e6e3f188ba19e991fab0a7018ae4f6e70927d91" + + "cffec51b2dcc8113908faa1173ec9ed72350aa93a8cadef8bfa7305bae22bdf9", + // padding:3039300d0609608648016503040201050024220420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e250004deadbeef + "0abb75f2fac084da0b99bc823c021c4872e23302a6a25e400b6f25d60f7c9038" + + "99a69dc548676106b44f37c1e6d2604eb995a16880a2a8e2cc9e0ccb2b984ae4" + + "82036f69a6ad31a2b5836e73e0d30c3e10f8b93c7587d7c0f2371183edc3b8cd" + + "0fd7bc325b1cf75e1079f8d6df53fe495722cc1ce707cca49bc6f4ed2ca6c4f9", + + // including undefined tags + // padding:3039aa00bb00cd003031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "9f2234b108a45abaed850e19d2f9576f59bb83dbc6165da61c4798638f9c9858" + + "7c7eb92a8c901dc4430e4a47dc05681ae811ffcad6f7a604c43551cd0f5d1235" + + "49435d622f7efec578301efd49dc6b139abbc3c7d6a26858f6d18f09b863a145" + + "d6483c9efc6c322fec1341b6362dc1d752c714efcdfb09097a0ce6df7dbe88a9", + // padding:3037aa02aabb3031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c + // 20a6ec113d682299550d7a6e0f345e25 + "24ba137a293599ab7e50a0a4f8c7a5cd02dda6a4568c93f84d00ff4729656456" + + "3c9051b334db2fd2c081b23d322d4870a61b2435d651d7efb4e1b0920e759f7f" + + "d81a937bbc85ff43dbe2b702dec3acf4db68d5fd7b8a2f6d32cc49a7300dd659" + + "623b391927a2442d69c6c3c29e59eb80b1d0a95bec6d18a6223cf4357eb7cc96", + // padding:30393015aa00bb00cd00300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "04023dd35fa479f8156794d02935f8669c023c774b95c5a0e02837e32ccaf7a4" + + "ba5195835a15de6a21796eb96bdaed868f9e8b7f0a5a21c1a3058f53aadb62d6" + + "ee74cd70b2c38f17e42a1f7ffd88955731b4e15368211ad53f617aacbb54a7e7" + + "078740ba6daaca81c1b321b748ea1d13f7aece490226636ecac41bdc275175d6", + // padding:30373013aa02aabb300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c + // 20a6ec113d682299550d7a6e0f345e25 + "253bed76e4b8465ebfffd1b7214ce586294d3bea290517ca2bfc417ba9d8e72d" + + "286570c348dc6084fd379c2bf4dae424189964639533e17c409ae18e445210ed" + + "4dc98de4ad7336554740d1532d5010a1bd7ebbc33ba48a3365d50669e4f4522d" + + "0e5ff7a3bdb1c42c42dee647a8a3ce16633eb33bbc0a869e12cf99f9481dcf85", + // padding:303930152611aa00bb00cd00060960864801650304020105000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "0775598491297eb9004eed66234ded82e047ea2f06837425e6bd27f33b137366" + + "7f3ff4961d60f85edede88ec2bba2680151da3763f0df9785b31771da7e64386" + + "2ff9ba944ab54bb1356ee113e420002a873f1eb381660f3eb84b1d6b25ccb8b8" + + "2ad12ad0a449c4de205144873329e80ae8a84d1d3c1660b3303cbef28b48a553", + // padding:30373013260faa02aabb060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c + // 20a6ec113d682299550d7a6e0f345e25 + "a73df043d06ae53a37773016a4e21d3f1093c50e079b189c4bd7db3e2e9875b1" + + "4e5374cb8e7394a9f1b45c7e4e9dd516198bf5055b30ea4d205f39fddaab3da0" + + "cec63524bdae2ae166a3874c59057d93855d6e6314fc5da8111ff58666a73c00" + + "a105311859f27d2fb92f507531b9d681e219861e4f0b2b979c185af2690eb4f7", + // padding:3039301506096086480165030402012508aa00bb00cd0005000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "17e5a889b8139593e192f7af684c918f2751f157214863f88984ff3d8c9e381d" + + "1bee5ee788fc82869f4c3d8483e3c17c873a850a7a5c85e4518cbd8531b331a3" + + "08a0368a868bb7995ce0f8a7ac5ba53b88c31c958dfabb36ed461472505b5984" + + "18185b864f381342c29dc80e55ca7c2095e7788e7e8d385d61de605f74e431b9", + // padding:3037301306096086480165030402012506aa02aabb05000420532eaabd9574880dbf76b9b8cc00832c + // 20a6ec113d682299550d7a6e0f345e25 + "a659f7c44e4589e9f6658b0b57e82e65d5ee9fbe2376894f558a7ca4b6e3c503" + + "2f953d1dccfb9b76bbc53dd5d1a52cfc092c6ca279b37c0a43c99ec0553d7ef4" + + "d9bf9361a1c4a3fb7496aa58c0af518312e18819fffdafd1a230a38440a6fbb0" + + "e69babaa977b8b5fe08ed7c6d59c0391ccd80b42a0c0102264b0ed6af8524e9e", + // padding:3039300d060960864801650304020105002428aa00bb00cd000420532eaabd9574880dbf76b9b8cc00 + // 832c20a6ec113d682299550d7a6e0f345e25 + "83fd4599a47bc0852ee1a12b2d97fceae6d8442fd089df1d21ecc252a4109824" + + "10bbd2cc6bbca219502c2934ac593a09beefdeb54b0692b3e5724b79b0f5c535" + + "41b62b0c4bf80a658af71d5964fc6a1fd7823370d00e24dcead4bdc86bcd883f" + + "e3f48dc7f8468ce99b7580306007021b68b48ace274e3c09a1b5e21fc7542ef0", + // padding:3037300d060960864801650304020105002426aa02aabb0420532eaabd9574880dbf76b9b8cc00832c + // 20a6ec113d682299550d7a6e0f345e25 + "4bab6fc6948143f8ec7c8ad86a0c5cda5bd8151c24ca7916857778729c882581" + + "603363fde0ae2a28b6f8f2c8ce8d5f6b6e731bf8ef735bd31318069544295b54" + + "b04ff2abd1e11900373931164586d7c830bae704f7314eebf1d32b3a171274ed" + + "456e335d2a0b998ac441053ef096a037bfa6e5cdf3835c45ede383f0ee8feeec", + + // changing tag value + // padding:2e31300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "5770bbbb883f93f7c29bdab32e496f2e9063110fe648705fd0b1dc927052fc9a" + + "ce9b36d898d19cd4f862b777b7c790d767b8313f735ff567c34cfb31f2964454" + + "0645beea182cabdf789ff9ac3f68cc20444af0b9d4ec0bc8992945063fdb733c" + + "ccef7590a10bdf491bc21c38f25ff65a581b40343e30529c3dbb71f62189ba3f", + // padding:3231300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "359dfbf40d3c2383f58bef1d518abe9852ca80d797393e4e1a9380ef08aa851d" + + "585213e8897c6f701ab680b0f63ccf5ea4216331918ca9a984fb6ba549f4bd06" + + "6ec1fc4f1ed053fa5658b01df674a21322ba7e21fba6cbb3a8eb5565fb7bc269" + + "f99c65981efa650dde613ccd6d3927cdae45922d94dcf7ca5188bf5acf84035f", + // padding:ff31300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "24a61067121e9b4363b816b7c5750584c23f3c3200ca929fdedbe95d7504c56e" + + "a7dffd762074e44e96e22147943f2b704003967270b2be1bd1baadc3861c4cae" + + "91bd41530c67220349db4481d324d9927d52fe85618ddab2598996c5813f3299" + + "e1afb020b24003fa94f94a0c6c02b3183295e0de79eda021dccc5539cd7874ce", + // padding:30312e0d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "11b8d1dc2fa2afbc32f048d7454ba032b432a2ecd438506aa72c697a5c118e9e" + + "231a0c6b6340b5564402b7e837c59dd36f726fd626621b8f543964198484087e" + + "ded70e7bb1dd63df2cea33198b9d02dd28e3b8bd006ba991a8b3bf06ac928bef" + + "45cba2362f2e11a5fbfb0310e84e8b7ba1e17c315adc1f34519134c36689619d", + // padding:3031320d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "8748f029d5294dc917cf4fb347e0046f903c088fd976ca97b1322738549df7c5" + + "6cd67349d66596338fe418b29de9e8af8872fcdbb55e1a6f74e9965fe7a365b8" + + "46b667d0ae50df23083be73cceb59db545a3e1a560f6ce0e9eaee57b5f95b848" + + "7a3987c00f364d0f148ead6d7e6a37b05456b913b7a79c0547b80da2a2893881", + // padding:3031ff0d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "2bfc087003f3b98f0c8c5273de34f5e4d5047e909cd80e222072f6a7926ced5a" + + "e169131342640f2be11bde2f7565c3c63d0335614dd278915514de8421f4521f" + + "0138109a5c9778f86647b8a42815b6b861f173f5a6df893873f99c5e62bc3c08" + + "6150e3b7d7abb943ecbe5806068abc433e9052d9bdfa19a58d19da463dbf3b23", + // padding:3031300d040960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "0fe03eea6c50ab664bebc7d64346762aa29b08b61f2877973cd543c9533c9d04" + + "51db8d836eb46e8d64283306efd7ef6387cdc3c794f7474f2e7d51b9df078095" + + "adc85fb810cae52434c9cee5048fbff72610778397fd83204f44bb87f7637373" + + "d111dd16e18287bd9ffe816683bc3663f586082fe0811ff6a06c0264b67f7716", + // padding:3031300d080960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "748b9e64195314003ca31f726bb3d3294abd8eb376365acc5b1cd36934bbe1a9" + + "bae99ceb7c1a40c910bca6007ced7961ecc9ac74c7a6424cc87b6b9610320ab9" + + "c5b527d986c6e8ed21e677bbe2ee7752e2dbcfceecc2dd6da3f6c6b9c81435e9" + + "e060dcd67ba834729761dfc9570b79bb1b8ead7bc1325c2233e445eeed12dcad", + // padding:3031300dff0960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "7379bc96dd40d37a7f8e58f87c10fb94f250a964a55b2abead479b368e60e442" + + "e6eb864952308eb45eef1d318b6a5ffce634fcb886dbfa062060b9809cf89a09" + + "a26fd334ca22a1917fd219900ec0c68164c308cb9cbca3fb2b89ed8637c5540f" + + "7a5886ab1e52c503e20edd6316e41c746e53917e107ef5308590800ad378ac97", + // padding:3031300d060960864801650304020103000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "4a2478918565be6b46fe61e5f66cd1befb7a3026b5a1502e9a42636b0b924a02" + + "e85d7ffdfd8671b1d6d3e604e3ac6a5302db4e0ae0975d0661efa018d6ba0c63" + + "2a6381368dcb75926542c74823a8c6d8732619764d5a61062fb3b17ae243bd69" + + "1c97c8f9821af9526abcb522ec8e9dca32de1989e576e336af9dddc3e766541b", + // padding:3031300d060960864801650304020107000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "5ec392c91cc165ae59013337e7f7d5f2f9b3a6d45b6f6beee6dbf93e7b960790" + + "0f4672555a57de6e9e1aee1fc9b7adfc0dc00e122e84b0233c0d615dd0d79764" + + "fdc9d1b0e541f2de0083ab479f313a07f55f51390d1c2274858b219b1ec0601b" + + "82a2f7648ae95ec17099067a173e3e83959b6c06f149af0e4610761aab5be1a5", + // padding:3031300d0609608648016503040201ff000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "6173aef07a7057c3e97f6b7d4d7266918876f9fad86000b4c8ec7f83ee491563" + + "115b0cb5d580df8c97feb0d95866eabb79147926f5395c5189554749f4a2c75c" + + "0d96325971635be029062e1f27536c5041bb42f42e1fa10e21bb8e9a2e2502f2" + + "a7299dfe3bd8720ecb8a57238056ab0eb546de8dc0e56b317c73ab1e19772596", + // padding:3031300d060960864801650304020105000220532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "3b80c72f3b7ada8b38b30527bca41180b4a89b066f44a17b9df5963dca46517d" + + "9160326afee7a34b650b9e7746e764958ce6a0a6268481a8df40e0a95a81ab0f" + + "0bd20c050becfc0c4b03ebda19749a4a1dd3ce925fafd9a4006a835eedf221a6" + + "ceab6aac6bc74f743fe171ef8c01935f8901e1ec9ff6e33ae8311851fa14a65e", + // padding:3031300d060960864801650304020105000620532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "4b0eaf3ae1c7a3322dcfabee0569aaafba51e0f34fa6afc325bacc853ccd2daa" + + "3dca56c918325bf553af02ddd19fb597c368dd18892d52d9e935dc51d38347eb" + + "ae2a7f90c78504355f6899ab4452d5f51d2025381d81042a08582dc50bc10782" + + "46ee69652043bb747969a7450659e333193990f34a8ce3f036221193e700489c", + // padding:3031300d06096086480165030402010500ff20532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "1fe7b390bcbd5bc1904e676111653e14e581e7817b45294bb790e4e62f3010aa" + + "aa77e246b29729f2b7da65a2f437b8d9c4fe3b26baad367a19fd7b1758d04c2f" + + "788c45e5309a833522b46d7255dd5ef70ed006ef966aa7c648bd0b893b8e1566" + + "961c16e9554fb729ec81819f1b3da890d413a153f487c030c7581da9531bf134", + + // dropping value of sequence + // padding:3000 + "317379f37cb7f21fd03259a27db3575d491a248df82e67b39d4956a1c619094f" + + "cde001544f0fa70c64dc0d0440fb21d2860a20a911cbb397792bf3eafa5cc050" + + "e78b1e7bb29d041cfa0287bdf54a90a7a8bff5c870e898fe34bb522477daf8e0" + + "03bc22891b789ff215869cceb92610c4b03210d19506058d941e6fce7a3cd786", + // padding:302430000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 + "2de802ddacb7e47e27875943d5098419bca3b170bf74f1c4b4a8ac420d4469d9" + + "aea97592fbeaaa1dcb5fd20bb97afc5f7abae17a9bb85c5490db97010c5217c8" + + "8f9f52b5e209cf5fba5f0594f4e4450114dd0348ece336870a1333f7660caf95" + + "9056ba13b77d35239eea164ddbc8808f8e7e1beb070f551b6e95f90d5bdbd925", + + // using composition + // padding:303530013030300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "09342a8fb8402b5e50fbf8c5d1cae415ce02c0a803adfed88188982129e84809" + + "18dc21616bb5f8381e8dfe13f63234090c32e542a005df70df5e8e00dd2a478d" + + "10fff1b61efbdcf0e410236f7c031c9a5f7cd0db9098f8a32a6a49f408e72c4a" + + "29b7d27e8041ba605bf089bbdb9777e19b31ecca0d49b90d54701721af79cf3a", + // padding:30353011300106300c0960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "3ef90c414a64601c538c286f2c35f32445039799b8c266eed605027578edda79" + + "6a409d905a751bf5c1cdea97840437fa82733d8f27efbbc05da732887078a8f5" + + "47bbfb54607a54f893df7dde0c35c45f9c2402bed0405c72e98175e5b9d6f902" + + "24e07d12e8c1bbad2fc8b1a14c42dd5fb7e554db5edae89d335705c672cd7b55", + // padding:30353011260d0601600608864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "3ad3e4ec3636b5eb8aac2161c04d228491ca0d9da2abd69d8904054373940b39" + + "b5c025c011c9b9508a25ec25b24a0837cdd6a27cb5c8ba3683d90ba5912ede9a" + + "21f2f7e851dc49dfebea8807576be703a6a87ca44c370db76812b9929a54fb8e" + + "2259453ccaf47da1b8ddc5b7322c20197604b9e028ec00bd7eb48012274d5b81", + // padding:3035300d060960864801650304020105002424040153041f2eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "778d93be708d56defbb6dedcfec2a917a3772b2810e26143db1f9d0f26c4fbb8" + + "de8db5818aa32ebb2cdcd7960e593ace2c3c3eb682c930cbffcfa6b34438ee2a" + + "786a9707d5d10902f7f4d8fc677106275fcb6cb08f56f341e0f52af590e0bdfa" + + "2f2bf95693265e87f5046bcf3e6de34810e8eaa479f3afa2b0a98b175007c209", + + // truncate sequence + // padding:3030300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e + "a3e0e0cb9f7cdf8a2b95139f7c475f274bb63252385f62e66f82158f429e74d8" + + "3df9ab1040717d34b6a5e009b6ac95960826ee83bb298ecf900425ff03a8f156" + + "053b57eac6086d61dd3a8085b84c83bebbe3270164e3147ddee8966a02679640" + + "1fa48da70f5d949386eccad26b0016543f3f90c8ac2874100dce13f03845509c", + // padding:30300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "84345c9d3de7b5da2156d3669a731c4baf6726c4c231bc8bcaef950d7ac37ca8" + + "d86e9c9558404f313de3fdf09024d25491b0a933cc3958033210b1c4f90070dd" + + "d083005873762566ff2cd7f6915b4cb430f5e7e1bca8c2ec32b4ddee48aba667" + + "f9d614a27c3bb40c6cb7f0cd77d3d17257f197974d1871cc09c9583cc6af8e15", + // padding:3030300c0609608648016503040201050420532eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "227aaebca262d2189c479ab46d8715a34100bc1975c2d3991a4ade27376f0687" + + "56cc9d89e903713bc28394d202d81b32126d7eb09154261841227cba6ea0a60d" + + "0ed9302f816fb4dd241dcd2d746d5c1b068c42c0b2bd567ef799cbfd0a83e8a3" + + "0c4fa2f7296dceca38c36ab597ba992f658ef7955d32d38847870afbca35d836", + // padding:3030300c0960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "a4316d438c7091b3bd5ec09aeea9095cb5046d8f08642b087c34985c34377bda" + + "fe74285d00862fba20572ce7a06dfe62b4fc08704d1cfb161cd88478e7e1c545" + + "1e0bdcce0fdd83c0e37fba5168ae03fcf4ccf60fa12c9b0acb39fe99b06933b9" + + "e0774f41151e0564ef805144c0cb76101672c287912197155d91bf036e84d1ce", + + // prepend empty sequence + // padding:30333000300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "361f80a57ddb48796e50b3e6467cb00a9e1e193330ecd2cd6a31f649b49eac27" + + "e295450efe03e09e59f1829cc661d36b0fe904602c644aad7ec8cb2ca3099078" + + "b6d4f7b9233dc159fd1a6189451fedbd176e436f6605f2b889fc7197ebb520ac" + + "cd7f90e543da44453c7ba1948e83e31f5907d1989d982acbb348ca2216fe050d", + // padding:3033300f3000060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "674c01596bf71fccd36aa81b000be007f6cff713e5f6ffe58b25e790f9a1f654" + + "2ba3f68e1eeaf1bb1ac6c3d55aeaf08140f6cc3d0474f6bd87ee442568346553" + + "ceb34efb5301a4d3a5b3f28a5fb038ccfe8444524d18adfa042aa1685fc3a5f9" + + "005da5688853b8660ba74f0e32c5be38c743b0048ca9b9fc19a35a5ff4e2c48f", + + // append empty sequence + // padding:3033300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e253000 + "07ba2b5d519b1f60dc455d6ad90b4135cb45c5da5a2a2c9b8cb954165394a0f4" + + "0145ebf2b1a3ff1d47f5031d542d25041fe9b6d78aab623c40eedcd846761816" + + "8ad02af8a696573c5c63cae0b2c26583b0240848d663fdd0195322bc2c8dbf9b" + + "5db2ff9cc3e75e70480e51da0d6dd402fa87772ddef5256467205cf41a42d18a", + // padding:3033300f0609608648016503040201050030000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "9fd302307455d4e946c1ccee65b0941c3550c823279cc52c4f29ecff72a12ac4" + + "0ef6b7e37b7dd774b7735bbae89b0792908bafc47f0b0a11637042fc8541b346" + + "151bdadc3990e64b6d1807dd0e7f9266ceb3f686a9813341f835562d3c8c8486" + + "8a1f98db97d3e695ce4a25fce80b828d010d6323120362ac48700abff8a7116e", + + // sequence of sequence + // padding:30333031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "247aa1cb69ccb72795c93809d7c3a5e52de98ec5285196058a6ab18ec2f5d9fe" + + "f5545ab5df923f63bd58f5f247b3d824bf161bcb56d325d4e2fc7eb3765dd81b" + + "5580422abf2a3bca8d8af94cf6a9a3133b1494f66d5cbe938d30b9308b5ce2cc" + + "6d3df37d3299b6a7616d40afcc7935d80225e1a89a7a63ebff13a66e21280a6a", + // padding:3033300f300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "6d6248f823020a9604bbafe5acc103d9bd020624585c95805533de22afa3b6b1" + + "b511f8805296ee4d3e96d707c91e55df8959464ddb6d6a3d62b1cb248754302b" + + "2833406300f4975d913f1b90f95e3673e2c57d6181d73a360e8c818b8a9dd1e7" + + "a4fdcd68683f11dd47c2d395f20b0ce9c59eede6ae6aa58a707c4ea8d1a73a9a", + + // truncated sequence + // padding:300f300d06096086480165030402010500 + "941d41c39aa8bf3879d16cb78c5486589e7b97e56a0249c4f613060d26b78659" + + "8fd2d34bc4e99cc8888137975937307d6a328059a09f3b994bf955c7de4a2841" + + "a0d10bbbebb2db3b332656f258c66c8d50cf9155ba94e1cb21a78e6147af7695" + + "8ddd997665b6d8f67ea8f5e1fdbebd7df635f20494489c895d33ae4c7f248bad", + + // repeat element in sequence + // padding:3053300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e250420532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 + "a32afeafa2c3b58bef55776ef6daaac6647485dde100d968e0449d1a2d5a1218" + + "07ca2fdd70e2e9cf524cae4f263e11837000df85f0886b718ff45cd316c8d031" + + "b746dabfb956dd6118a37e0dabcda1ce9c728afd9a5f2448f5b15d2798221888" + + "8d457752485119f53219315bf63141c9c0802327226a096403ece022cb27c0df", + + // removing oid + // padding:3026300205000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 + "6098a732419cd71887548ccf4fbf3edeaf9fe7b220bd747ae1b995b746de1f4d" + + "7b48c73ddb71903f50ccf7c93be9c8219de5a75ecc302ab50356069dfaf642f3" + + "2ec580a283519fbcf04784860b0660174dfb7e1e527bb320960bde8f6c605bc3" + + "c1055b878d2adbb44e1b6c41add15cb603345c4fe2d1c0158fa03f21b4c015e0", + + // appending 0's to oid + // padding:3033300f060b608648016503040201000005000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "2f08cdca4d621007acd15b1f4e3c39882a8aef706878e8f101e7fb250798a352" + + "8dcbf4d3327ceb0754a2ca0850794094dde8a875cb947d624d386ddb9593259c" + + "53ef2311260ac3c9cd1277050ec98d105188f590f198ba908ddcf3f9ed18f5a9" + + "6cc6b353fadde007658f87ff4c201db7621d69c8278305f3e9f2041a2dddfad0", + + // prepending 0's to oid + // padding:3033300f060b000060864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "10078ea73abb9bbb879c9d8139b1758170fb73b34f39cdc83e6a725439e315a5" + + "cba4421fe15e8c80d8fda0a9aba9a12c23aab41f7328d4191e6c7c3a53a505ab" + + "518dce078439347945671ab06a2cd5375457b3bf181c40a1a4be1ea8305c9a40" + + "1488532c7cdc1150fb9c46a2e846ce4a2fd9ee863d0b0b8af7f10360acc47f10", + + // dropping value of oid + // padding:30283004060005000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e + // 25 + "69a74665f61787b54b522937c534e95e91917f5dd4fa9e3472add6e21dc033a2" + + "75408f35c71ff6cc029e25986fe6dced8ed053a9040aac32fc444e9252d2bd40" + + "81fe3e51ace15a0f694c0b8953dd6afa7f8cac67f4d8e17513b415c14b439a63" + + "4274893885907e2ea428a6e242154a58a031fedae31c73df7cd4e2f5591496cb", + + // modify first byte of oid + // padding:3031300d060961864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "8f3b544724810d462cc9b19f356e61efe7c192dd63511a9f1f63286ca81f8947" + + "7c2b464f8e51a97ee138dcf8c6709d79a78591081384af7cb5e182c9867b8260" + + "13e6191efddddcc39909d3ffbb18944503b69d774c959831a8092f4790a49335" + + "21100c3e9741c3b58e1d24b75425ee28fde4e40c249b4dccd726cb06cb9ad2e3", + + // modify last byte of oid + // padding:3031300d060960864801650304020005000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "3933d6937e977caac37a07a5c4ae503565af57e6c4e830004147f8bbf6784f79" + + "666d89cb4cac60e3f0aff2d5ed6a182921e490c958bfa49c86fcf0270914c102" + + "275b0878f01795c7a2f44a8a6f5306aa67a81f9294089876801503989e749d15" + + "2c3e34906291f1f54bb6232fdd3d51e807f70927bf38ef70bd2ba45f0323acf2", + + // truncate oid + // padding:3030300c0608608648016503040205000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "7b2f6581fb0b4f913ed38c0ea20dff2bd60723f2bc3f1022ceb946e48adb75b1" + + "e0be031dd8b706d82967f93c6b6ba496d8c4b49aea9970e139b18fefdce30a4e" + + "c04f77625eaca4c7d1265cebbbcf53b63a113cf06bc50e4a416a771cd28785a0" + + "075631a3ef60c9212e224aaa063e7d8109c27e248e6422b26acd02ec012b7bf3", + // padding:3030300c0608864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "4dc9e86e076a395b530868d9fec9f858bd6e8c10cc1e32cae7653abb3f23991c" + + "677e970ee468c7f35022f3241f5d35673a8cf4ce9134b1e63a994dc7abc8cf4b" + + "9dbbb126b314312539931a0163c911f0234f5c3f683c9376f2ecaa3294d71a12" + + "74f6c63b84ea8faf826eacb05e4fa5459b787ff384b2cfe0f1f4c755f32b5c50", + + // wrong oid + // padding:302d300906052b0e03021a05000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d + // 7a6e0f345e25 + "8bbc9167821885a728260bf9831120ecc42c14b2b07854169c86421146367d1b" + + "ec66d8c3daadd115f16a29754e7fa8fb70a63966f7838484615d4364311b6c3f" + + "6e73ecd8ced0adb52db2c374297119f5fe571bd5396529d13b7225e87db5b5b0" + + "df38e4c56f2349071b09ff5c1ded919b398d4aff38c6ae29af6f6ff99d3e8836", + + // longer oid + // padding:3032300e060a6086480165030402010105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "2054d402bf6a148b52972b830c8c8a16a6aeddbcd5c2ae3fd83de67c666e712f" + + "a98650308658837a67ab87b2c444bedc7cf995c19af433da9343f260049b1bcb" + + "436ebe27d8a502728dfb0daac5d2710e2c39fa000b909aede07ad7a0d27629e0" + + "ac27ed9fcd41a39e09f7acdec4c2df77f38c535f46e3b96f2772a81e65e74bb8", + + // oid with modified node + // padding:3031300d060960864801650304021105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "3a94d241563a2ad97574ec82baefccd9dd114e21fa9169d0f54c4d0f57826224" + + "804ddc9b29c1905c59f39bd6aa3366705a85f5e6e18c0eb0f67986b5265e7371" + + "865b618e90e5c5313f0b6fce2343aa12d4ed44d6770fa08d4f1342608a4fb627" + + "a273f3a1f1340d1f5c55957ce51048e3690a845851009cbfe38d3c96e96d4172", + // padding:30353011060d6086480165030402888080800105000420532eaabd9574880dbf76b9b8cc00832c20a6 + // ec113d682299550d7a6e0f345e25 + "079cb62831dbeb40a638402865cc92cb49913dae214babc3f4f8d69d64cf1436" + + "2c23c8dd6ebcee9c44633dd54a62bb2f0042c20033728fc2f8ff482cf0be3ee1" + + "03bacf757b50319495d9a838844ea1064f4bd1f1ebdc1b71a318c3c8f7d76ebd" + + "79ef2f3991d4d87e110d60e5fc655adfa4a8e792e46c1c7aa96156b884e2f7a9", + + // large integer in oid + // padding:303a3016061260864801650304028280808080808080800105000420532eaabd9574880dbf76b9b8cc + // 00832c20a6ec113d682299550d7a6e0f345e25 + "2c9083459ba6504dc10e0e63edf8ede8bdb4a9728673306908ad4e8f25656d48" + + "65f0748b9fd2cf7b51db0a2c659e0ce021fef3d2d3d0cf7c45343729c2001a19" + + "d37e29398a9a7e92d7f62693252261f1f7406b54af5447db6e846f981722059b" + + "7bb09ba95268c321c156ff659e0ce8e709d2819d5ce15f5dcfa54c55114a611a", + + // oid with invalid node + // padding:3032300e060a608648016503040201e005000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "9a76669c75f0f11399699f76e7bfbefc0d29feb5a8d86de1f751eedbb5c9e7b8" + + "1ecbc224534db67cfe1b611951a6ff499d86e11cac4a1725e2ff707085a81a76" + + "c73d5b53d1b0b2c4fab2d2eebe57eca83242a261cfca768abcd8e1f42e3841d6" + + "98bef3d4f16ac2dfab0fd42ef0abb0463474367dff7ec99d665a9838f2cfc24c", + // padding:3032300e060a6080864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d + // 682299550d7a6e0f345e25 + "6674ec2352f0d3e90f4b72086f39815db11b056babc57644c8a703014f439baa" + + "46e8ed961714d5c7b5f0ec97ba3fe5ab867c16b7e1de089868dcb195fc20cc42" + + "fa1b3d3060f50cca77281bb6be18d65a1ee8e5a381e21e7f02e819752b71327a" + + "28719c7284f6425bc9241abb08d000faf58d48848d7f4b8d68b28266e663f36b", + + // appending 0's to null + // padding:3033300f0609608648016503040201050200000420532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "8d18a5e0a81522b56eb9e4f43bee15475cdfc7881006150cc230e76028283375" + + "a13425fe5a106f2626346a65817010a5510b157b234a16fcb9426909a524a288" + + "161537be91ab13033ed296f5f8c1e5c3bdb963f12d7b5eded46106f7c2dc1ae9" + + "c451415303cb7e6a3f59809b922183b9638197909d5730e5b1e89705fbbe8464", + + // appending 0's to digest + // padding:3033300d060960864801650304020105000422532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e250000 + "51640e26e8764936a7d9d709b3e0f52a5f1843453f2c6107a8e7fd6dad8b1c02" + + "ecc71659cd4134be952c03ee83c190bea4ea7260e5472c3cdf87b6ad45b5c974" + + "957ee9b4bf6f30152c2d939f722cff32e5482db96f3e283532b96716d3624daf" + + "16767e0ecdad16c97e56e4e076d64b92af329d2d6a2f8d14b59d1b84853659ab", + + // prepending 0's to digest + // padding:3033300d0609608648016503040201050004220000532eaabd9574880dbf76b9b8cc00832c20a6ec11 + // 3d682299550d7a6e0f345e25 + "9080bd4ac03b7ecedd45f8165360d4848bdfe1c9212ee1a4debc1aa92886cd79" + + "47a2df5435789bbb0b3e8f78815aac80e2cff14e1939e9ec32f42e7c29ed4029" + + "c88cafb64e8523dc85217c40d1bba900468a69c5bd4d12ac67401698fbffaa51" + + "59907ad459d3843e12487b3b2315c585881bc42e45543f7cf25110ab7e0a19f4", + + // dropping value of digest + // padding:3011300d060960864801650304020105000400 + "5f66f645307346216d3ba9c3d8b29e96270cb3b2e686a676fe975c10b8c26fda" + + "8d8eb172628bb3dcd726160c13ab8c5afb1d6ae943ea4c18d00465d97c0d2bcc" + + "27a63c18457ff8d6e3f5ba373b4be7b6f4c610f83578613f4fe41a40d86230af" + + "ce0bb8d4496425a5bf0a80c6b1b1e2a981cd44c31a9aa603748c3d2fd2b85478", + + // modify first byte of digest + // padding:3031300d060960864801650304020105000420522eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "8ccff4ab4fd8534b6b50593f775bf6684391225adc37745e7ff25a4c4baff78a" + + "252aa1177ea3f3f09d2791da50ba19cef40ab8915379f128bba3271069cc2c02" + + "725e09f0b2cdfa0d313eba3f5a7e231588fd617b7d90b285e88a944d7d0a7fe9" + + "cc558dfe8103391ab2e6fbf762d829a55ed4486b5d888957078ffcf49e8ec352", + + // modify last byte of digest + // padding:3031300d060960864801650304020105000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e24 + "694b90d259b8dbe290f5851ede2ebf3bb718c1674ab1d3b7b6418e8ef7ea0760" + + "bf3ce69d98a7a3baae5aee488cddfb877972fa88ad05996879d0ce15aca53591" + + "423bf1b1b3ff02f823cdbb26bb80e3f7b83c3b7ac01ad7806335f871cd7b7e9e" + + "64708c200a9cd092589131aeb7db15655174000cf7db782bd54325ea956a1a15", + + // truncate digest + // padding:3030300d06096086480165030402010500041f532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e + "888cd9bdece5ceeef0fea92727ef1a1d996960f3f551bf108682f81035903236" + + "69ba1ab48becd14a49b87a900434d0ca7670d094b08b2f851834757bef580d2d" + + "3278d85b88036ea90d4c2a673dfafeb0c3701332c2b77493110d9b28dade7e98" + + "5ec27240c90498372fc00ac8e0e5547e4d59cdd19022b8d961f3b63630b5448d", + // padding:3030300d06096086480165030402010500041f2eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "762c745262627d0df634d6cce41fb8af3cb855fc2d974b8093b035e9d11e510b" + + "9b7e7d61581b8f262fc1c4b8a6da3f6d609512e32f16416c7449c623c1773417" + + "032ddf2a559d7eb3af129fd02f83b5e35f5b5c065b1e0bc6481f38b6361f0b01" + + "8b5e7166e8e67dddcf1550222f125efde241a27b0e7f670d15346dde082a8c4e", + + // wrong hash in padding + // padding:3030300c06082a864886f70d020505000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d6822 + // 99550d7a6e0f345e25 + "27830ed405bc9d34009ec6258b766100273b4dcf2a9b3cf6ae31029837c6e24c" + + "f6e819734c1fd10c2c23db34d227d98d3498850f083ecd78b648baccfd4647a5" + + "72607dedbc2b8ab7a595c0594ece904380e7f395ba4840a81367e99275cde106" + + "4fc6f7fbd564c5f26ddd0103991ae8262eaf16623685b43f77ea7a05d080166a", + // padding:3031300d060960864801650304020205000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "4cdfa8cd615bcdefa253d75212e4ed0a1fd60841656c6a749690cb0c6c3cd723" + + "b518560c3b11a734010acf6e38f0526338351d9b58351826b360c851d3c86429" + + "f38eb689e8555aa2a23157e197faebdd29bc49f84c10dacca655cd5fa50fdec8" + + "6a72f0ff1c7f8feeec31fee188fbfa72776a7b5cdae1c1506830bd3a00181b13", + // padding:3031300d060960864801650304020305000420532eaabd9574880dbf76b9b8cc00832c20a6ec113d68 + // 2299550d7a6e0f345e25 + "024746d8dd71ecfe33cf0ad7ab8ddab9dfeb5740ec47b8ddd668f07b8f7610f7" + + "26692404ac14c3a1947ff4246fe0a9e216131489125e71df68d60930fac06a20" + + "e948a3e4948aff5e3f9772155f8bd6772b1cefd8180ae719afc061e2f0d68a69" + + "769930b8d90ca4ecd6c7b20d04f0cc939502e698ad1c500403763c0205f6870d", + + // wrong hash in signature + // padding:3020300c06082a864886f70d0205050004100cbc6611f5540bd0809a388dc95a615b + "3a152ced8b5e0efa33cd57d4afe67f31ed3b9fb22e7b0ff32795cd9510374fa0" + + "9fc63a3366465f83ba4d44e36418a5c1d171b6ca05d8c74a242983d5e5912cd0" + + "5bdbd75fcfd5b4eda7cadab21e6dcefca8e2ab7303871ef360beff45564a01bd" + + "c887d9e849e407c6aa5b12055647f6c9df49758d1272f7cb476f51088e21f246", + // padding:3021300906052b0e03021a05000414640ab2bae07bedc4c163f679a746f7ab7fb5d1fa + "3765b8800e6ccf29544d834034e39f8fe7a2e6dfd7e6b4a8f81df091bbfd7aa1" + + "7edfa6005024fe04d35c340a2215fd3f1cf4b4dfdd3c8ad09e6df2c2256c7541" + + "e19c2e80051d1ef5df5c384bfb6be88c4415eb2740db2d9fb3214890a8a0f191" + + "46dfb7897bacc02700a89139dc8fb21b2a7bbfbd43604d7f384cc00aecefb4ef", + // padding:3041300d0609608648016503040202050004307b8f4654076b80eb963911f19cfad1aaf4285ed48e82 + // 6f6cde1b01a79aa73fadb5446e667fc4f90417782c91270540f3 + "5c5b097c21ac2eb156de39d1eaebe3b96082f54b0171469a94edf7d2027ebfde" + + "bc0837f766cfefec577e7b797c7a082df2ecc826e55d39927b01c2da26f8f681" + + "4ec993e3b93ee87a3418322b65ac652b3bba6d34373a13fd40b66be489938fad" + + "f67bbda762f6ee09a1ddc41382051d4a9a946e0df832bc65b7d5dd58cc5a402b", + // padding:3051300d060960864801650304020305000440c6ee9e33cf5c6715a1d148fd73f7318884b41adcb916 + // 021e2bc0e800a5c5dd97f5142178f6ae88c8fdd98e1afb0ce4c8d2c54b5f37b30b7da1997bb33b0b8a31 + "0ede4ac9ffcb6d3d42c75cf73303a28ba6089941f68dcf392a75b071f6c149a1" + + "09cab95b80a679ca3b29ae44e51c18a2db4c72211ae6b959c7f22e854c45f20f" + + "5560446f33be4819f08d981d2fb176d48039ac4acd28127d593f9e219ad40e2a" + + "5ee911b334b3b8bb290f2327524e3faae2c028745e03d58882bfe503c4ff04b2", + + // using PKCS#1 encryption padding + // padding:0002ff...00<asn wrapped hash> + "6c0b3edf5f6e5d3f07057d0b752e89cfdd1c289ad18a0ba94670cd36547734e2" + + "c7bb32dd49709f0f7149944c450c23b7f2d360e3602cad5ddff7fd9d711eef6d" + + "d4c32e66c4433f041fffefe112024a655bc5bacbd0914bbb2b2a41a91b1293fe" + + "9478ddca926a13e6131cc5e9b70625eac1e533ce8171a2dc7b2c4a490e966445", + // padding:0002ff...00<hash> + "1acce04e348a5c8377c54d8ddd8ec2d8c5cb9b195863c32eb716745f3462b5f2" + + "49b612aefb31ba484949d0a0cb5cb8e1f06c1cec58fe5ffff6ba796218c46c3e" + + "527c7ab0c4276ccbafd133812faec33721a08542e7e3a34449bebbb28bd0f289" + + "94c6801ba5c971991004e31de8f728f6bc37a4ec7b049c1f2dc64d4be9415462", + + // invalid PKCS#1 signature padding + // padding:0001ff...ee00 + "61a4066d0b64964100ecf583325cad10b53912aba1bf3606720d2bdd8e21120b" + + "b0b5e4323987d96039819ccce0e5e90854bc0e5c239ab198f75b00355a04e4eb" + + "1f855f76697cd65732820575306eb9323954bc5913568a7278fcdeff8e8acad4" + + "481e3559f8c44a0be3bc02bae437c3146e4516632b3fe788c3a0e44171155728", + + // PKCS#1 padding too short + // padding:000001ff... + "979a313677883b0980997f1cb525f43401739945860149dcad80f602df8abed4" + + "fd85bcd6e174d9183a5a44008fd77b5a5abcffbcfd4f47ccd2dabef963d9b228" + + "310d99000ed0cebbf61438cbe586985bcffb3923a8467a97ae791d0b04925c08" + + "94b5a41583d6de72d4369f481f66abce41a577fb128fc0b0aeec746ec089d834", + + // invalid length + // padding:2 bytes too long + "ab9014dc47d44b6d260fc1fef9ab022042fd9566e9d7b60c54100cb6e1d4edc9" + + "8590467d0502c17fce69d00ac5efb40b2cb167d8a44ab93d73c4d0f109fb5a26" + + "c2f8823236ff517cf84412e173679cfae42e043b6fec81f9d984b562517e6feb" + + "e1f72295dbc3fdfc19d3240aa75515563f31dad83563f3a315acf9a0b351a23f" + + "0000", + }; + + public void testBasic() throws Exception { + String algorithm = "SHA256WithRSA"; + String hashAlgorithm = "SHA-256"; + String message = "Hello"; + int keysize = 2048; + + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(keysize); + KeyPair keyPair = keyGen.generateKeyPair(); + RSAPublicKey pub = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey priv = (RSAPrivateKey) keyPair.getPrivate(); + + byte[] messageBytes = message.getBytes("UTF-8"); + Signature signer = Signature.getInstance(algorithm); + Signature verifier = Signature.getInstance(algorithm); + signer.initSign(priv); + signer.update(messageBytes); + byte[] signature = signer.sign(); + verifier.initVerify(pub); + verifier.update(messageBytes); + assertTrue(verifier.verify(signature)); + + // Extract some parameters. + byte[] rawHash = MessageDigest.getInstance(hashAlgorithm).digest(messageBytes); + + // Print keys and signature, so that it can be used to generate new test vectors. + System.out.println("Message:" + message); + System.out.println("Hash:" + TestUtil.bytesToHex(rawHash)); + System.out.println("Public key:"); + System.out.println("Modulus:" + pub.getModulus().toString()); + System.out.println("E:" + pub.getPublicExponent().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(pub.getEncoded())); + System.out.println("Private key:"); + System.out.println("D:" + priv.getPrivateExponent().toString()); + System.out.println("encoded:" + TestUtil.bytesToHex(priv.getEncoded())); + System.out.println("Signature:" + TestUtil.bytesToHex(signature)); + } + + /** + * Tests an RSA signature implementation with a number of vectors. The test assumes that the first + * test vector is valid, but everything else is invalid. Many of the test vectors are derived by + * signing modified ASN encodings. Hence accepting an invalid signature does not mean by itself + * that the implementation can be broken, but often points to a bigger problem. The test expects + * that verifying an invalid signature either leads to a return value False or will result in a + * SignatureException. Verifying an RSA signature should not result in an RuntimeException, so + * that reasonably implementated applications can be expected to catch and treat invalid + * signatures appropriately. While RuntimeExceptions may not be exploitable, they often indicate + * an oversight in the implementation of the provider. + * https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html + */ + public void testVectors(RSAPublicKeySpec key, String algorithm, String[] testvectors) + throws Exception { + byte[] message = "Test".getBytes("UTF-8"); + Signature verifier = Signature.getInstance(algorithm); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PublicKey pub = kf.generatePublic(key); + int errors = 0; + boolean first = true; + for (String signature : testvectors) { + byte[] signatureBytes = TestUtil.hexToBytes(signature); + verifier.initVerify(pub); + verifier.update(message); + boolean verified = false; + try { + verified = verifier.verify(signatureBytes); + } catch (SignatureException ex) { + // verify can throw SignatureExceptions if the signature is malformed. + } + if (first && !verified) { + System.out.println("Valid signature not verified:" + signature); + errors++; + } else if (!first && verified) { + System.out.println("Incorrect signature verified:" + signature); + errors++; + } + first = false; + } + assertEquals(0, errors); + } + + /** SunJCE threw an OutOfMemoryError with one of the signatures. */ + public void testVectorsAll() throws Exception { + testVectors(RSA_KEY1, ALGORITHM_KEY1, SIGNATURES_KEY1); + } + + /** + * Signatures with legacy encoding. Such signatures are sometimes accepted to be compatible with + * previously buggy implementations. + */ + static final String[] LEGACY_SIGNATURES_KEY1 = { + // A signature where the NULL parameter is missing in the ASN encoding. + // padding = 302f300b06096086480165030402010420532eaabd9574880dbf + // 76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 + "253e1d19bbe91064f2364c1e7db3ba8eb6dc5b19202e440eab6fbdf28c8c6ec0" + + "5b812983713c338c72b6e99b8edf506a89ff9fc8e5c2c52362097a56dc228060" + + "eca01e1ff318c6c81617691438703411c1f953b21cd74331f87c9b8b189fdffd" + + "fe8550bd2bd1d47be915f8604a0f472199dd705e19b1b815f99b68d60bc257c7", + }; + + /** + * Tests legacy signatures. In this context we use the term legacy signatures for signatures that + * are not conforming to the PKCS #1 standard, but are sometimes generated by buggy signers. So + * far this test considers both accepting and rejecting such signatures as valid behavior. + * + * <p>Currently we check for just one type of legacy signatures: i.e., a missing NULL parameter in + * the ASN encoding of the hash. BouncyCastle and the SunJCE accept this signature, Conscrypt does + * not. + * + * <p>Some references that support accepting this signature: + * https://codereview.chromium.org/1690123002/ + * https://groups.google.com/a/chromium.org/forum/#!topic/chromium-reviews/Jo5S7HtEABI claims that + * 7% of the responses in the Online Certificate Status Protocol (OCSP) miss the NULL parameter + */ + public void testLegacySignatures() throws Exception { + RSAPublicKeySpec key = RSA_KEY1; + String algorithm = ALGORITHM_KEY1; + byte[] message = "Test".getBytes("UTF-8"); + Signature verifier = Signature.getInstance(algorithm); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PublicKey pub = kf.generatePublic(key); + for (String signature : LEGACY_SIGNATURES_KEY1) { + byte[] signatureBytes = TestUtil.hexToBytes(signature); + verifier.initVerify(pub); + verifier.update(message); + boolean verified = false; + try { + verified = verifier.verify(signatureBytes); + } catch (SignatureException ex) { + verified = false; + } + if (verified) { + System.out.println("Verfied legacy signature:" + signature); + } else { + System.out.println("Rejected legacy signature:" + signature); + } + } + } +} diff --git a/local_repository_defs.bzl b/local_repository_defs.bzl new file mode 100644 index 0000000..3c9b348 --- /dev/null +++ b/local_repository_defs.bzl @@ -0,0 +1,25 @@ +_bouncycastle_jar_rule = """ +java_import( + name = "bouncycastle_jar", + jars = ["bouncycastle.jar"], + visibility = ["//visibility:public"], + ) +""" + +# TODO(ekasper): implement environment invalidation once supported by bazel, +# see https://bazel.build/designs/2016/10/18/repository-invalidation.html +# Meanwhile, users have to call 'bazel clean' explicitly when the +# environment changes. +def _local_jars_impl(repository_ctx): + contents = "" + if "WYCHEPROOF_BOUNCYCASTLE_JAR" in repository_ctx.os.environ: + repository_ctx.symlink(repository_ctx.os.environ["WYCHEPROOF_BOUNCYCASTLE_JAR"], + "bouncycastle.jar") + contents += _bouncycastle_jar_rule + + repository_ctx.file("BUILD", contents) + +local_jars = repository_rule( + implementation = _local_jars_impl, + local = True +) |