diff --git a/test/jdk/java/security/PEM/PEMData.java b/test/jdk/java/security/PEM/PEMData.java index e1f32cdbb7c..2c8c60fcccc 100644 --- a/test/jdk/java/security/PEM/PEMData.java +++ b/test/jdk/java/security/PEM/PEMData.java @@ -27,6 +27,7 @@ import javax.crypto.EncryptedPrivateKeyInfo; import java.security.DEREncodable; import java.security.KeyPair; import java.security.PEMRecord; +import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.interfaces.*; import java.util.ArrayList; @@ -45,7 +46,7 @@ class PEMData { KwDdi3cNwu7YYD/QtJ+9+AEBdoqhRANCAASL+REY4vvAI9M3gonaml5K3lRgHq5w +OO4oO0VNduC44gUN1nrk7/wdNSpL+xXNEX52Dsff+2RD/fop224ANvB -----END PRIVATE KEY----- - """, KeyPair.class); + """, KeyPair.class, "SunEC"); public static final Entry rsapriv = new Entry("rsapriv", """ @@ -65,7 +66,68 @@ class PEMData { 6onPAs4hkm+63dfzCojvEkALevO8J3OVX7YS5q9J1r75wDn60Ob0Zh+iiorpx8Ob WqcWcoJqfdLEyBT+ -----END PRIVATE KEY----- - """, RSAPrivateKey.class); + """, RSAPrivateKey.class, "SunRsaSign"); + + public static final Entry rsaCrtCoefZeroPriv = new Entry("rsaCrtCoefZeroPriv", + """ + -----BEGIN RSA PRIVATE KEY----- + MIIEIwIBAAKCAQEAuZAPiPMlA5R0oOIbxbq+gOmBRcvptIT+0pmG6rZ6H//r7A/Z + MRwen0iO2GuhlyUgOk9Fja/TMBrNX99boVDEZtL4oxRTJibdLNjfQqPeFhs3NNvv + CJJEGD91Dq/fGbWv1TMZcEywqqYSdERDEA7yluw87I7YZc9kXVBwRw5AedvoXOL/ + z5yPjK8W7FTCLHSVKiD/X3P3ZX9TmFjTIbRH15Do5sRxsPdrZczYjWdXFXNQEUuF + sVFGHFbB/AJiZlGYqMU+hEIErE35sHrKpZYkj9YovYQe0SBJyuROPl8wmz0Cd69s + rhg142Qf23RPhclBuCNAQQOkefeCppg4IFFh7QIDAQABAoIBADlKHlm4Q7m2uElB + dbSWwqEXNnefjJBUrT3E84/8dXjysNppTDNqzJN9uchcdn+tESWfeshTO97yr2yF + j4se3fwm72ed60vwnMFvVYKECBmIHoO90S8yxT49PT0jFDyiSN6IT7bJnpOZAUKP + HqtTCheJaQfZ1DqejIx4vKlbX5GfShwPQV0Q7KeKnfxhryhAbM5Y5UT8grQGBQU7 + aQUZuasQV10APVRaz39VU8/hzBc081LR3O0tjnZcrMAQ7ANsP9Gu3My04cnQ5WBo + P8uCCaSPSkrzCvjd9YYkdnwXMbVCfALOa+MxBddMi4IQG0qI28Bpw6dkKziPxage + KcAQnAsCgYEA0/CwzUlyrG6f+FF3uAvPVn/jEhWatJb7Me7lkhO3suV92brb1pQo + 1W1jHdx0OqMuCVfIJ4bXkTwKuvLQGcWJzNWUVh4Tij/ZAV0Ssw2cKbBSCQGNIFsx + Ux0V9tDSYJsEdk+Y5grloDNJokYYCCpF5bz/6QYmX+t3yzjyVSvcNeMCgYEA4COU + ezUXKLSWD+jJZXpS5yopB7oXAg7mmonlc1DRuaIxspwBrbXPLQ/neN8Sefpz9Nxn + 4ksPxGbLnJh0wGCnxSu0Qfn4eNVSsulag4IQmbCO2UBsdXNCJB5KlDpRlVhvvviH + Zpz2Dkdx+itLf1EV841MCtPAHZJwrs6i6JntEe8CgYEAgJYdjs+rJXcQ04YKDr4L + k72PtR8qd7rKuObqnhAcegvGqV03mB7YD3WIl0tzsUfj3INHysOC8njtQbOkEp7J + Fl/W2dDxpgVK0gr4F26AesKhYxlv2Fu7t2OEOfVETpx+vpFYgOnHm8TCPhQs7HdJ + ZTOgSG8UxUmFquToEkjEGGUCgYB6AMP8wKxHeuzH4iVl+EySCa/lxdRqSWQasH7V + 4yMVkYTNvP9o57LKy4Jql7n97Wca3LIrSkJd3LpuFcpPQQ1xVNW8p+0pEK0AN+cN + +ElC7wkCln+y+rcA5AAiaRApY8cHw04oe72vjhIrY0+oEKILPVkr95D2R9TQQigI + xmh1vwIBAA== + -----END RSA PRIVATE KEY----- + """, RSAPrivateKey.class, "SunRsaSign"); + + public static final Entry rsapsspriv = new Entry("rsapsspriv", + """ + -----BEGIN PRIVATE KEY----- + MIIEugIBADALBgkqhkiG9w0BAQoEggSmMIIEogIBAAKCAQEAn3qFQtvj9JVqVPRh + mMMRyT17GiUY+NWOwUHx5bHqfhlHJoCllctSU/YXzrH4Da1w7sSeaMmAKYMW4X5k + rn9hnKOhgHnm2nkZBaVNQeyrseuDnfwWtLXjnj8rEKpgf9UPRUeXGRSoAb1qpwBf + epFtLSKZrzswZY2u2UEUGJERABi6Qp+cIZ8uXzBkIsMgrhb50xsdysZ9+qq95z0i + N1vh/V+Yi2fYpSYVDE8aMWdpvs0oWGvoLQjRgElJx/SknndAfLD42HPYZyyXevyJ + RgUf+NP0V7c+UtE7m7pgMs1hhxHSmUNdfH9GnOSg9m3+L3WqhaNNWB4aKMqFyhlM + EsAuawIDAQABAoIBAAMJ9yXIgeYEaN54j67fsg7nJIQ228HLc/5xGWvFQaYofidu + K87twm0GKKWlf4gR24U5QEQtPst2YNu9fav+PRJv4yEgcYqNOdxWg4veN4Fa7wr2 + JZ/zmARJHjLMRFgl67YSwKmCMBdkZXa24PA5et6cJQM7+gFIELe5b+lt7j3VsxQ7 + JpTJyp3I73lXcJrzcb/OCTxobFPLtkVSgKUNwae26xlNqXX4fQfLp99LHGnkmG3k + Wlzjs6dUi4fl4yLAJYMxEwxQbSbmY66ZKnM4SkT/YHx67gyJw2CMRp4FQDg94Sor + 0IDDKiSMGzcjuCuUl27/qTuv+iMgCqNB7CSPXtECgYEAvqN8ZuZXeUKz4tn6wxJk + k1utCl3pSM5PLMF4J43uvX49HF1i3svXrwxzJqug6kPXvB7cuB6U2DFIM3lh2jNE + u2w0U/5zVz2yEI9EaRjnOXePLsSWjOiC+5MGTafJWy5vZ8+zaWL9tjtUH5hsg1cB + ZMlXtWrI+AmAUAv6FFDZaHECgYEA1igXzRMGgXAT+YX0wdZQcRMy9jD5WIYIiCex + 6/WRE2LDM855ZBwTU5gyqZC2MWC3yn1ASDraxKdH1m3872Q0NVJfsOaLvBk1HuPk + dlSHRKO2GeO9m5/YzrZm9jpGs0IH6DKOah/t0aCd2CFxt6qef2wOUmXTCK6tyCXN + EiUmEpsCgYAMue85E1Ftl+VYVILn+Ndb+ve/RGupX5RrgXLa+R+h6MZ9mUJbazI3 + zlX1k+mHGgZR2aGUbP40vH18ajL9FQUWme+YV9ktTsIPVvETLwVokbGuRpNiTrdH + whXeoz/O5Xesb3Ijq+cR/j3sagl8bxd5ufMv+jP2UvQM4+/K4WbSEQKBgGuZeVvw + UzR1u5ODWpaJt6EYpGJN+PohXegLCbokh9/Vn35IH3XNJWi677mCnAfzMGTsyX+B + Eqn74nw6hvtAvXqNCMc5DrxTbf03Q3KwxcYW+0fGxV2L0sMJonHUlfE7G/3uaN+p + azQIH0aYhypg74HWKNv9jSqvmWEWnRKg16BBAoGAGLAqCRCP8wxqRVZZjhUJ+5JN + b6PrykDxCKhlA6JqZKuCYzvXhLABq/7miNDg0CmRREl+yKXlkEoFl4g9LtP7wfjX + n4us/WNmh+GPZYxlCJSNRTjgk7pm5TjVH5YWURDEnjIHZ7yxbAFlvNUhI1mF5g97 + KVcB4fjBitP1h8P+MoY= + -----END PRIVATE KEY----- + """, RSAPrivateKey.class, "SunRsaSign"); public static final Entry rsaprivbc = new Entry("rsaprivbc", """ @@ -85,14 +147,14 @@ class PEMData { 6onPAs4hkm+63dfzCojvEkALevO8J3OVX7YS5q9J1r75wDn60Ob0Zh+iiorpx8Ob WqcWcoJqfdLEyBT+ -----END PRIVATE KEY----- - """, RSAPrivateKey.class); + """, RSAPrivateKey.class, "SunRsaSign"); public static final Entry ec25519priv = new Entry("ed25519priv", """ -----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIFFZsmD+OKk67Cigc84/2fWtlKsvXWLSoMJ0MHh4jI4I -----END PRIVATE KEY----- - """, EdECPrivateKey.class); + """, EdECPrivateKey.class, "SunEC"); public static final Entry rsapub = new Entry("rsapub", """ @@ -102,7 +164,20 @@ class PEMData { MtJpIPIXynEqRy2mIw2GrKTtu3dqrW+ndarbD6D4yRY1hWHluiuOtzhxuueCuf9h XCYEHZS1cqd8wokFPwIDAQAB -----END PUBLIC KEY----- - """, RSAPublicKey.class); + """, RSAPublicKey.class, "SunRsaSign"); + + public static final Entry rsapsspub = new Entry("rsapsspub", + """ + -----BEGIN PUBLIC KEY----- + MIIBIDALBgkqhkiG9w0BAQoDggEPADCCAQoCggEBAJ96hULb4/SValT0YZjDEck9 + exolGPjVjsFB8eWx6n4ZRyaApZXLUlP2F86x+A2tcO7EnmjJgCmDFuF+ZK5/YZyj + oYB55tp5GQWlTUHsq7Hrg538FrS1454/KxCqYH/VD0VHlxkUqAG9aqcAX3qRbS0i + ma87MGWNrtlBFBiREQAYukKfnCGfLl8wZCLDIK4W+dMbHcrGffqqvec9Ijdb4f1f + mItn2KUmFQxPGjFnab7NKFhr6C0I0YBJScf0pJ53QHyw+Nhz2Gcsl3r8iUYFH/jT + 9Fe3PlLRO5u6YDLNYYcR0plDXXx/RpzkoPZt/i91qoWjTVgeGijKhcoZTBLALmsC + AwEAAQ== + -----END PUBLIC KEY----- + """, RSAPublicKey.class, "SunRsaSign"); public static final Entry rsapubbc = new Entry("rsapubbc", """ @@ -112,14 +187,14 @@ class PEMData { MtJpIPIXynEqRy2mIw2GrKTtu3dqrW+ndarbD6D4yRY1hWHluiuOtzhxuueCuf9h XCYEHZS1cqd8wokFPwIDAQAB -----END PUBLIC KEY----- - """, RSAPublicKey.class); + """, RSAPublicKey.class, "SunRsaSign"); public static final Entry ecsecp256pub = new Entry("ecsecp256pub", """ -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi/kRGOL7wCPTN4KJ2ppeSt5UYB6u cPjjuKDtFTXbguOIFDdZ65O/8HTUqS/sVzRF+dg7H3/tkQ/36KdtuADbwQ== -----END PUBLIC KEY----- - """, ECPublicKey.class); + """, ECPublicKey.class, "SunEC"); // EC key with explicit parameters -- Not currently supported by SunEC public static final String pubec_explicit = """ @@ -152,7 +227,7 @@ class PEMData { P4c4mySRy5N3plFQUp3pIB7wqshi1t6hkdg7gRGjMtJpIPIXynEqRy2mIw2GrKTtu3dqrW+ndarb D6D4yRY1hWHluiuOtzhxuueCuf9hXCYEHZS1cqd8wokFPwIDAQAB -----END PRIVATE KEY----- - """, KeyPair.class); + """, KeyPair.class, "SunRsaSign"); public static final Entry oasrfc8410 = new Entry("oasrfc8410", """ @@ -161,7 +236,24 @@ class PEMData { oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB Z9w7lshQhqowtrbLDFw4rXAxZuE= -----END PRIVATE KEY----- - """, KeyPair.class); + """, KeyPair.class, "SunEC"); + + public static final Entry oasxdh = new Entry("oasxdh", + """ + -----BEGIN PRIVATE KEY----- + MFECAQEwBQYDK2VuBCIEIIrMS7w5YxuBTyPFiaFvp6ILiGET7wY9ybk7Qqhe3hSq + gSEAB7ODPxRePrPnJMaj3f47blVx6c5bfxcllQzLp4bW5x4= + -----END PRIVATE KEY----- + """, KeyPair.class, "SunEC"); + + public static final Entry oasec = new Entry("oasec", + """ + -----BEGIN PRIVATE KEY----- + MIGFAgEBMBMGByqGSM49AgEGCCqGSM49AwEHBCcwJQIBAQQgkGEVbZE1yAiO11Ya + eepcrBQL+HpVE4fy0V6jbpJcmkiBQgAERCqYYmN9uNT9Z1O2Z2VC3Zag9eUAhz7G + p8DqC21VrIgpqVQ4BrcWsieNg9fSd4N2hgfMpk9PCQwJQ8ifCMiBVQ== + -----END PRIVATE KEY----- + """, KeyPair.class, "SunEC"); public static final Entry rsaOpenSSL = new Entry("rsaOpenSSL", """ @@ -192,7 +284,7 @@ class PEMData { EcgIOtkvoTrJ9Cquvuj+O7/d2yNoH0SZQ4IYJKq47/Z4kKhwXzJnBCCCBKgkjfub RTQSNnSEgTaBD29l7FrhNRHX9lIKFZ23caCTBS6o3q3+KgPbq7ao -----END RSA PRIVATE KEY----- - """, RSAPrivateKey.class); + """, RSAPrivateKey.class, "SunRsaSign"); static final Entry ed25519ep8 = new Entry("ed25519ep8", """ @@ -202,11 +294,11 @@ class PEMData { vdMyi46+Dw7cOjwEQLtx5ME0NOOo7vlCGm3H/4j+Tf5UXrMb1UrkPjqc8OiLbC0n IycFtI70ciPjgwDSjtCcPxR8fSxJPrm2yOJsRVo= -----END ENCRYPTED PRIVATE KEY----- - """, EdECPrivateKey.class, "fish".toCharArray()); + """, EdECPrivateKey.class, "SunEC", "fish".toCharArray()); // This is not meant to be decrypted and to stay as an EKPI static final Entry ed25519ekpi = new Entry("ed25519ekpi", - ed25519ep8.pem(), EncryptedPrivateKeyInfo.class, null); + ed25519ep8.pem(), EncryptedPrivateKeyInfo.class, "SunEC", null); static final Entry rsaCert = new Entry("rsaCert", """ @@ -237,7 +329,7 @@ class PEMData { 8gOYV33zkPhziWJt4uFMFIi7N2DLEk5UVZv1KTLZlfPl55DRs7j/Sb4vKHpB17AO meVknxVvifDVY0TIz57t28Accsk6ClBCxNPluPU/8YLGAZJYsdDXjGcndQ13s5G7 -----END CERTIFICATE----- - """, X509Certificate.class); + """, X509Certificate.class, "SUN"); static final Entry ecCert = new Entry("ecCert", """ @@ -249,7 +341,68 @@ class PEMData { lU3G9QAwCgYIKoZIzj0EAwIDSAAwRQIgMwYld7aBzkcRt9mn27YOed5+n0xN1y8Q VEcFjLI/tBYCIQDU3szDZ/PK2mUZwtgQxLqHdh+f1JY0UwQS6M8QUvoDHw== -----END CERTIFICATE----- - """, X509Certificate.class); + """, X509Certificate.class, "SUN"); + + private static final Entry rsaCrl = new Entry("rsaCrl", + """ + -----BEGIN X509 CRL----- + MIIBRTCBrwIBATANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJVUzEaMBgGA1UE + ChMRVGVzdCBDZXJ0aWZpY2F0ZXMxITAfBgNVBAMTGEJhc2ljIEhUVFAgVVJJIFBl + ZXIgMSBDQRcNMDUwNjAzMjE0NTQ3WhcNMTUwNjAxMjE0NTQ3WqAvMC0wHwYDVR0j + BBgwFoAUa+bxcvx1zVdUhvIEd9hcfbmFdw4wCgYDVR0UBAMCAQEwDQYJKoZIhvcN + AQEFBQADgYEAZ+21yt1pJn2FU6vBwpFtAKVeBCCCqJVFiRxT84XbUw0BpLrCFvlk + FOo6tC95aoV7vPGwOEyUNbKJJOCzLliIwV1PPfgZQV20xohSIPISHdUjmlyttglv + AuEvltGnbP7ENxw18HxvM20XmHz+akuFu6npI6MkBjfoxvlq1bcdTrI= + -----END X509 CRL----- + """, X509CRL.class, "SUN"); + + // Few random manipulated Base64 characters in PEM content + private static final Entry invalidDer = new Entry("invalidDER", """ + -----BEGIN PRIVATE KEY----- + MIICeAIBADANBhkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOtjMnCzPy4jCeZb + OdOvmvU3jl7+cvPFgL5MfqDCM5a8yI0yImg/hzibJJHLk3emUVBSnekgHvCqyGLW + 3qGR2DuBEaMy0mkg8hfKcSpHLaYjDYaspO27d2qtb6d1qtsPoPjJFjWFYeW6K463 + OHG654K5/2FcJgQdlLVyp3zCiQU/AgMBAAECgYEAwNkDkTv5rlX8nWLuLJV5kh/T + H9a93SRZxw8qy5Bv7bZ7ZNfHP7uUkHbi7iPojKWRhwo43692SdzR0dCSk7LGgN9q + CYvndsYR6gifVGBi0WF+St4+NdtcQ3VlNdsojy2BdIx0oC+r7i3bn+zc968O/kI+ + EgdgrMcjjFqyx6tMHpECQQD8TYPKGHyN7Jdy28llCoUX/sL/yZ2vIi5mnDAFE5ae + KZQSkNAXG+8i9Qbs/Wdd5S3oZDqu+6DBn9gib80pYY05AkEA7tY59Oy8ka7nBlGP + g6Wo1usF2bKqk8vjko9ioZQay7f86aB10QFcAjCr+cCUm16Lc9DwzWl02nNggRZa + Jz8eNwJBAO+1zfLjFOPb14F/JHdlaVKE8EwKCFDuztsapd0M4Vtf8Zk6ERsDpU63 + Ml9T2zOwnM9g+whpdjDAZ59ATdJ1JrECQQDReJQ2SxeL0lGPCiOLu9RcQp7L81aF + 79G1bgp8WlAyEjlAkloiqEWRKiz7DDuKFR7Lwhognng9S+n87aS+PS57AkBh75t8 + 6onPAs4hkm+63dfzCojvEkALevO8J3OVX7YS5q9J1r75wDn60Ob0Zh+iiorpx8Ob + WqcWcoJqfdLEyBT+ + -----END PRIVATE KEY----- + """, DEREncodable.class, null); + + private static final Entry invalidPEM = new Entry("invalidPEM", """ + -----BEGIN INVALID PEM----- + MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBVS52ZSKZ0oES7twD2 + GGwRIVu3uHlGIwlu0xzFe7sgIPntca2bHfYMhgGxrlCm0q+hZANiAAQNWgwWfLX8 + 8pYVjvwbfvDF9f+Oa9w6JjrfpWwFAUI6b1OPgrNUh+yXtUXnQNXnfUcIu0Os53bM + """, DEREncodable.class, null); + + private static final Entry invalidHeader = new Entry("invalidHeader", """ + ---BEGIN PRIVATE KEY--- + MC4CAQAwBQYDK2VwBCIEIFFZsmD+OKk67Cigc84/2fWtlKsvXWLSoMJ0MHh4jI4I + -----END PRIVATE KEY----- + """, DEREncodable.class, null); + + private static final Entry invalidFooter = new Entry("invalidFooter", """ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIFFZsmD+OKk67Cigc84/2fWtlKsvXWLSoMJ0MHh4jI4I + ---END PRIVATE KEY--- + """, DEREncodable.class, null); + + private static final Entry incorrectFooter = new Entry("incorrectFooter", """ + -----BEGIN PRIVATE KEY----- + MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBVS52ZSKZ0oES7twD2 + GGwRIVu3uHlGIwlu0xzFe7sgIPntca2bHfYMhgGxrlCm0q+hZANiAAQNWgwWfLX8 + 8pYVjvwbfvDF9f+Oa9w6JjrfpWwFAUI6b1OPgrNUh+yXtUXnQNXnfUcIu0Os53bM + 8fTqPkQl6RyWEDHeXqJK8zTBHMeBq9nLfDPSbzQgLDyC64Orn0D8exM= + -----END PUBLIC KEY----- + """, DEREncodable.class, null); // EC cert with explicit parameters -- Not currently supported by SunEC static final String ecCertEX = """ @@ -280,7 +433,7 @@ class PEMData { 8pYVjvwbfvDF9f+Oa9w6JjrfpWwFAUI6b1OPgrNUh+yXtUXnQNXnfUcIu0Os53bM 8fTqPkQl6RyWEDHeXqJK8zTBHMeBq9nLfDPSbzQgLDyC64Orn0D8exM= -----END PRIVATE KEY----- - """, KeyPair.class); + """, KeyPair.class, "SunEC"); public static final Entry ecCSR = new Entry("ecCSR", """ @@ -297,7 +450,7 @@ class PEMData { MQYMBGZpc2gwCgYIKoZIzj0EAwIDRwAwRAIgUBTdrMDE4BqruYRh1rRyKQBf48WR kIX8R4dBK9h1VRcCIEBR2Mzvku/huTbWTwKVlXBZeEmwIlxKwpRepPtViXcW -----END CERTIFICATE REQUEST----- - """, PEMRecord.class); + """, PEMRecord.class, "SunEC"); public static final String preData = "TEXT BLAH TEXT BLAH" + System.lineSeparator(); @@ -318,39 +471,41 @@ class PEMData { MQYMBGZpc2gwCgYIKoZIzj0EAwIDRwAwRAIgUBTdrMDE4BqruYRh1rRyKQBf48WR kIX8R4dBK9h1VRcCIEBR2Mzvku/huTbWTwKVlXBZeEmwIlxKwpRepPtViXcW -----END CERTIFICATE REQUEST----- - """ + postData, PEMRecord.class); + """ + postData, PEMRecord.class, "SunEC"); final static Pattern CR = Pattern.compile("\r"); final static Pattern LF = Pattern.compile("\n"); final static Pattern LSDEFAULT = Pattern.compile(System.lineSeparator()); - public record Entry(String name, String pem, Class clazz, char[] password, + public record Entry(String name, String pem, Class clazz, String provider, char[] password, byte[] der) { - public Entry(String name, String pem, Class clazz, char[] password, + public Entry(String name, String pem, Class clazz, String provider, char[] password, byte[] der) { this.name = name; this.pem = pem; this.clazz = clazz; + this.provider = provider; this.password = password; - if (pem != null && pem.length() > 0) { + if (pem != null && pem.length() > 0 && + !name.contains("incorrect") && !name.contains("invalid")) { String[] pemtext = pem.split("-----"); this.der = Base64.getMimeDecoder().decode(pemtext[2]); } else { this.der = null; } } - Entry(String name, String pem, Class clazz, char[] password) { - this(name, pem, clazz, password, null); + Entry(String name, String pem, Class clazz, String provider, char[] password) { + this(name, pem, clazz, provider, password, null); } - Entry(String name, String pem, Class clazz) { - this(name, pem, clazz, null, null); + Entry(String name, String pem, Class clazz, String provider) { + this(name, pem, clazz, provider, null, null); } public Entry newClass(String name, Class c) { - return new Entry(name, pem, c, password); + return new Entry(name, pem, c, provider, password); } public Entry newClass(Class c) { @@ -360,20 +515,20 @@ class PEMData { Entry makeCRLF(String name) { return new Entry(name, Pattern.compile(System.lineSeparator()).matcher(pem).replaceAll("\r\n"), - clazz, password()); + clazz, provider, password()); } Entry makeCR(String name) { return new Entry(name, Pattern.compile(System.lineSeparator()).matcher(pem).replaceAll("\r"), - clazz, password()); + clazz, provider, password()); } Entry makeNoCRLF(String name) { return new Entry(name, LF.matcher(CR.matcher(pem).replaceAll("")). replaceAll(""), - clazz, password()); + clazz, provider, password()); } } @@ -401,10 +556,12 @@ class PEMData { static { pubList.add(rsapub); + pubList.add(rsapsspub); pubList.add(rsapubbc); pubList.add(ecsecp256pub.makeCR("ecsecp256pub-r")); pubList.add(ecsecp256pub.makeCRLF("ecsecp256pub-rn")); privList.add(rsapriv); + privList.add(rsapsspriv); privList.add(rsaprivbc); privList.add(ecsecp256); privList.add(ecsecp384); @@ -413,9 +570,12 @@ class PEMData { privList.add(rsaOpenSSL); oasList.add(oasrfc8410); oasList.add(oasbcpem); + oasList.add(oasec); + oasList.add(oasxdh); certList.add(rsaCert); certList.add(ecCert); + certList.add(rsaCrl); entryList.addAll(pubList); entryList.addAll(privList); @@ -429,6 +589,11 @@ class PEMData { failureEntryList.add(new Entry("emptyPEM", "", DEREncodable.class, null)); failureEntryList.add(new Entry("nullPEM", null, DEREncodable.class, null)); + failureEntryList.add(incorrectFooter); + failureEntryList.add(invalidPEM); + failureEntryList.add(invalidDer); + failureEntryList.add(invalidHeader); + failureEntryList.add(invalidFooter); } static void checkResults(PEMData.Entry entry, String result) { diff --git a/test/jdk/java/security/PEM/PEMDecoderTest.java b/test/jdk/java/security/PEM/PEMDecoderTest.java index 2ee9d1a69b3..90d67af2f8d 100644 --- a/test/jdk/java/security/PEM/PEMDecoderTest.java +++ b/test/jdk/java/security/PEM/PEMDecoderTest.java @@ -26,6 +26,7 @@ /* * @test * @bug 8298420 + * @library /test/lib * @modules java.base/sun.security.pkcs * java.base/sun.security.util * @summary Testing basic PEM API decoding @@ -37,23 +38,27 @@ import java.io.*; import java.lang.Class; import java.nio.charset.StandardCharsets; import java.security.*; +import java.security.cert.CertificateEncodingException; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.security.interfaces.*; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; +import java.security.spec.*; import java.util.*; import java.util.Arrays; +import jdk.test.lib.Asserts; +import sun.security.pkcs.PKCS8Key; import sun.security.util.Pem; public class PEMDecoderTest { static HexFormat hex = HexFormat.of(); - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws Exception { System.out.println("Decoder test:"); - PEMData.entryList.forEach(PEMDecoderTest::test); + PEMData.entryList.forEach(entry -> test(entry, false)); + System.out.println("Decoder test withFactory:"); + PEMData.entryList.forEach(entry -> test(entry, true)); System.out.println("Decoder test returning DEREncodable class:"); PEMData.entryList.forEach(entry -> test(entry, DEREncodable.class)); System.out.println("Decoder test with encrypted PEM:"); @@ -95,7 +100,11 @@ public class PEMDecoderTest { System.out.println("Check a Signature/Verify op is successful:"); PEMData.privList.forEach(PEMDecoderTest::testSignature); - PEMData.oasList.forEach(PEMDecoderTest::testSignature); + PEMData.oasList.stream().filter(e -> !e.name().endsWith("xdh")) + .forEach(PEMDecoderTest::testSignature); + + System.out.println("Checking if decode() returns a PKCS8Key and can generate a pub"); + PEMData.oasList.forEach(PEMDecoderTest::testPKCS8Key); System.out.println("Checking if ecCSR:"); test(PEMData.ecCSR); @@ -182,6 +191,10 @@ public class PEMDecoderTest { } catch (Exception e) { throw new AssertionError("error getting key", e); } + testCertTypeConverter(PEMData.ecCert); + + System.out.println("Decoder test testCoefZero:"); + testCoefZero(PEMData.rsaCrtCoefZeroPriv); } static void testInputStream() throws IOException { @@ -231,6 +244,24 @@ public class PEMDecoderTest { throw new AssertionError("Failed"); } + // test that X509 CERTIFICATE is converted to CERTIFICATE in PEM + static void testCertTypeConverter(PEMData.Entry entry) throws CertificateEncodingException { + String certPem = entry.pem().replace("CERTIFICATE", "X509 CERTIFICATE"); + Asserts.assertEqualsByteArray(entry.der(), + PEMDecoder.of().decode(certPem, X509Certificate.class).getEncoded()); + + certPem = entry.pem().replace("CERTIFICATE", "X.509 CERTIFICATE"); + Asserts.assertEqualsByteArray(entry.der(), + PEMDecoder.of().decode(certPem, X509Certificate.class).getEncoded()); + } + + // test that when the crtCoeff is zero, the key is decoded but only the modulus and private + // exponent are used resulting in a different der + static void testCoefZero(PEMData.Entry entry) { + RSAPrivateKey decoded = PEMDecoder.of().decode(entry.pem(), RSAPrivateKey.class); + Asserts.assertNotEqualsByteArray(decoded.getEncoded(), entry.der()); + } + static void testPEMRecord(PEMData.Entry entry) { PEMRecord r = PEMDecoder.of().decode(entry.pem(), PEMRecord.class); String expected = entry.pem().split("-----")[2].replace(System.lineSeparator(), ""); @@ -333,13 +364,26 @@ public class PEMDecoderTest { // Change the Entry to use the given class as the expected class returned static DEREncodable test(PEMData.Entry entry, Class c) { - return test(entry.newClass(c)); + return test(entry.newClass(c), false); } // Run test with a given Entry static DEREncodable test(PEMData.Entry entry) { + return test(entry, false); + } + + // Run test with a given Entry + static DEREncodable test(PEMData.Entry entry, boolean withFactory) { + System.out.printf("Testing %s %s%n", entry.name(), entry.provider()); try { - DEREncodable r = test(entry.pem(), entry.clazz(), PEMDecoder.of()); + PEMDecoder pemDecoder; + if (withFactory) { + Provider provider = Security.getProvider(entry.provider()); + pemDecoder = PEMDecoder.of().withFactory(provider); + } else { + pemDecoder = PEMDecoder.of(); + } + DEREncodable r = test(entry.pem(), entry.clazz(), pemDecoder); System.out.println("PASS (" + entry.name() + ")"); return r; } catch (Exception | AssertionError e) { @@ -412,6 +456,19 @@ public class PEMDecoderTest { } } + private static void testPKCS8Key(PEMData.Entry entry) { + try { + PKCS8Key key = PEMDecoder.of().decode(entry.pem(), PKCS8Key.class); + PKCS8EncodedKeySpec spec = + new PKCS8EncodedKeySpec(key.getEncoded()); + + KeyFactory kf = KeyFactory.getInstance(key.getAlgorithm()); + kf.generatePublic(spec); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + static void testClass(PEMData.Entry entry, Class clazz) throws IOException { var pk = PEMDecoder.of().decode(entry.pem(), clazz); } @@ -472,9 +529,15 @@ public class PEMDecoderTest { "should not be null"); } + AlgorithmParameterSpec spec = null; String algorithm = switch(privateKey.getAlgorithm()) { case "EC" -> "SHA256withECDSA"; case "EdDSA" -> "EdDSA"; + case "RSASSA-PSS" -> { + spec = new PSSParameterSpec( + "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1); + yield "RSASSA-PSS"; + } case null -> { System.out.println("Algorithm is null " + entry.name()); @@ -487,6 +550,9 @@ public class PEMDecoderTest { try { if (d instanceof PrivateKey) { s = Signature.getInstance(algorithm); + if (spec != null) { + s.setParameter(spec); + } s.initSign(privateKey); s.update(data); s.sign(); diff --git a/test/jdk/java/security/PEM/PEMEncoderTest.java b/test/jdk/java/security/PEM/PEMEncoderTest.java index c8b19c313a5..3d1948ba2fe 100644 --- a/test/jdk/java/security/PEM/PEMEncoderTest.java +++ b/test/jdk/java/security/PEM/PEMEncoderTest.java @@ -26,9 +26,15 @@ /* * @test * @bug 8298420 + * @library /test/lib * @summary Testing basic PEM API encoding * @enablePreview * @modules java.base/sun.security.util + * @run main PEMEncoderTest PBEWithHmacSHA256AndAES_128 + * @run main/othervm -Djava.security.properties=${test.src}/java.security-anotherAlgo + * PEMEncoderTest PBEWithHmacSHA512AndAES_256 + * @run main/othervm -Djava.security.properties=${test.src}/java.security-emptyAlgo + * PEMEncoderTest PBEWithHmacSHA256AndAES_128 */ import sun.security.util.Pem; @@ -39,13 +45,22 @@ import javax.crypto.spec.PBEParameterSpec; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.InvalidParameterSpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; import java.util.*; +import jdk.test.lib.security.SecurityUtils; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertThrows; + public class PEMEncoderTest { static Map keymap; + static String pkcs8DefaultAlgExpect; public static void main(String[] args) throws Exception { + pkcs8DefaultAlgExpect = args[0]; PEMEncoder encoder = PEMEncoder.of(); // These entries are removed @@ -63,7 +78,12 @@ public class PEMEncoderTest { System.out.println("New instance re-encode testToString:"); keymap.keySet().stream().forEach(key -> testToString(key, PEMEncoder.of())); - + System.out.println("Same instance Encoder testEncodedKeySpec:"); + testEncodedKeySpec(encoder); + System.out.println("New instance Encoder testEncodedKeySpec:"); + testEncodedKeySpec(PEMEncoder.of()); + System.out.println("Same instance Encoder testEmptyKey:"); + testEmptyAndNullKey(encoder); keymap = generateObjKeyMap(PEMData.encryptedList); System.out.println("Same instance Encoder match test:"); keymap.keySet().stream().forEach(key -> testEncryptedMatch(key, encoder)); @@ -86,6 +106,13 @@ public class PEMEncoderTest { PEMRecord pemRecord = d.decode(PEMData.ed25519ep8.pem(), PEMRecord.class); PEMData.checkResults(PEMData.ed25519ep8, pemRecord.toString()); + + // test PemRecord is encapsulated with PEM header and footer on encoding + String[] pemLines = PEMData.ed25519ep8.pem().split("\n"); + String[] pemNoHeaderFooter = Arrays.copyOfRange(pemLines, 1, pemLines.length - 1); + PEMRecord pemR = new PEMRecord("ENCRYPTED PRIVATE KEY", String.join("\n", + pemNoHeaderFooter)); + PEMData.checkResults(PEMData.ed25519ep8.pem(), encoder.encodeToString(pemR)); } static Map generateObjKeyMap(List list) { @@ -145,10 +172,12 @@ public class PEMEncoderTest { static void testEncrypted(String key, PEMEncoder encoder) { PEMData.Entry entry = PEMData.getEntry(key); try { - encoder.withEncryption( + String pem = encoder.withEncryption( (entry.password() != null ? entry.password() : "fish".toCharArray())) .encodeToString(keymap.get(key)); + + verifyEncriptionAlg(pem); } catch (RuntimeException e) { throw new AssertionError("Encrypted encoder failed with " + entry.name(), e); @@ -157,6 +186,11 @@ public class PEMEncoderTest { System.out.println("PASS: " + entry.name()); } + private static void verifyEncriptionAlg(String pem) { + var epki = PEMDecoder.of().decode(pem, EncryptedPrivateKeyInfo.class); + assertEquals(epki.getAlgName(), pkcs8DefaultAlgExpect); + } + /* Test cannot verify PEM was the same as known PEM because we have no public access to the AlgoritmID.params and PBES2Parameters. @@ -195,5 +229,42 @@ public class PEMEncoderTest { PEMData.checkResults(entry, result); System.out.println("PASS: " + entry.name()); } -} + static void testEncodedKeySpec(PEMEncoder encoder) throws NoSuchAlgorithmException { + KeyPair kp = getKeyPair(); + encoder.encodeToString(new X509EncodedKeySpec(kp.getPublic().getEncoded())); + encoder.encodeToString(new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded())); + System.out.println("PASS: testEncodedKeySpec"); + } + private static void testEmptyAndNullKey(PEMEncoder encoder) throws NoSuchAlgorithmException { + KeyPair kp = getKeyPair(); + assertThrows(IllegalArgumentException.class, () -> encoder.encode( + new KeyPair(kp.getPublic(), new EmptyKey()))); + assertThrows(IllegalArgumentException.class, () -> encoder.encode( + new KeyPair(kp.getPublic(), null))); + + assertThrows(IllegalArgumentException.class, () -> encoder.encode( + new KeyPair(new EmptyKey(), kp.getPrivate()))); + assertThrows(IllegalArgumentException.class, () -> encoder.encode( + new KeyPair(null, kp.getPrivate()))); + System.out.println("PASS: testEmptyKey"); + } + + private static KeyPair getKeyPair() throws NoSuchAlgorithmException { + Provider provider = Security.getProvider("SunRsaSign"); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", provider); + kpg.initialize(SecurityUtils.getTestKeySize("RSA")); + return kpg.generateKeyPair(); + } + + private static class EmptyKey implements PublicKey, PrivateKey { + @Override + public String getAlgorithm() { return "Test"; } + + @Override + public String getFormat() { return "Test"; } + + @Override + public byte[] getEncoded() { return new byte[0]; } + } +} diff --git a/test/jdk/java/security/PEM/PEMMultiThreadTest.java b/test/jdk/java/security/PEM/PEMMultiThreadTest.java new file mode 100644 index 00000000000..f345a3c129d --- /dev/null +++ b/test/jdk/java/security/PEM/PEMMultiThreadTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +/* + * @test + * @bug 8298420 + * @library /test/lib + * @summary Testing PEM API is thread safe + * @enablePreview + * @modules java.base/sun.security.util + */ + +import java.security.*; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import jdk.test.lib.security.SecurityUtils; + +public class PEMMultiThreadTest { + static final int THREAD_COUNT = 5; + static final int KEYS_COUNT = 50; + + public static void main(String[] args) throws Exception { + PEMEncoder encoder = PEMEncoder.of(); + try (ExecutorService ex = Executors.newFixedThreadPool(THREAD_COUNT)) { + Map keys = new HashMap<>(); + Map encoded = Collections.synchronizedMap(new HashMap<>()); + Map decoded = Collections.synchronizedMap(new HashMap<>()); + final CountDownLatch encodingComplete = new CountDownLatch(KEYS_COUNT); + final CountDownLatch decodingComplete = new CountDownLatch(KEYS_COUNT); + + // Generate keys and encode them in parallel + for (int i = 0; i < KEYS_COUNT; i++) { + final int finalI = i; + KeyPair kp = getKeyPair(); + keys.put(finalI, kp.getPublic()); + + ex.submit(() -> { + encoded.put(finalI, encoder.encodeToString(kp.getPublic())); + encodingComplete.countDown(); + }); + } + encodingComplete.await(); + + // Decode keys in parallel + PEMDecoder decoder = PEMDecoder.of(); + for (Map.Entry entry : encoded.entrySet()) { + ex.submit(() -> { + decoded.put(entry.getKey(), decoder.decode(entry.getValue(), PublicKey.class) + .toString()); + decodingComplete.countDown(); + }); + } + decodingComplete.await(); + + // verify all keys were properly encoded and decoded comparing with the original key map + for (Map.Entry kp : keys.entrySet()) { + if (!decoded.get(kp.getKey()).equals(kp.getValue().toString())) { + throw new RuntimeException("a key was not properly encoded and decoded: " + decoded); + } + } + } + + System.out.println("PASS: testThreadSafety"); + } + + private static KeyPair getKeyPair() throws NoSuchAlgorithmException { + String alg = "EC"; + KeyPairGenerator kpg = KeyPairGenerator.getInstance(alg); + kpg.initialize(SecurityUtils.getTestKeySize(alg)); + return kpg.generateKeyPair(); + } +} diff --git a/test/jdk/java/security/PEM/java.security-anotherAlgo b/test/jdk/java/security/PEM/java.security-anotherAlgo new file mode 100644 index 00000000000..c084f465fa2 --- /dev/null +++ b/test/jdk/java/security/PEM/java.security-anotherAlgo @@ -0,0 +1 @@ +jdk.epkcs8.defaultAlgorithm=PBEWithHmacSHA512AndAES_256 diff --git a/test/jdk/java/security/PEM/java.security-emptyAlgo b/test/jdk/java/security/PEM/java.security-emptyAlgo new file mode 100644 index 00000000000..deb2ab7aa45 --- /dev/null +++ b/test/jdk/java/security/PEM/java.security-emptyAlgo @@ -0,0 +1 @@ +jdk.epkcs8.defaultAlgorithm= diff --git a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/EncryptKey.java b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/EncryptKey.java index d1fccd9730a..3fe8cfcfbfa 100644 --- a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/EncryptKey.java +++ b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/EncryptKey.java @@ -25,11 +25,15 @@ /** * @test + * @library /test/lib + * @modules java.base/sun.security.util * @bug 8298420 * @summary Testing encryptKey * @enablePreview */ +import sun.security.util.Pem; + import javax.crypto.EncryptedPrivateKeyInfo; import javax.crypto.SecretKey; import javax.crypto.spec.PBEParameterSpec; @@ -37,8 +41,13 @@ import javax.crypto.spec.SecretKeySpec; import java.security.AlgorithmParameters; import java.security.PEMDecoder; import java.security.PrivateKey; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; import java.util.Arrays; +import static jdk.test.lib.Asserts.assertEquals; + public class EncryptKey { private static final String encEdECKey = @@ -56,6 +65,8 @@ public class EncryptKey { passwdText.getBytes(), "PBE"); public static void main(String[] args) throws Exception { + Provider p = Security.getProvider(System.getProperty("test.provider.name", "SunJCE")); + EncryptedPrivateKeyInfo ekpi = PEMDecoder.of().decode(encEdECKey, EncryptedPrivateKeyInfo.class); PrivateKey priKey = PEMDecoder.of().withDecryption(password). @@ -71,6 +82,19 @@ public class EncryptKey { " with expected."); } + // Test encryptKey(PrivateKey, char[], String, ...) with provider + e = EncryptedPrivateKeyInfo.encryptKey(priKey, password, ekpi.getAlgName(), + ap.getParameterSpec(PBEParameterSpec.class), p); + if (!Arrays.equals(ekpi.getEncryptedData(), e.getEncryptedData())) { + throw new AssertionError("encryptKey() didn't match" + + " with expected."); + } + + // Test encryptKey(PrivateKey, char[], String, ...) with provider and null algorithm + e = EncryptedPrivateKeyInfo.encryptKey(priKey, password, null, null, + p); + assertEquals(e.getAlgName(), Pem.DEFAULT_ALGO); + // Test encryptKey(PrivateKey, Key, String, ...) e = EncryptedPrivateKeyInfo.encryptKey(priKey, key, ekpi.getAlgName(), ap.getParameterSpec(PBEParameterSpec.class),null, null); @@ -78,5 +102,26 @@ public class EncryptKey { throw new AssertionError("encryptKey() didn't match" + " with expected."); } + + // Test encryptKey(PrivateKey, Key, String, ...) with provider and null random + e = EncryptedPrivateKeyInfo.encryptKey(priKey, key, ekpi.getAlgName(), + ap.getParameterSpec(PBEParameterSpec.class), p, null); + if (!Arrays.equals(ekpi.getEncryptedData(), e.getEncryptedData())) { + throw new AssertionError("encryptKey() didn't match" + + " with expected."); + } + + // Test encryptKey(PrivateKey, Key, String, ...) with provider and SecureRandom + e = EncryptedPrivateKeyInfo.encryptKey(priKey, key, ekpi.getAlgName(), + ap.getParameterSpec(PBEParameterSpec.class), p, new SecureRandom()); + if (!Arrays.equals(ekpi.getEncryptedData(), e.getEncryptedData())) { + throw new AssertionError("encryptKey() didn't match" + + " with expected."); + } + + // Test encryptKey(PrivateKey, Key, String, ...) with provider and null algorithm + e = EncryptedPrivateKeyInfo.encryptKey(priKey, key, null, null, + p, new SecureRandom()); + assertEquals(e.getAlgName(), Pem.DEFAULT_ALGO); } } diff --git a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java index 7c8951b3417..b1917ffa84d 100644 --- a/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java +++ b/test/jdk/javax/crypto/EncryptedPrivateKeyInfo/GetKey.java @@ -35,6 +35,8 @@ import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.PEMDecoder; import java.security.PrivateKey; +import java.security.Provider; +import java.security.Security; import java.util.Arrays; public class GetKey { @@ -48,12 +50,29 @@ public class GetKey { IycFtI70ciPjgwDSjtCcPxR8fSxJPrm2yOJsRVo= -----END ENCRYPTED PRIVATE KEY----- """; + private static final String encDHECKey = + """ + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIIBvDBmBgkqhkiG9w0BBQ0wWTA4BgkqhkiG9w0BBQwwKwQUN8pkErJx7aqH0fJF + BcOadPKiuRoCAhAAAgEQMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBAT1Vwd + gU4rTd6zy7lKr4wmBIIBUMe+2+O0AG6t4CMSHcDVceRg2jvbs5PmPjW4Ka5mDich + hVEsjSpJLbUyJdbji6UaiUpuWgvYSMLZ10pfhOFw/ssXwCw+JrlXUqDpQGLaW8ZR + zSL3CoozTI2Y6EBdWt53KbySwtZMoTpW/W3vPi98bJXtR635msf6gYXmSUP7DyoJ + 79dxz3pRYsnOuBe0yZ2wTq9iMgTMudzLJAFX2qyi+3KOb1g5Va9DYAqJmzCYOd74 + +I+0gGNFtSc1vGQYr3cAfcKT8AZ1RHE4IkpnpgFD5HsZ8f4hy0yK8juk9NE9Gzuy + B929LBXk6V3L0MKzIABS3QvAlhWETM6XtGBDugzAgsooo9lEHLwYRldvOlL+QYyE + CtqDmXOrgEMWvxWGEFCTKYhKkqMKjU3y3GiozEEdb9j2okW1s30yHQjIoj0OR4nB + D8GeP0QnY73NfbOw7z81TA== + -----END ENCRYPTED PRIVATE KEY----- + """; private static final String passwdText = "fish"; private static final char[] password = passwdText.toCharArray(); private static final SecretKey key = new SecretKeySpec( passwdText.getBytes(), "PBE"); public static void main(String[] args) throws Exception { + Provider p = Security.getProvider(System.getProperty("test.provider.name", "SunJCE")); + EncryptedPrivateKeyInfo ekpi = PEMDecoder.of().decode(encEdECKey, EncryptedPrivateKeyInfo.class); PrivateKey priKey = PEMDecoder.of().withDecryption(password). @@ -66,11 +85,23 @@ public class GetKey { + "match with expected."); } - // Test getKey(key, provider) + // Test getKey(key, provider) provider null if (!Arrays.equals(priKey.getEncoded(), ekpi.getKey(key, null).getEncoded())) { throw new AssertionError("getKey(key, provider) " + "didn't match with expected."); } + + // Test getKey(key, provider) with provider + EncryptedPrivateKeyInfo ekpiDH = PEMDecoder.of().decode(encDHECKey, + EncryptedPrivateKeyInfo.class); + PrivateKey priKeyDH = PEMDecoder.of().withDecryption(password). + decode(encDHECKey, PrivateKey.class); + + if (!Arrays.equals(priKeyDH.getEncoded(), + ekpiDH.getKey(key, p).getEncoded())) { + throw new AssertionError("getKey(key, provider) " + + "didn't match with expected."); + } } } diff --git a/test/jdk/sun/security/pkcs/pkcs8/PKCS8Test.java b/test/jdk/sun/security/pkcs/pkcs8/PKCS8Test.java index 49cca69971f..9bb5502ad9f 100644 --- a/test/jdk/sun/security/pkcs/pkcs8/PKCS8Test.java +++ b/test/jdk/sun/security/pkcs/pkcs8/PKCS8Test.java @@ -31,10 +31,13 @@ * java.base/sun.security.provider * java.base/sun.security.x509 * @run main PKCS8Test + * @run main/othervm -Dtest.provider.name=SunJCE PKCS8Test */ import java.math.BigInteger; import java.security.InvalidKeyException; +import java.security.Provider; +import java.security.Security; import java.util.Arrays; import java.util.HexFormat; @@ -45,6 +48,7 @@ import sun.security.provider.DSAPrivateKey; public class PKCS8Test { + static Provider provider; static final String FORMAT = "PKCS#8"; static final String EXPECTED_ALG_ID_CHRS = "DSA, \n" + "\tp: 02\n\tq: 03\n\tg: 04\n"; @@ -59,7 +63,7 @@ public class PKCS8Test { "0403020101"); // PrivateKey OCTET int x = 1 public static void main(String[] args) throws Exception { - + provider = Security.getProvider(System.getProperty("test.provider.name")); byte[] encodedKey = new DSAPrivateKey( BigInteger.valueOf(1), BigInteger.valueOf(2), @@ -73,7 +77,8 @@ public class PKCS8Test { .toString(encodedKey)); } - PKCS8Key decodedKey = (PKCS8Key)PKCS8Key.parseKey(encodedKey); + PKCS8Key decodedKey = provider == null ? (PKCS8Key)PKCS8Key.parseKey(encodedKey) : + (PKCS8Key)PKCS8Key.parseKey(encodedKey, provider); assert(ALGORITHM.equalsIgnoreCase(decodedKey.getAlgorithm())); assert(FORMAT.equalsIgnoreCase(decodedKey.getFormat())); @@ -126,7 +131,11 @@ public class PKCS8Test { original[1] = (byte) (length - 2); // the length field inside DER original[4] = (byte) newVersion; // the version inside DER try { - PKCS8Key.parseKey(original); + if (provider == null) { + PKCS8Key.parseKey(original); + } else { + PKCS8Key.parseKey(original, provider); + } } catch (InvalidKeyException e) { throw new RuntimeException(e); } diff --git a/test/lib/jdk/test/lib/security/SecurityUtils.java b/test/lib/jdk/test/lib/security/SecurityUtils.java index 7509488225e..be6ff1cc0e3 100644 --- a/test/lib/jdk/test/lib/security/SecurityUtils.java +++ b/test/lib/jdk/test/lib/security/SecurityUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -45,6 +45,8 @@ public final class SecurityUtils { private enum KeySize{ RSA(2048), DSA(2048), + Ed25519(256), + EC(256), DH(2048); private final int keySize; @@ -145,6 +147,8 @@ public final class SecurityUtils { return switch (algo) { case "RSA" -> KeySize.RSA.keySize; case "DSA" -> KeySize.DSA.keySize; + case "Ed25519" -> KeySize.Ed25519.keySize; + case "EC" -> KeySize.EC.keySize; case "DH", "DiffieHellman" -> KeySize.DH.keySize; default -> throw new RuntimeException("Test key size not defined for " + algo); };