| /* |
| * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| import java.io.ByteArrayInputStream; |
| import java.security.Key; |
| import java.security.KeyFactory; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.NoSuchProviderException; |
| import java.security.PrivateKey; |
| import java.security.PublicKey; |
| import java.security.cert.Certificate; |
| import java.security.cert.CertificateException; |
| import java.security.cert.CertificateFactory; |
| import java.security.interfaces.RSAPrivateCrtKey; |
| import java.security.interfaces.RSAPublicKey; |
| import java.security.spec.InvalidKeySpecException; |
| import java.security.spec.PKCS8EncodedKeySpec; |
| import java.security.spec.RSAPrivateCrtKeySpec; |
| import java.security.spec.RSAPublicKeySpec; |
| import java.security.spec.X509EncodedKeySpec; |
| import java.util.Arrays; |
| import java.util.Base64; |
| |
| /** |
| * @test |
| * @bug 8242335 |
| * @summary OpenSSL generated compatibility test with RSASSA-PSS Java. |
| * @run main PSSKeyCompatibility |
| */ |
| public class PSSKeyCompatibility { |
| |
| private static final String ALGO = "RSASSA-PSS"; |
| private static final String OID = "1.2.840.113549.1.1.10"; |
| private static final String PROVIDER = "SunRsaSign"; |
| |
| public static void main(String[] args) { |
| |
| boolean result = true; |
| for (String algo : new String[]{ALGO, OID}) { |
| System.out.println("With : " + algo); |
| result &= validateCert(algo, PROVIDER, PUBLIC_256); |
| result &= validateCert(algo, PROVIDER, PUBLIC_384); |
| result &= validateCert(algo, PROVIDER, PUBLIC_512); |
| |
| result &= validatePrivate(algo, PROVIDER, PRIVATE); |
| } |
| if (!result) { |
| throw new RuntimeException("Some test cases failed"); |
| } |
| } |
| |
| private static boolean validatePrivate(String algorithm, String provider, |
| String type) { |
| |
| try { |
| KeyFactory kf = KeyFactory.getInstance(algorithm, provider); |
| PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec( |
| Base64.getMimeDecoder().decode(type)); |
| PrivateKey priv = kf.generatePrivate(privSpec); |
| |
| RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey) priv; |
| PrivateKey priv1 = kf.generatePrivate(new RSAPrivateCrtKeySpec( |
| crtKey.getModulus(), |
| crtKey.getPublicExponent(), |
| crtKey.getPrivateExponent(), |
| crtKey.getPrimeP(), |
| crtKey.getPrimeQ(), |
| crtKey.getPrimeExponentP(), |
| crtKey.getPrimeExponentQ(), |
| crtKey.getCrtCoefficient(), |
| crtKey.getParams() |
| )); |
| equals(priv, priv1); |
| } catch (NoSuchAlgorithmException | InvalidKeySpecException |
| | NoSuchProviderException e) { |
| e.printStackTrace(System.out); |
| return false; |
| } |
| System.out.println("PASSED - validatePrivate"); |
| return true; |
| } |
| |
| private static boolean validateCert(String algorithm, String provider, |
| String type) { |
| |
| try { |
| CertificateFactory cf = CertificateFactory.getInstance("X.509"); |
| Certificate cert = cf.generateCertificate( |
| new ByteArrayInputStream(type.getBytes())); |
| System.out.println(cert); |
| KeyFactory kf = KeyFactory.getInstance(algorithm, provider); |
| X509EncodedKeySpec pubSpec = kf.getKeySpec( |
| cert.getPublicKey(), X509EncodedKeySpec.class); |
| PublicKey pub = kf.generatePublic(pubSpec); |
| PublicKey pub1 = kf.generatePublic(new RSAPublicKeySpec( |
| ((RSAPublicKey) pub).getModulus(), |
| ((RSAPublicKey) pub).getPublicExponent(), |
| ((RSAPublicKey) pub).getParams())); |
| equals(cert.getPublicKey(), pub); |
| equals(pub, pub1); |
| } catch (CertificateException | NoSuchAlgorithmException |
| | InvalidKeySpecException | NoSuchProviderException e) { |
| e.printStackTrace(System.out); |
| return false; |
| } |
| System.out.println("PASSED - validateCert"); |
| return true; |
| } |
| |
| private static void equals(Key orig, Key gen) { |
| if (!orig.equals(gen) && orig.hashCode() != gen.hashCode() |
| && !Arrays.equals(orig.getEncoded(), gen.getEncoded())) { |
| throw new RuntimeException("Key mismatch found"); |
| } |
| } |
| |
| //rsa_pss_pss_sha256 |
| private static final String PRIVATE |
| = "MIIEvAIBADALBgkqhkiG9w0BAQoEggSoMIIEpAIBAAKCAQEAu1qb8PZ8vMrX08Gf\n" |
| + "y9mx7c5NHymdPIpdDvaiYkpRfYGXp3Jpx7A0Hq01QY0OUu+0sCd5IbiVoVGqM4cq\n" |
| + "r2e4eyYnbgJEF7Tg8Ipu70cOUCZLj/fYNAjvFjv4+lxQYRCZHUH+lWPDPtJWKELx\n" |
| + "iIsAL5tglfyrQrdWLaOiZKlJ49DrYKU6PYqELxdQ1lw3r8iBbgGJP2podGD0rMWw\n" |
| + "nGX4pl9C7dYA+FV2yDirpH+OMNGOqB5QCe2WcsMLMzLPxJxOpqU8lCuscXR0VZuV\n" |
| + "krgztGJcq4J0eqp05jvMWii4vW/KSIh9bndVmS2QIU7YArI8RMXtbSHdE0hXAkh+\n" |
| + "Phb6/QIDAQABAoIBAQC4gbJDKquLTYQhYXTaT4h/toSS5OuZfHXKz675d1ErdZ2B\n" |
| + "ZRaxdmDNuSxSYvSxTqm2NRmA0QRiu0cPudSaq12twdRg7VBbvGEt4lb/xA1fd2dA\n" |
| + "4AcGr6mtTuCSxqjN/oebnat3OalFS+VXfx3Yp3NGbxE+hHewm1b+WUELOwCunhYw\n" |
| + "WJxs5dR0APiqzknveFgkOSDRbMYhwN6ZIrAmZH0wkGI7ufssnp9LEVDkoQCaFHlW\n" |
| + "bUpBHV1YxMCgAD/Azoo7MtedoO/+qnu1h26VhMVMCQL1DymZAnWd5kXumP9PG9j9\n" |
| + "z2JwIdYc7wkLVoSHJmjuXn/Sa/X7YCTGNk5Qwp/tAoGBAPJIWN3b6FPasnAevD2O\n" |
| + "04l1nnNrjNmu7aMGTTH5CrDseI7y/nqbSC18pOivRLmvhkON26I/Gu8GPKBteZAV\n" |
| + "OHKPc4RM11nvv9CyN4yDp0g76pPXLPXRRN/HV0RfBkmaiE6rpS07ue8FDUZmqb9+\n" |
| + "T8LV2eCYL7gYnIxsctzEQ8tXAoGBAMX2H7wpZVqHlGW94FF2pLp82q2cP80PBD+Z\n" |
| + "TglUVHy957EGPqEzxAWf3saORMDXyme7o0eSHJ1tikNTqAb+//zg5JexNEZSv6cR\n" |
| + "trAxuUT7kgjdJaD2i2BjlJyGG6fiXHcxC8lBvnFiWrC+qihTKDPdwWXdEOwzqCdL\n" |
| + "0eBbKAvLAoGAKDjah/p6F3G3LeXsWkvb0nY0V/UC7SCdUvM43ZL6s2SOnyy4EqK0\n" |
| + "2NhYiEiQoEMDhzOFwum3Dvd6GSgThlf/hwVJqC0Zk1S6A2uSzUEOBG/uAZ03WZfk\n" |
| + "V0JAupkL8iw1dNoKEfhYZdXw3j8s7x2JIE9gXGjngyiS1L0sVHpAxwECgYB78csS\n" |
| + "23RLB0JhpU2yk6812ABu3LqRoEpPq6PRcYxogdpz2u4RrkCYKO2psd/YQgPHiRMF\n" |
| + "N7VU2AXOe61jm/sZEJHvbBLHyP2YFB4nGSrfxwc7J4Ns0ZCYbCDbE5hzN+Ye9oVj\n" |
| + "oBcmFKelq+sLzm0IdFqndY8n5HvvBqjEaS6cmwKBgQDM5VsMKnGuqy5pozamgABu\n" |
| + "/z3f8ATzPVr85LiEWP7qB9Y1JIFuTma3IVlULtab2S4rhrHqQNy6qA6Be9fKKPwE\n" |
| + "TCmM/SDdolcz2d0rC2VDO+pc1RPluDpB/Ag8aHkV58azQASHHvAKBckIe7fay2t2\n" |
| + "j4FaKzM/ieY3WSapIbjf3w=="; |
| |
| /* |
| * Certificate: Data: Version: 3 (0x2) |
| * Serial Number: 11:4c:35:8c:63:47:91:1d:c1:c8:0f:c2:6f:d0:bd:8b:8f:89:e3:6c |
| * Signature Algorithm: rsassaPss |
| * Hash Algorithm: sha256 |
| * Mask Algorithm: mgf1 with sha256 |
| * Salt Length: 0xDE |
| * Trailer Field: 0xBC (default) |
| * Issuer: CN = localhost |
| * Validity Not Before: Apr 8 06:01:37 2020 GMT |
| * Not After : Apr 3 06:01:37 2040 GMT |
| * Subject: CN = localhost |
| * Subject Public Key Info: Public |
| * Key Algorithm: rsassaPss |
| * RSA-PSS Public-Key: (2048 bit) |
| */ |
| private static final String PUBLIC_256 = "-----BEGIN CERTIFICATE-----\n" |
| + "MIIDaTCCAiCgAwIBAgIUe9ijWtZJGfoH6whOTEIc+J/T1vswPgYJKoZIhvcNAQEK\n" |
| + "MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC\n" |
| + "AgDeMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMDAzMTcwNjM4MDdaFw00MDAz\n" |
| + "MTIwNjM4MDdaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n" |
| + "A4IBDwAwggEKAoIBAQC7Wpvw9ny8ytfTwZ/L2bHtzk0fKZ08il0O9qJiSlF9gZen\n" |
| + "cmnHsDQerTVBjQ5S77SwJ3khuJWhUaozhyqvZ7h7JiduAkQXtODwim7vRw5QJkuP\n" |
| + "99g0CO8WO/j6XFBhEJkdQf6VY8M+0lYoQvGIiwAvm2CV/KtCt1Yto6JkqUnj0Otg\n" |
| + "pTo9ioQvF1DWXDevyIFuAYk/amh0YPSsxbCcZfimX0Lt1gD4VXbIOKukf44w0Y6o\n" |
| + "HlAJ7ZZywwszMs/EnE6mpTyUK6xxdHRVm5WSuDO0YlyrgnR6qnTmO8xaKLi9b8pI\n" |
| + "iH1ud1WZLZAhTtgCsjxExe1tId0TSFcCSH4+Fvr9AgMBAAGjUzBRMB0GA1UdDgQW\n" |
| + "BBSDV090I9jEWvpjZ7fgO+GGocVgaDAfBgNVHSMEGDAWgBSDV090I9jEWvpjZ7fg\n" |
| + "O+GGocVgaDAPBgNVHRMBAf8EBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n" |
| + "AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3gOCAQEAVl99\n" |
| + "g2F0H9YzEtvG5NjSGq8uCW5dLQd5DcXNfyfSLlUBwCTaZXncrc5/3DLYN1mWRQm2\n" |
| + "pCwmoGVzslwcLNENldTYogCc0Pc3YeG81wTBq0Tt6zS8RsDR3jhCFSDTVOjOoe0R\n" |
| + "kdYRd9d2pLg2ZOzAJXa6GLrFA+3Vv3dFFh8FhGB9CcVsyPQDzWhXQ0IwukHK+AMY\n" |
| + "6x1h12/CGQfrzBhrUtwbV+9iZN3lVsBYEFNKVz8Ca7H80YC4bsEHAHeR5nIUFk82\n" |
| + "kYuOBhcfC10oz+NdM1KbyAX8/4Uf7S3aBca27GTr1vP6tkmybonRHnZRoELNo1RQ\n" |
| + "wM0XPciACllEAJCVrQ==\n" |
| + "-----END CERTIFICATE-----"; |
| |
| /* |
| * Certificate: Data: Version: 3 (0x2) |
| * Serial Number: 32:f5:cf:23:71:d3:7f:16:10:5d:6e:c7:25:82:ee:7f:a8:ec:27:80 |
| * Signature Algorithm: rsassaPss |
| * Hash Algorithm: sha384 |
| * Mask Algorithm: mgf1 with sha384 |
| * Salt Length: 0xCE |
| * Trailer Field: 0xBC (default) |
| * Issuer: CN = localhost |
| * Validity Not Before: Apr 8 06:01:37 2020 GMT |
| * Not After : Apr 3 06:01:37 2040 GMT |
| * Subject: CN = localhost |
| * Subject Public Key Info: Public |
| * Key Algorithm: rsassaPss |
| * RSA-PSS Public-Key: (2048 bit) |
| */ |
| private static final String PUBLIC_384 = "-----BEGIN CERTIFICATE-----\n" |
| + "MIIDaTCCAiCgAwIBAgIUAeOnPMUidJHBqZbvhJWcH/05h0MwPgYJKoZIhvcNAQEK\n" |
| + "MDGgDTALBglghkgBZQMEAgKhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAICogQC\n" |
| + "AgDOMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMDAzMTcwNzI2MzFaFw00MDAz\n" |
| + "MTIwNzI2MzFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n" |
| + "A4IBDwAwggEKAoIBAQDPgUMdvdYOeVahvAp92RNG55plAlUyEdowNmIpEbyZOlEM\n" |
| + "Jc+7VqMt1K/+ZX1MkAGrFjV635p3c0NqI6qyv57cXA7VT92aYp9S0l4t7Cb2DQ6Y\n" |
| + "D+1jPNYTpYoMoI8ZPA486RGpnBtmRp9KRSkAoLS6AngCABE7OxuE0MrYKhbJ/8Lq\n" |
| + "Ss627FDXK+7aLCbEdLbr5G9BAIMEQDJAomHcqBMz5+EnEXWHc8drHFVIniHByFv3\n" |
| + "HmzDhFEMKCV9PbBXjgKdpMIAJsRXG3t1CBE/pEzILomgg3i4OHSUvEIzTApwTJvg\n" |
| + "UqtXi0UJqPohPViCQFeWLMa2N0pOAx1FMfdJIutLAgMBAAGjUzBRMB0GA1UdDgQW\n" |
| + "BBQBEi9rWGXrZObncP4StBKXB3baODAfBgNVHSMEGDAWgBQBEi9rWGXrZObncP4S\n" |
| + "tBKXB3baODAPBgNVHRMBAf8EBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n" |
| + "AWUDBAICoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAqIEAgIAzgOCAQEADIQ6\n" |
| + "2ktTyS9+POWWe8yGEqW/q9DxL0NAqc0n4rYm5hs/8MKk1NMaqIku2xjE3T/16iFj\n" |
| + "3WEtj51yoSIUN0VxXPUoj3Yv5xR03huBk8gAwTpQc9psRQuGpLt9BBq0dyErQ8XR\n" |
| + "88SshQRpDEZ2yR4Tb+U5XfbWe70uCGfeG3iDMtZPAx2GnYBD+u3JaN/m7sr0cB8V\n" |
| + "Y8GuxWNh40aaIR0iaWbIC4b9N3wYDOa1yd8PqAKnLIs1F5CinJM6i5LmbkQpd+cK\n" |
| + "t13iaFYN26HuD3AywDQDvyYTwV7q5jcoEGAd35+pmKCdatEHlo0uLzbTGZw31Gfo\n" |
| + "BeSEh3vmXa1Q7SOpTQ==\n" |
| + "-----END CERTIFICATE-----"; |
| /* |
| * Certificate: Data: Version: 3 (0x2) |
| * Serial Number: 32:f5:cf:23:71:d3:7f:16:10:5d:6e:c7:25:82:ee:7f:a8:ec:27:80 |
| * Signature Algorithm: rsassaPss |
| * Hash Algorithm: sha512 |
| * Mask Algorithm: mgf1 with sha512 |
| * Salt Length: 0xBE |
| * Trailer Field: 0xBC (default) |
| * Issuer: CN = localhost |
| * Validity Not Before: Apr 8 06:01:37 2020 GMT |
| * Not After : Apr 3 06:01:37 2040 GMT |
| * Subject: CN = localhost |
| * Subject Public Key Info: Public |
| * Key Algorithm: rsassaPss |
| * RSA-PSS Public-Key: (2048 bit) |
| */ |
| private static final String PUBLIC_512 = "-----BEGIN CERTIFICATE-----\n" |
| + "MIIDaTCCAiCgAwIBAgIUMvXPI3HTfxYQXW7HJYLuf6jsJ4AwPgYJKoZIhvcNAQEK\n" |
| + "MDGgDTALBglghkgBZQMEAgOhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIDogQC\n" |
| + "AgC+MBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMDAzMTcwNzI4MjZaFw00MDAz\n" |
| + "MTIwNzI4MjZaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n" |
| + "A4IBDwAwggEKAoIBAQCzuWpxs8c0JPgSykN9LM+2k0RlexrxCAlkgHRpfLI8XpV4\n" |
| + "Ak3hx9a045Ym1yyskNw7FjZVfWNgmx5Z8qQZvBykCL2iwDoMLEfoJTcE3cZEppaz\n" |
| + "3PqRoOVhuUGqA4jOW8WGbMi7aq/9UfTQGikxMBD7aS/ExILtAcd0N173ZARWcP0s\n" |
| + "68bRDLmTYAclZTWDZee0gAl8MHMnXSFFPotSbZOEWz4RqhpCa49tcx1BHgto3lyc\n" |
| + "ofzOerHpilZ/zAqOVRF2qHoZKlYTsTcSK0mE2MAfV7fk40qHYkyKbKLJVj8L8Lmc\n" |
| + "AFUNTx07bLYymgtqa07ei+kaVTJdlzDWiREgN8MNAgMBAAGjUzBRMB0GA1UdDgQW\n" |
| + "BBRlbX8E0L89iIOjkgLpbL/WSbuxmTAfBgNVHSMEGDAWgBRlbX8E0L89iIOjkgLp\n" |
| + "bL/WSbuxmTAPBgNVHRMBAf8EBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n" |
| + "AWUDBAIDoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCA6IEAgIAvgOCAQEAaRTy\n" |
| + "CmQxYkS5qCGQeJun/lFVLVE83Sl2kCBaJCMJdBYw38H+6DknJx/sjZwD1vO+OGj6\n" |
| + "1yyzQF1dv2Y5qOUrJIgw1ODkxTLMCrdotVqClazX02VGvyRe7efbjii96/9hqtxt\n" |
| + "TZwN7+8wUX6sP91z1vXVYD5sfl/qum/cWAVJEyw32h7RpUeB0rCJcIUrNqnbBziw\n" |
| + "SRkZof1Q2b02JRO0Pb3jV3H1MV5Agt3cFCCdsmvVq595rmYRwVMtyzCxXHb8jm+N\n" |
| + "8Fzhl9pxCCd4KIOGDAvngFZAloVsCHt+BG8jPhSxOldnFM7xGrGss2lLJnmf3YSe\n" |
| + "EPDF7NvA9wKPz4oyRg==\n" |
| + "-----END CERTIFICATE-----"; |
| |
| } |