8358171: Additional code coverage for PEM API

Reviewed-by: ascarpino
This commit is contained in:
Fernando Guallini 2025-06-06 09:53:25 +00:00
parent 65fda5c02a
commit b2e7cda6a0
10 changed files with 533 additions and 43 deletions

View File

@ -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) {

View File

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

View File

@ -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<String, DEREncodable> 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<PEMData.Entry> 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]; }
}
}

View File

@ -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<Integer, PublicKey> keys = new HashMap<>();
Map<Integer, String> encoded = Collections.synchronizedMap(new HashMap<>());
Map<Integer, String> 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<Integer, String> 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<Integer, PublicKey> 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();
}
}

View File

@ -0,0 +1 @@
jdk.epkcs8.defaultAlgorithm=PBEWithHmacSHA512AndAES_256

View File

@ -0,0 +1 @@
jdk.epkcs8.defaultAlgorithm=

View File

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

View File

@ -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.");
}
}
}

View File

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

View File

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