From e51a84dd1e0ee1bc75d92022dc75a61f4c5a031c Mon Sep 17 00:00:00 2001 From: tracyboehrer Date: Fri, 5 Mar 2021 09:55:49 -0600 Subject: [PATCH] Dropped private Sun security imports. Now using pregenerated certs. (#1032) --- .../bot/connector/JwtTokenExtractorTests.java | 106 +++++++----------- .../resources/bot-connector-expired.pkcs12 | Bin 0 -> 2702 bytes .../src/test/resources/bot-connector.key | 27 +++++ .../src/test/resources/bot-connector.pkcs12 | Bin 0 -> 2702 bytes 4 files changed, 66 insertions(+), 67 deletions(-) create mode 100644 libraries/bot-connector/src/test/resources/bot-connector-expired.pkcs12 create mode 100644 libraries/bot-connector/src/test/resources/bot-connector.key create mode 100644 libraries/bot-connector/src/test/resources/bot-connector.pkcs12 diff --git a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenExtractorTests.java b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenExtractorTests.java index de9604db5..96f6b1bdd 100644 --- a/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenExtractorTests.java +++ b/libraries/bot-connector/src/test/java/com/microsoft/bot/connector/JwtTokenExtractorTests.java @@ -14,15 +14,17 @@ import com.microsoft.bot.connector.authentication.OpenIdMetadataKey; import com.microsoft.bot.connector.authentication.TokenValidationParameters; import java.io.IOException; -import java.math.BigInteger; +import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyPair; -import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; -import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; @@ -34,20 +36,21 @@ import java.util.concurrent.CompletionException; import org.junit.Before; import org.junit.Test; -import sun.security.x509.AlgorithmId; -import sun.security.x509.CertificateAlgorithmId; -import sun.security.x509.CertificateSerialNumber; -import sun.security.x509.CertificateValidity; -import sun.security.x509.CertificateVersion; -import sun.security.x509.CertificateX509Key; -import sun.security.x509.X500Name; -import sun.security.x509.X509CertImpl; -import sun.security.x509.X509CertInfo; +/** + * Test Notes: + * + * The PKCS12 certificates were created using these steps: + * https://kb.globalscape.com/Knowledgebase/11039/Generating-a-PKCS12-Private-Key-and-Public-Certificate + * + * For the expired cert, just specify a negative number of days in step #4. + * + * For both valid and expired certs, these unit tests expect the alias for both to be "bot-connector-pkcs12" + * and the password to be "botframework" + */ public class JwtTokenExtractorTests { - private X509Certificate validCertificate; - private X509Certificate expiredCertificate; - private KeyPair keyPair; + private CertInfo valid; + private CertInfo expired; @Before public void setup() throws GeneralSecurityException, IOException { @@ -55,25 +58,15 @@ public void setup() throws GeneralSecurityException, IOException { EmulatorValidation.TOKENVALIDATIONPARAMETERS.validateLifetime = false; GovernmentChannelValidation.TOKENVALIDATIONPARAMETERS.validateLifetime = false; - // create keys - keyPair = createKeyPair(); - Date now = new Date(); - Date from = new Date(now.getTime() - (10 * 86400000L)); - - // create expired certificate - Date to = new Date(now.getTime() - (9 * 86400000L)); - expiredCertificate = createSelfSignedCertificate(keyPair, from, to); - - // create valid certificate - to = new Date(now.getTime() + (9 * 86400000L)); - validCertificate = createSelfSignedCertificate(keyPair, from, to); + valid = loadCert("bot-connector.pkcs12"); + expired = loadCert("bot-connector-expired.pkcs12"); } @Test(expected = CompletionException.class) public void JwtTokenExtractor_WithExpiredCert_ShouldNotAllowCertSigningKey() { // this should throw a CompletionException (which contains an AuthenticationException) buildExtractorAndValidateToken( - expiredCertificate, keyPair.getPrivate() + expired.cert, expired.keypair.getPrivate() ).join(); } @@ -81,7 +74,7 @@ public void JwtTokenExtractor_WithExpiredCert_ShouldNotAllowCertSigningKey() { public void JwtTokenExtractor_WithValidCert_ShouldAllowCertSigningKey() { // this should not throw buildExtractorAndValidateToken( - validCertificate, keyPair.getPrivate() + valid.cert, valid.keypair.getPrivate() ).join(); } @@ -92,7 +85,7 @@ public void JwtTokenExtractor_WithExpiredToken_ShouldNotAllow() { Date issuedAt = new Date(now.getTime() - 86400000L); buildExtractorAndValidateToken( - expiredCertificate, keyPair.getPrivate(), issuedAt + expired.cert, expired.keypair.getPrivate(), issuedAt ).join(); } @@ -161,45 +154,24 @@ private static TokenValidationParameters createTokenValidationParameters(X509Cer }}; } - private KeyPair createKeyPair() throws NoSuchAlgorithmException { - // note that this isn't allowing for a "kid" value - KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); - generator.initialize(2048); - return generator.generateKeyPair(); + private static class CertInfo { + public X509Certificate cert; + public KeyPair keypair; } - private static X509Certificate createSelfSignedCertificate( - KeyPair pair, Date from, Date to - ) throws GeneralSecurityException, IOException { - String dn = "CN=Bot, OU=BotFramework, O=Microsoft, C=US"; - String algorithm = "SHA256withRSA"; - - PrivateKey privateKey = pair.getPrivate(); - X509CertInfo info = new X509CertInfo(); - - CertificateValidity interval = new CertificateValidity(from, to); - BigInteger sn = new BigInteger(64, new SecureRandom()); - X500Name owner = new X500Name(dn); - - info.set(X509CertInfo.VALIDITY, interval); - info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); - info.set(X509CertInfo.SUBJECT, owner); - info.set(X509CertInfo.ISSUER, owner); - info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic())); - info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); - AlgorithmId algo = new AlgorithmId(AlgorithmId.sha256WithRSAEncryption_oid); - info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); - - // Sign the cert to identify the algorithm that's used. - X509CertImpl cert = new X509CertImpl(info); - cert.sign(privateKey, algorithm); - - // Update the algorithm, and resign. - algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG); - info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo); - cert = new X509CertImpl(info); - cert.sign(privateKey, algorithm); - return cert; + private static CertInfo loadCert(String pkcs12File) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, + UnrecoverableKeyException { + InputStream fis = ClassLoader.getSystemResourceAsStream(pkcs12File); + KeyStore p12 = KeyStore.getInstance("pkcs12"); + p12.load(fis, "botframework".toCharArray()); + + return new CertInfo() {{ + cert = (X509Certificate) p12.getCertificate("bot-connector-pkcs12"); + keypair = new KeyPair(cert.getPublicKey(), + (PrivateKey) p12.getKey("bot-connector-pkcs12", "botframework".toCharArray()) + ); + }}; } private static String encodeCertificate(Certificate certificate) { diff --git a/libraries/bot-connector/src/test/resources/bot-connector-expired.pkcs12 b/libraries/bot-connector/src/test/resources/bot-connector-expired.pkcs12 new file mode 100644 index 0000000000000000000000000000000000000000..ac947006105f57b29bda8445c1067e00aa60484d GIT binary patch literal 2702 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 literal 0 HcmV?d00001 diff --git a/libraries/bot-connector/src/test/resources/bot-connector.key b/libraries/bot-connector/src/test/resources/bot-connector.key new file mode 100644 index 000000000..e5e43c892 --- /dev/null +++ b/libraries/bot-connector/src/test/resources/bot-connector.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAy8VcIYWh4sF2XcZF7u+lSq7YdE8skZhmtDF5w8GoEoPscGyT +wSeWjK7u+y2g5iAZsXQwzhN1VvOHznAlLrswLaORie7ch9veFeTMT60gLL2w8e6h +RUWxNJiQXjeExwk8Fhvcq7Kpl+qM4iEHvDX6iXCjEkNJ4Ghx48j9siUKMf1T8IcZ +sE3zzaaGOU5ar8NVsf9Kz1kPCOYv8zqykB45nUDsbE/q9cEkumL8ebjd1JApDJf0 +sf/PkftMvwP69QY1CJ/achUsRqDvFGLw+ZyUyXaSdPt92H92vbNzo8hn6GuxnPHy +f/Aoxjy/o5zNocsiiJvgFBFjRBZXWhk3OJWKZwIDAQABAoIBADNiKx9Q4Uea3Uw8 +STo9OAMjH/YEWQrF0XAy4a+ZT9aLab3Xw1J7txz2p9Cy6tXc1l3HHN96TKaGdoJ6 +CQZFsZpwmqybjQS9Tr1amqKk124wz0PSltwu/MZ0ikMX4OWH0J0KnZS2Usm6HZiQ +F7FAM1MhEh3y1dg+vilgb4jSikWcVp7RbcMgwG0N9oQhbPqN+Bv/E5KBpYk1Rdwt +yjSBOdDenx+TF5RrdKYxC3ouKN0BJMgtIIkv+iGce1WMtSAHkNXrgxJ9AhDquREU +Op363fad01Ulvs4Z+IDlEhrpA6oUt5hr8lStFhrhVuDPqctAWz27+YNw5ioHbimA +U48EOzECgYEA7T5dQzKXIzrDha4Spr8KbCMvXsesehWG3RLZxhU7lnjSMAhBuKGU +hZMfjmSSBR/rr7ppMjN4LLmpjqTkhojg/p+MnK9XRSvmGaSxlS1K8hANjShhx6s7 +xWbEsKQEPbuq1m0vCAzxgGkxLpRmM9ajJhFYEoSdVbc/hhVI72mxhiUCgYEA2+GI +ig0Wpbq5D1ISwljWHhpdi4d0MeO+wtogMo46AAX4kpgCEKDmPwX2igJKJjQJyWNB +PqHXPPQJyferun27baiNA5vEDzoCRvyLqKjyLrzSS+wDszR4mYhK8naILPonmIca +9BsUDcQw7x3rzVUlOKFpbRfT0qPVa5qn3T32apsCgYEAmYJvCloj3ZHajhdSzj5z +WgFyV1vQSLbBKy9VZoy6n+TR7G6LSBKVbdEC7Do7GcHL2Us/YlJXgmkoQ7qCfGL5 +YwiODZyPVZzQKOueVK6X/gVRH3NvwakU5ehXgQzACcnzAwhnFEh7w+FNB5zSfNx3 +eNxkJqdUvu/x1KrVJMU5L1kCgYEAkIokYGOUNKOXDTwterY9IpLAVX1YY4dLmfkb +W0BlXiiOq4bjLJ0oXduEolo49f4VRN5LQGnQ/I+Lc8msiK4oLEC1Wd7mNgAzCQjw +oZFVimWzdBcUo5Plhz+xzMsgXzieGMUPcdHvD9GdPUKVBGhpTF3G2ODl7LyoCdEj +cetOdesCgYAIuxFR/89S44Je5maTMkcExZpVTm1D1Zc8EmlHQ+WPjrakZSWFx2TS +o8wUd/mCwCTLRG3S2t3eUZiEi+G9gI8bE/w7ABxNCFAlHbo0SETy7T+9XeznoFbZ +0FyvVLvXQVZhKPVTF0pYkfuHo3ofbotKbTEM62EurroU1dviRJ7Seg== +-----END RSA PRIVATE KEY----- diff --git a/libraries/bot-connector/src/test/resources/bot-connector.pkcs12 b/libraries/bot-connector/src/test/resources/bot-connector.pkcs12 new file mode 100644 index 0000000000000000000000000000000000000000..e9854a3813522f39a933e66a648ddb1de3458cd1 GIT binary patch literal 2702 zcmZXWc{CJ`7RP6%!5AcK!iYrKGIq-7hsj_lYZPT0%VZn-QpCuRE$i4KvPSkbO_3;B z#+IGYpll@>*+*}F=e+lR@0@q;x#xcG_ug~={G1ENL*qce6L37#gqc;EpikK40I~oJ z@K9|q9*SVt8gM+g<)0CA0Ulh=u!=!I0HfsnGXcVdnW6u_z|OdM5)2uWX(Yj;p6G!< z5I_VTj9U(YS60mB6ZIo$!(|J0X%E>fjjUmkyH(&tj>ZK#8zn*Lyu)92`>Vjg*4az~ z9esq0)?eOY{t~y@v(CTw;q?XddDo$`TN383o+U`$kXxJ2a(}(=n|IJmCZ=p_(OHh6 zRyp6>1AV#%7TEZzgnW{8J*9@ueg$#m-zxf3mRu~WUMr^##qJR!z& zNj`U6Sy38K;N~#~P+ex;j#1(;@ff1GArSGNv)UoQpT*$2k081P>zw491@@0D?EL+9 zaERj$r`LOv4|+k0kF}Siy1 zh*O{)Z%ol^1BTw)cG$qmfQoHXwB?QwQA?^@zQZo*R*gyQY0LGxK&A^1*CxNamBy!# zDsRo8vIVut<6h|PaqG~g$}I;n87!eLANqz0T@g%mR$~=Z>=1lBmH1nntKT^18K-&& z+0XxZpmi7eB9^4>)%ANvG`+5aXv~UleD$V`seG zSD*E;ppTmIQ7_lLm?J#XLeWkeZhj>4t4Gy7qu}$4*H@epJ;+Xc+%D2-y^z*x2K}HG zVtw-r#ur$B95!G$*xGa4Z);32qRr^0IkVq^5mTq@li2048m~9qelSbYBsGY~nt7oQ zw%&l;-Ott#dB}XUZ`_D;u8P6a^O-tqSM`=lrws&d7go744e?Bi7;H*g^B%T9tH%+^ zLH0SW&1A)4B|>M6Xd4z{{7s(!NbI5ox*-={j`?E>d4CmmbiJbMcUYqB3oZTUaJA6H z;e>QU?pO+*Blm@kxJ*kc@eYR}b`u}X9`GF(MkdA66vo#jO8N%jtvm(Vm_PVJdmb|>h~<%uO{`+pETw{i9W=>o?y zh5iqq3h+$sU_6s6!**h%9W&d1a0LZ|7+l+60B!C6DJBjld*%05KK`3xU_7`-0@Y>T zNIf-LoN4|s$}f<6^si>tsKwE?3X&ZD5| z0r>i9n`_r;95HWJ&cLEEqKAaOBb6|L^=?udna~`vR7@Z1(%jeVl9Hi=%BYLN_ui?P zy*C}Qd=;x5GoSRhc0`uaXO+C7L;BewcCTPKlSF|Wwb#`6>Q7-4Hda;*Vj>Tc+0{>M z-&m04-eLMYl(U+IQvJ*DKuwuW4Xv`7bZM`S-diWDgUx7#k5k?aAK(FoW3|`k8`~zz zC4x*+B6Ta{j@||j93rLq4hWfNGQ2|(EF*4tzf&dNaim`d@XKOsZ2GPI1qUei)l&t# z)4FLYtliI_FF@|HKPr+=7OlyiQR)qc4J^<`E+Qb`Ab*BV*NEomZ3^`l$emla>%{fz z-a|Jg=g%mElwVdglc|HHXXhT%>}za(lZaYSzjWg&vOp2PN#RsZ`3A)m3Mu<_K{U zS9_Sf!2SgVV&SwU%a8AdrBG_1<#7Em|H&8xWHsrR#akwR7izowf~2C;L_RouN=#Y8 zj2g!wVmU~yc0#Mphp~XkY;{cHrAbG^#1zq8vpv^z8~}#K1TN;m^1Rl_ca0e9i89Xqz;n+ZqXVm;}7t-JO0f;S@tqkIBb5x zFS~*KrS0_FsI8avJLBTTA&m_gbwHc#@ufq#n#)#49kpsss{$0g=1pAc6zVdijmJ?x zbE8|vcg`)8D-(E7oFSApRI%|)h2%KD5HLS~2z|s!CmqN3W;u?CKqF)^l}e<<8-=jr zu2;Lg`aj0)G>S~~=@0m=3wXsqFWvnsF7ZnLShGs7zhXP|;cMWvD56J(+$vAtS7{dW zsR6&6(JdR@qd^lrGC6{loc8)FH|`*t&QCYkX$i%gB`qG>kHi;n)$!bjk5?W0={A|r z>3-~1lDWwzCk2c~^7~S5oe#6cDbM_@DD&ZQBn~)c-za?tVN?6+LdC}a<=~6$_7(R2 z>ZYn5hbp8$xrvKQ(|nZqAlQEVq{3ae_mF{&3MoEgfWp?w)14&ct{`~V67MYsZ749?2TBy;iv rNRSBt=4BcFA`tUH!SVd|-K?ieH`5eZq8Lx2Cv^(2Z0(2s8?XNY3?>01 literal 0 HcmV?d00001