From 4eca8a4004fc52f7d31ef41a4bef8428081f0d28 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 1 Jul 2020 14:05:14 -0700 Subject: [PATCH 1/9] Add additional certificate formats --- .../test/TestCertificates/.gitattributes | 1 + .../test/TestCertificates/https-aspnet.crt | Bin 0 -> 784 bytes .../test/TestCertificates/https-aspnet.key | 30 +++++++++++ .../TestCertificates/https-dsa-no-pass.key | 20 +++++++ .../test/TestCertificates/https-dsa.crt | Bin 0 -> 1276 bytes .../test/TestCertificates/https-dsa.key | 23 ++++++++ .../test/TestCertificates/https-rsa.crt | Bin 0 -> 1431 bytes .../test/TestCertificates/https-rsa.key | 51 ++++++++++++++++++ 8 files changed, 125 insertions(+) create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.crt create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.crt create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.key diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes b/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes new file mode 100644 index 000000000000..9fb7e61e8dba --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes @@ -0,0 +1 @@ +*.key binary diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.crt new file mode 100644 index 0000000000000000000000000000000000000000..0421f377734d035790e8cd737bdfbad614e72667 GIT binary patch literal 784 zcmXqLV&*YuV*IjznTe5!iNpJ`;q5=d21g8d**LY@JlekVGBR?rG8l*$3Kq1NMvk$A^D^^IA)Wq<$ntc*Wl4v@rY+C=FuVlmf z%bc?qF1|2rys>S6*u3_4@+|^q`j_`??GP?=nSQS>vDoHP<@q1`6dLTT=Dlq$pLCJ+ zl&k&16s{Ytzm)3~on=F6mTr~^wCz3I|Hh^8@H0lYe9jYLu^DWKj&2FoU=`5nZp~h~ z-A$+b)G0}kkFtxb&;JX$dR}y@hsr~~qwZ3>l0kw24=}`Kg&7(DvoIMj81R93{2(3+GZX6q12GU^ z6~yN;;9}#@W@BV!WoKqI5C@41g2Z_ZxSNooi=T}PsECEJ$vlJ+NHHSE0x*(+vB1cX zV(-cPey-AkleJ|DGGop$EPvMVonoxfNv zH=Vx7Ci4&1HQi~in*=N#-EVl9lo_q4DX?hWvkCupe%w`Bx5AF+_es&0la&hAMSi<} zJ6VEZ*{!Lk8;$ozvd3*)wrbbE^*0VmKQoFs65jRn2=CvOH^f#XtNl*An)OALN7}kQ zdwZnw&$VCHFHP3}&7u_4b>qaYPa7|sefX~V-L5-Hm$&oIPS-xL;Ed#ADT{EP?bQ>j P%Xzmis+z!lw__my11T}7 literal 0 HcmV?d00001 diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.key new file mode 100644 index 000000000000..34fba0f776de --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-aspnet.key @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNjBgBgkqhkiG9w0BBQ0wUzAyBgkqhkiG9w0BBQwwJQQQ93oRxzJ5UoNOb/zN +x5cdsAIDAYagMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBAuHsE18X/Z9ZVe +aBl7C55nBIIE0AABqjc9ERcLYNpCRpA6c/TFG62m4Mr9J4dU4g1WD07t7uLxZiRi +Pl0YOjCulljMsevAW5PlLxi4ffJ+I0/UB1WOfzEMhcj7o1qG0Uv55B7WRuWKw1Zr +jo0bDY5Man48ZjpqMMBdnWhyHdIDm+WD0OyN98mpsN6SCQMjvx91M+klrsp7LOMM +88HHS0RFVKGF9hYSy6rCwMJWf+7QGO2wXfq+MKvJ/bBgPGDLwN4phUCyocnR0swD +/XZNiiw0xIC8OxAKhc6BV4AJkjNs32THdBOCGY6B4P/9Zo5W29S3ja/hGsMQAA27 +QtIDg74HpX7TgIyqoc1oiLNIWW/+jUHSEYJsTPlg5VYWsXUfSHZpz8EJvKt2tyvt +vBGOCLDDZD4GVXhPigKG6zJSJeTe94/VlwPhNSEucKeaALdax5t3HvPNzWKFX57E +aC82/IxRrjgHmgsGSZdMi08HY6K9GAVBFpIGvXOGtRq7w8zO/KagAvSwAOLLtOs7 +iEuAQxD+cKLRT59c4E7r5W7BT+faq85ovqdXe5Edtl3cT81zsl27pZvQrcrTPbZe +4OeIdWxOmOnC/bXvRHNd9XuYadXXazBoFbe9yPwjqnflEh39CyvlOZXeaQXSdsEM +1IBhddRTorO/I8M/znu9glqIa5ya1NA+4ujmf4OnJLtsrlKQa65VPVTrFdeYuMr0 +VfOuuIye2OdyJ6jS0a1PYQm4bEEz6UR88dnmnhDx6i8/l2wW5+CArA/x8IBYboBM +NJpJY9bHpic1AhjnjnTtFz2s4uYPi5g9peBizarZn+6OJvgYqs4a8SI92dA3E2o4 +a/1j7xlLlgXnVRLBMibxqzjMt4Zt7Nj+BaN1owrB/q04AWS2M4TSQz+NYOZwNFxB +dzb+fysTLK5XNEYq6rSg+0i+EKZl8Jb/t4d8SLPVr/tdfDt9BtZ0nTgjvy1HWy1p +kQdm13XfK1/9KsePH/Jb6dvN/u6ubV+ZqI7Bc7VyTi0bKMdpH2K8/dtopNyDZ/P+ +/IsyyDYTorgJB/klSih/W0hqpSBbEAmlSBfBxP1/ozBEGR2oF20JOCFyD6UXQR/1 +V7r2KtplpyfXaIWh4fABitAMHz7VgmEIQ2H9cB4Ey9jdRPQ/1p+OgGjfaFJQ0uYM +987TDtjkuukJYnPZNIIx0Yv3iAX16XmhzJixWSMUIJiWfSiz0aTjBxsPQVPTQV+M +6BgFf3riBApZYlVVJsGIie2XTvu/tHRhfQrxccl63HN7yAeJheQnoscin6Z5TKN/ +U8Ouy/QGiATatKUEUjr4lN+BYySf8F6e3cAAeAx/ZnFvGw5z8fwNYBjVWg/83bTw +9rS+tSk8VsvTdkcKoNbbDtw+SwYfZSbMUBFm0B13190iJZoyWI+5ZKPnZ2CvOZhX +PjGTOnh6Diq907l2Q7S/v8SLe0bCHCHVBy+CcPWVDZ6Z7V5cJ/W8TvFPcSGw1UCl +tKPp862uDaPKvGxqGDq0vGouEUrtJKZ279Lnrtz1n8raUj0Gxa+KXqLACh8dXCzK +ZgCTPhfAjZcYgA73edW0whNNH9MNInDGulT/arCK3HTkFPczD+7wA8Ojw/LxKFJs +0d8vtILbmLv46CO+wvIdWrW1c7PCrGJDf9Zuw06vIH7hpW9swSM55k9/ +-----END ENCRYPTED PRIVATE KEY----- \ No newline at end of file diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key new file mode 100644 index 000000000000..c5230eb518b2 --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key @@ -0,0 +1,20 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIDVgIBAAKCAQEAz9N+6hnrhi1kF8To+Rxfm2f3rjF+l6SV559K8KGJVP+m730V +eI4GzZBQ0vdpZ58LRom59mhx1RQ6JJpl4TPdDeLGAaEvabmYP0c4AsDZbVui8nqo +aQY/haIaOR7FdNb4hpJhe2Scy6h2ftDr6l6fvQA6flHzzv9nOLMPPtnZMVdWzgvg +3TnNEEFdPrJWeSQD/4R614ZkmnozTS3vv1vnD1oi/OBjcJmrArjorIfvbBAc/eRT +kuayW7lAjBVFP34vZTfjuzaOFe9+fdOfHq52rmWUHr06rrlC6v4ynWJi/Z+pBQfn +7tCPO7CNmscF5s8D1+pI6i1GEn548yqj8W51pQIhAMkQtTVtwn/gXFCWKGeDZCUM +Rq4/ZsudU59GFuc4/7K1AoIBADmyd+UXxB+zYWitB391FqqHW3Nz2MT6MoJUkwwf +vSPSM5BK9TPicZJwNPFfsjosb2spSmVJ47BoEHxUmZVaaFhiZERSCpRCQlHaZHwM +3Q5rn8w981+gv6qQ93CMYP16u7rBoalrvloYUyD6gKzKnNvHCOMstqIC5dwsBsMA +5oM/4w4V99Od34CIv0rLUadBWvIBC5zD4idf8dKo6Cugx3Xy8TC93xHHvXtBHIe5 +YawTx/hVRxDrPxNDW6/Saxn6dQRDykIYsQVWfD5Kf79aK6DFr9qfm8a4PVhpCnIc +KCAio/hKnPkI7Doa6qwdH43fl7GttA1UyOeNRfCl0+w2i2UCggEABqgs/uZ1x7RQ +lRicSvZ7cqzBDtdTaWmTPqjoqowGLPUbQcaMyoKYJ2KdmZEuNDmcaC5Em8NgFMVJ +NGbaI5l2pcJj319pXlWuPmDdDNH4iwsGMhpSR9YTvPG5H+A2hFroQ+RmkpTrsqVJ +PJoqdNNXVZpWofrFUP7gPi+vQ4CHLVBg/fOcY6Qv2PU6RmTwuwuXzUiOfSFxoIy+ +gAvhRWIAcUipkb0Yneb6pfP4UiPvijuVuEV3y1dQa9y9B8Tbd57hw5RzQaL0cw1G +HzzUGItC8KyffQPl+ey5QRatbZ9rsJ6tfy+QCx4pJtJ2wJbPw1ZYl9R9liYBktHo +T1EZGHq6LAIhAKzMePNnv3YJH1V6+Y9ikL5rbDM0irbXPkrvxnUUDfZd +-----END DSA PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt new file mode 100644 index 0000000000000000000000000000000000000000..c62c2a5e9903d1c457734cf907312bba2bca8244 GIT binary patch literal 1276 zcmXqLV)jQGZP~dlSq!)xsnN5PpscK=iUqBx_3WHl8fDdn~gJ}&4V$OnT46j zAkvWAfRl|ml!Z;0$uZPW*gz1(;o#v4&d*KN4K7J6Ni|e7kOv8J@kn^)m82HsrIsj! zXQrfQmJ}-llvFDCl%yC683=%sF!ONcTQWaJl@7|4n98W|Xv8yFf|m|B{cMFF{n zNL*T4-Nfu>(8OfP#;(=oan6E;5y;VDYGPz$IDfhBmE`L--4yX7FMi6z&rbio&aiI! zlBv(ydiBp} zZc@_U`72r3pTE1%Z@r;+)^XNn=b5j+@_41|CRA7PS!?mfywasiiVPAAu4-Nc?-{NJ<{7)}h9o64VxACcdjn6Z|BVp_c|T8+%f7CBln!ckJRHoURv=&d%^M2Pah5T-WNQ+x7tyr zeP`kt;p0C--34CT3p+=zzmzTctCYq0l#|3p*035ouloH_+6#`ZzcqjMu^qM%nOsFO z8VX8_e|XLL$??WY>eU)q`QH1}H?G~n8*<`#uj_}Um*1Fmr!qG&vNC`If^CJ)zh|Y# zw**X;nB(=Wx@gTozU#r6nUn2Syja!4rt?+W@mSBPrWxuV@-@v`JH5Z(8bU zGfS)Fa(L*hu!X;l2K;+qr@!90p@TE)TzJ^LEC zAG#(n6ndOS7v)uS!UvTZNqi*Q@Y9gO*OHS~GW s1K~qV3O;Y7{!Qq7uli<1#I9qKb)PD)9`DI`%cL;j@y6)W60^1d0Q(3Q0{{R3 literal 0 HcmV?d00001 diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key new file mode 100644 index 000000000000..6b9002b25aea --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key @@ -0,0 +1,23 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,25877371F267513A + +0trY+6ZmQGWPwtcQUt948x5ZJ+aYpYLdOeGzqHqIUI0zVQ2PhuBOo5euR6tVNvHd ++R3EHDpt1I2xQVkr3Opnfe9AbXO4PT67sj8TQeUWFN1HcrpqfwL8nL3nQqLXtynp +jxQ4GdJQ/9pQPB6k4uLhLI43FM9nGIaeGTBPi5mCu5p2PpvPoScy1iwK9V2/ERnH +FJAmV/4ASJXQw9Ww2uY8raDvrVHpX0UHQPuxjQXtOghQjik9XWZA15cp6s18OKd/ +ck+fNg04b7tSsbwEcB4FTzw/UqZWSGeKLhDVXSPWhNjKD14j839tN6kqY5u6FSsJ +7kslskJow8pRuWiR/B/LiTVOJH99kwL3lslKejWhG0Skx8vXoQndLtp5D7WNufsd +78HaBhZhuI/JBR2Pwx/UQBfsz+h3rZHKgwLqxo6+Mii6TEc3qFMsfuvRJAbKun6q +sYSX+ZH7Ju44ZjWzHNuqsixifWMsIyw8jQ1ocK3MjKUFbracjPc6lnAPZjGeqHgg +cxkCS80LjNyZ64BXYhnPwQZs4KKGtGOXvwNuM0aspTFX+5o4Azde5tTSd86Bze2v +jAXa4ZhtlxBa5KInRNuTUOKdCFQX3KkNsvlVRmKrOFc6rlGdLpSe901XYBe6Zbu0 +OMq7wMYLe8iGSvtdvZXngKEjZ9F4RBwC313Q0rQ6diuVZ9u58PzcZC/Cp0Qx3AB7 +GJhsixSL+4rswQUX9Bvhrm3QhuFSNXIa/oQ/xC4kLajbyvnbOQSTk36dRdpjyFwx +LbyW1wl1wFB8lMXdzfssCd6S86ZZHIa2QJCL/ZSH2E+zahn+3RXgBMK2MN4aJM2n +r2Z2aLi6A1qN5eMVULwGY4eiciz2TbJwjsdTaQnM70hsb5/mu4liIygZ2Ly79Y9q +JTdKP0gP4lyFhrs+G6j2DoCD0YPqhn8E5jpokkKDAitqxe4nDyHVM97p/Ax7X4IR +XydpRaAiKAVBO3rquV1pBl/CVynD0QDeyjfq8ve8viPtU/9oXUiaXJurqIkJ/HN5 +MlprNG+Svaa5mtf7HgMqDk7YgGXyyBE4dFL68x/Ye4+7JfvQAUwyb46h3QIhwSKI +NrAjZxA0i+Lla4w2bXNZXxfK38EldZm7gpVzbay1c//TAxXZz7NnNLOed8b7u1zZ +-----END DSA PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.crt new file mode 100644 index 0000000000000000000000000000000000000000..618ba1f992da31e9abbb91e23577b255eb219525 GIT binary patch literal 1431 zcmXqLVx4Tz#9Y0AnTe5!NyPMH*yY_`hpwrwic8Ap@zZ+f*=kD4_9!0ZmMo@Nn%N=p`w92NRW$1!ZWWVwJ0yO zL?JvgB|WpGSRtUKQo*Mr#ZbsV0HlPOhchQXIWZ?AzqrIePMp`sz`)$V5J;LDnnnS+ zhDcmmTHVB?gzQm9RtDxKCVmEkCMGVXCMHIPz0-eYa8+DSXuPh+@TRHYex$D4fvZ+) zI|^r-zGn$*U=sPm)A{siYSq>Iob2V4@QQbo@VrCdc<2#mfZ|0F%#K~Z9J}VmcGm| z4BhkORKcX{wLiQTc1zS*+~el#ElK?U_7`jD!vl6)OsiX(ZC<+6^^_f-mbz#A%_}d? zHyn4on}1)lHTg?O?lxgr*0#*Ff+qQ0Zk=IS*Mzn_KK*R9@ZH~1s~iXm!UuJu|bu;ZB{bRfIV}A9fNt2t*d+&k435+jUtYq#x@%BWkR&bDwV{}snw zh1T}--RyYJiPiKk5!Nqmo+wj);nS6GJokU`=OoBPyUk#B_*5Ky+4WNXE$fLpPI<`f zU*T+=nb^~QU%|3eCi94;-rBWM71Nen+fno7{wK?|opKz0NB(@An=m^v`XCcCBLm~& zV1qydSzxl2l) zZER8f4xwE$XPCWcd~u<{K6>R{Te(HX->z87f1KnmHo1Ut$-#Qp-Wm5Sbmd!8wz^C8 zY&>5ft);PZhBW`R`KI%8vcx>t-uPeMwZuK3qqgJZYGv*>W*6Uh&2=nSe5J!>{h|ex_Tf@vi(g=Scjf zMW)i*tAo7HOKp;ieWqeuP{BK+$2io|PuBI%PEOSmd9NqepXB?>@>Y3?{^W-J9n|x!I?CWLhoaR+jdbIE3@J|SF6Y0zkMN6$`SUbvQ@d76ef(rzp|A3c zFJ6WB8k~2!aW!FMazoroZF5TMm!0t7>!rDUSd-=A3)H-F? zDQmAQ@%%O_t^Tj&{?%;dLB20%m)z0v^<;=pDDab?v3B$ABRxHN%4@f`ezf*UkodFa z`y!#%$FE;m-dAOdKHCv;Cb%}M|Ln%BCt8Ak>)STIIv%%7@>_A>ve~}pbgo{$68pe; zQu$LMv;4PL*M9ia`K^gFW8cnVuO)XHUjE-7$Qe>*JNa0OOWXWaJl0nGEtmf(KR9FW qk+p8T-;CcK Date: Wed, 1 Jul 2020 14:05:51 -0700 Subject: [PATCH 2/9] Add PEM support --- src/Servers/Kestrel/Core/src/CoreStrings.resx | 3 + .../Core/src/Internal/ConfigurationReader.cs | 2 + .../Core/src/KestrelConfigurationLoader.cs | 63 ++++++++ ...spNetCore.Server.Kestrel.Core.Tests.csproj | 2 + .../test/KestrelConfigurationLoaderTests.cs | 137 +++++++++++++++++- ...oft.AspNetCore.Server.Kestrel.Tests.csproj | 2 + 6 files changed, 208 insertions(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Core/src/CoreStrings.resx b/src/Servers/Kestrel/Core/src/CoreStrings.resx index 46f2e263a326..57fb521b78d7 100644 --- a/src/Servers/Kestrel/Core/src/CoreStrings.resx +++ b/src/Servers/Kestrel/Core/src/CoreStrings.resx @@ -614,4 +614,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l A TimeSpan value greater than or equal to {value} is required. + + The provided key file is missing or invalid. + \ No newline at end of file diff --git a/src/Servers/Kestrel/Core/src/Internal/ConfigurationReader.cs b/src/Servers/Kestrel/Core/src/Internal/ConfigurationReader.cs index 31e4270131bd..2843bb014c5e 100644 --- a/src/Servers/Kestrel/Core/src/Internal/ConfigurationReader.cs +++ b/src/Servers/Kestrel/Core/src/Internal/ConfigurationReader.cs @@ -205,6 +205,8 @@ public CertificateConfig(IConfigurationSection configSection) public string Path { get; set; } + public string KeyPath { get; set; } + public string Password { get; set; } // Cert store diff --git a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs index ad7210b6d655..c00ecf8dadc8 100644 --- a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs +++ b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs @@ -436,6 +436,23 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp else if (certInfo.IsFileCert) { var env = Options.ApplicationServices.GetRequiredService(); + if (certInfo.KeyPath != null) + { + if (TryReadPemRSAKey(certInfo, out var rsaKey)) + { + var publicCertificate = new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path)); + return publicCertificate.CopyWithPrivateKey(rsaKey); + } + + if (TryReadPemDSAKey(certInfo, out var dsaKey)) + { + var publicCertificate = new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path)); + return publicCertificate.CopyWithPrivateKey(dsaKey); + } + + throw new InvalidOperationException(CoreStrings.InvalidPemKey); + } + return new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path), certInfo.Password); } else if (certInfo.IsStoreCert) @@ -445,6 +462,52 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp return null; } + private static bool TryReadPemRSAKey(CertificateConfig certInfo, out RSA key) + { + try + { + var rsaKey = RSA.Create(); + if (certInfo.Password == null) + { + rsaKey.ImportFromPem(File.ReadAllText(certInfo.KeyPath)); + } + else + { + rsaKey.ImportFromEncryptedPem(File.ReadAllText(certInfo.KeyPath), certInfo.Password); + } + key = rsaKey; + return true; + } + catch + { + key = null; + return false; + } + } + + private static bool TryReadPemDSAKey(CertificateConfig certInfo, out DSA dsaKey) + { + try + { + var dsa = DSA.Create(); + if (certInfo.Password == null) + { + dsa.ImportFromPem(File.ReadAllText(certInfo.KeyPath)); + } + else + { + dsa.ImportFromEncryptedPem(File.ReadAllText(certInfo.KeyPath), certInfo.Password); + } + dsaKey = dsa; + return true; + } + catch + { + dsaKey = null; + return false; + } + } + private static X509Certificate2 LoadFromStoreCert(CertificateConfig certInfo) { var subject = certInfo.Subject; diff --git a/src/Servers/Kestrel/Core/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj b/src/Servers/Kestrel/Core/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj index 108edc514d13..8786fa6969ee 100644 --- a/src/Servers/Kestrel/Core/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj +++ b/src/Servers/Kestrel/Core/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj @@ -13,6 +13,8 @@ + + diff --git a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs index fb0b182cdd28..a52a96bd751e 100644 --- a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs +++ b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs @@ -25,7 +25,7 @@ public class KestrelConfigurationLoaderTests private KestrelServerOptions CreateServerOptions() { var serverOptions = new KestrelServerOptions(); - var env = new MockHostingEnvironment { ApplicationName = "TestApplication" }; + var env = new MockHostingEnvironment { ApplicationName = "TestApplication", ContentRootPath = Directory.GetCurrentDirectory() }; serverOptions.ApplicationServices = new ServiceCollection() .AddLogging() .AddSingleton(env) @@ -254,6 +254,141 @@ public void ConfigureEndpointDevelopmentCertificateGetsLoadedWhenPresent() } } + [Fact] + public void ConfigureEndpoint_CanLoadRsaPemCerts() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-rsa.crt")); + + var ran1 = false; + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-rsa.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-rsa.key")), + }).Build(); + + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + ran1 = true; + Assert.True(opt.IsHttps); + Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); + }).Load(); + + Assert.True(ran1); + Assert.NotNull(serverOptions.DefaultCertificate); + } + + [Fact] + public void ConfigureEndpoint_CanLoadProtectedRsaPemCerts() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-aspnet.crt")); + + var ran1 = false; + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-aspnet.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-aspnet.key")), + new KeyValuePair("Certificates:Default:Password", "aspnetcore"), + }).Build(); + + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + ran1 = true; + Assert.True(opt.IsHttps); + Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); + }).Load(); + + Assert.True(ran1); + Assert.NotNull(serverOptions.DefaultCertificate); + } + + [Fact] + public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-aspnet.crt")); + + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-aspnet.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-aspnet.key")) + }).Build(); + + var ex = Assert.Throws(() => + { + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + Assert.True(opt.IsHttps); + }).Load(); + }); + Assert.Equal(CoreStrings.InvalidPemKey, ex.Message); + } + + [Fact] + public void ConfigureEndpoint_CanLoadDsaPemCerts() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-dsa.crt")); + + var ran1 = false; + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-dsa.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-dsa.key")), + new KeyValuePair("Certificates:Default:Password", "asdf"), + }).Build(); + + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + ran1 = true; + Assert.True(opt.IsHttps); + Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); + }).Load(); + + Assert.True(ran1); + Assert.NotNull(serverOptions.DefaultCertificate); + } + + [Fact] + public void ConfigureEndpoint_CanLoadUnprotectedDsaPemCerts() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-dsa.crt")); + + var ran1 = false; + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-dsa.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-dsa-no-pass.key")), + }).Build(); + + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + ran1 = true; + Assert.True(opt.IsHttps); + Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); + }).Load(); + + Assert.True(ran1); + Assert.NotNull(serverOptions.DefaultCertificate); + } + [Fact] public void ConfigureEndpointDevelopmentCertificateGetsIgnoredIfPasswordIsNotCorrect() { diff --git a/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj b/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj index 571f2cda3028..731b0df05eec 100644 --- a/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj +++ b/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj @@ -8,6 +8,8 @@ + + From eb7ddcd3a525f56126577b9742748dc61cdadccf Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 1 Jul 2020 15:23:07 -0700 Subject: [PATCH 3/9] Force the keys to be persisted on windows --- .../Kestrel/Core/src/KestrelConfigurationLoader.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs index c00ecf8dadc8..124ac45395e0 100644 --- a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs +++ b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Net; +using System.Runtime.InteropServices; using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; @@ -441,7 +442,14 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp if (TryReadPemRSAKey(certInfo, out var rsaKey)) { var publicCertificate = new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path)); - return publicCertificate.CopyWithPrivateKey(rsaKey); + var fullCertificate = publicCertificate.CopyWithPrivateKey(rsaKey); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // We need to force the key to be persisted. + // See https://github.com/dotnet/runtime/issues/23749 + var certificateBytes = fullCertificate.Export(X509ContentType.Pkcs12, ""); + return new X509Certificate2(certificateBytes, "", X509KeyStorageFlags.DefaultKeySet); + } } if (TryReadPemDSAKey(certInfo, out var dsaKey)) From aeb9ea7f7d4621e6e16eddbd37fb00c21f2f7a2a Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 1 Jul 2020 16:38:25 -0700 Subject: [PATCH 4/9] Add an E2E test for ensuring the key works --- .../Core/src/KestrelConfigurationLoader.cs | 54 ++++++++++++------- .../HttpsConnectionMiddlewareTests.cs | 39 ++++++++++++++ .../InMemory.FunctionalTests.csproj | 2 + 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs index 124ac45395e0..2df4ffd16491 100644 --- a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs +++ b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs @@ -436,52 +436,65 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp } else if (certInfo.IsFileCert) { - var env = Options.ApplicationServices.GetRequiredService(); + var environment = Options.ApplicationServices.GetRequiredService(); if (certInfo.KeyPath != null) { - if (TryReadPemRSAKey(certInfo, out var rsaKey)) + X509Certificate2 certificate = null; + if (TryReadPemRSAKey(certInfo, environment, out var rsaKey)) + { + var publicCertificate = new X509Certificate2(Path.Combine(environment.ContentRootPath, certInfo.Path)); + certificate = publicCertificate.CopyWithPrivateKey(rsaKey); + } + + if (TryReadPemDSAKey(certInfo, environment, out var dsaKey)) + { + var publicCertificate = new X509Certificate2(Path.Combine(environment.ContentRootPath, certInfo.Path)); + certificate = publicCertificate.CopyWithPrivateKey(dsaKey); + } + + if (certificate != null) { - var publicCertificate = new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path)); - var fullCertificate = publicCertificate.CopyWithPrivateKey(rsaKey); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - // We need to force the key to be persisted. - // See https://github.com/dotnet/runtime/issues/23749 - var certificateBytes = fullCertificate.Export(X509ContentType.Pkcs12, ""); - return new X509Certificate2(certificateBytes, "", X509KeyStorageFlags.DefaultKeySet); + return PersistKey(certificate); } - } - if (TryReadPemDSAKey(certInfo, out var dsaKey)) - { - var publicCertificate = new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path)); - return publicCertificate.CopyWithPrivateKey(dsaKey); + return certificate; } throw new InvalidOperationException(CoreStrings.InvalidPemKey); } - return new X509Certificate2(Path.Combine(env.ContentRootPath, certInfo.Path), certInfo.Password); + return new X509Certificate2(Path.Combine(environment.ContentRootPath, certInfo.Path), certInfo.Password); } else if (certInfo.IsStoreCert) { return LoadFromStoreCert(certInfo); } return null; + + static X509Certificate2 PersistKey(X509Certificate2 fullCertificate) + { + // We need to force the key to be persisted. + // See https://github.com/dotnet/runtime/issues/23749 + var certificateBytes = fullCertificate.Export(X509ContentType.Pkcs12, ""); + return new X509Certificate2(certificateBytes, "", X509KeyStorageFlags.DefaultKeySet); + } } - private static bool TryReadPemRSAKey(CertificateConfig certInfo, out RSA key) + private static bool TryReadPemRSAKey(CertificateConfig certInfo, IHostEnvironment environment, out RSA key) { try { + var keyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); var rsaKey = RSA.Create(); if (certInfo.Password == null) { - rsaKey.ImportFromPem(File.ReadAllText(certInfo.KeyPath)); + rsaKey.ImportFromPem(File.ReadAllText(keyPath)); } else { - rsaKey.ImportFromEncryptedPem(File.ReadAllText(certInfo.KeyPath), certInfo.Password); + rsaKey.ImportFromEncryptedPem(File.ReadAllText(keyPath), certInfo.Password); } key = rsaKey; return true; @@ -493,18 +506,19 @@ private static bool TryReadPemRSAKey(CertificateConfig certInfo, out RSA key) } } - private static bool TryReadPemDSAKey(CertificateConfig certInfo, out DSA dsaKey) + private static bool TryReadPemDSAKey(CertificateConfig certInfo, IHostEnvironment environment, out DSA dsaKey) { try { + var keyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); var dsa = DSA.Create(); if (certInfo.Password == null) { - dsa.ImportFromPem(File.ReadAllText(certInfo.KeyPath)); + dsa.ImportFromPem(File.ReadAllText(keyPath)); } else { - dsa.ImportFromEncryptedPem(File.ReadAllText(certInfo.KeyPath), certInfo.Password); + dsa.ImportFromEncryptedPem(File.ReadAllText(keyPath), certInfo.Password); } dsaKey = dsa; return true; diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsConnectionMiddlewareTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsConnectionMiddlewareTests.cs index fe0b8dae14fd..70b216e149e7 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsConnectionMiddlewareTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsConnectionMiddlewareTests.cs @@ -21,7 +21,11 @@ using Microsoft.AspNetCore.Server.Kestrel.Https.Internal; using Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.TestTransport; using Microsoft.AspNetCore.Testing; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging.Testing; +using Moq; using Xunit; namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests @@ -51,6 +55,41 @@ void ConfigureListenOptions(ListenOptions listenOptions) } } + [Fact] + public async Task CanReadAndWriteWithHttpsConnectionMiddlewareWithPemCertificate() + { + var configuration = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary + { + ["Certificates:Default:Path"] = Path.Combine("shared", "TestCertificates", "https-aspnet.crt"), + ["Certificates:Default:KeyPath"] = Path.Combine("shared", "TestCertificates", "https-aspnet.key"), + ["Certificates:Default:Password"] = "aspnetcore", + }).Build(); + + var options = new KestrelServerOptions(); + var env = new Mock(); + env.SetupGet(e => e.ContentRootPath).Returns(Directory.GetCurrentDirectory()); + + options.ApplicationServices = new ServiceCollection().AddSingleton(env.Object).AddLogging().BuildServiceProvider(); + var loader = new KestrelConfigurationLoader(options, configuration, reloadOnChange: false); + loader.Load(); + void ConfigureListenOptions(ListenOptions listenOptions) + { + listenOptions.KestrelServerOptions = options; + listenOptions.UseHttps(); + }; + + await using (var server = new TestServer(App, new TestServiceContext(LoggerFactory), ConfigureListenOptions)) + { + var result = await server.HttpClientSlim.PostAsync($"https://localhost:{server.Port}/", + new FormUrlEncodedContent(new[] { + new KeyValuePair("content", "Hello World?") + }), + validateCertificate: false); + + Assert.Equal("content=Hello+World%3F", result); + } + } + [Fact] public async Task HandshakeDetailsAreAvailable() { diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/InMemory.FunctionalTests.csproj b/src/Servers/Kestrel/test/InMemory.FunctionalTests/InMemory.FunctionalTests.csproj index 952a0a9f50c9..ba3a4b8e0b05 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/InMemory.FunctionalTests.csproj +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/InMemory.FunctionalTests.csproj @@ -11,6 +11,8 @@ + + From e05299f3ae7504d7df00304e5ca16c497cf759e3 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 2 Jul 2020 10:28:36 -0700 Subject: [PATCH 5/9] Cleanups --- .../Core/src/KestrelConfigurationLoader.cs | 101 ++++++++++++------ .../test/KestrelConfigurationLoaderTests.cs | 57 ++++------ ...oft.AspNetCore.Server.Kestrel.Tests.csproj | 1 + .../test/TestCertificates/.gitattributes | 1 + .../TestCertificates/https-dsa-no-pass.key | 20 ---- .../TestCertificates/https-dsa-protected.key | 18 ++++ .../test/TestCertificates/https-dsa.crt | Bin 1276 -> 1185 bytes .../test/TestCertificates/https-dsa.key | 38 +++---- .../test/TestCertificates/https-dsa.pem | 27 +++++ .../https-ecdsa-protected.key | 7 ++ .../test/TestCertificates/https-ecdsa.crt | Bin 0 -> 522 bytes .../test/TestCertificates/https-ecdsa.key | 8 ++ .../test/TestCertificates/https-ecdsa.pem | 13 +++ .../TestCertificates/https-rsa-protected.key | 30 ++++++ .../test/TestCertificates/https-rsa.crt | Bin 1431 -> 784 bytes .../test/TestCertificates/https-rsa.key | 79 +++++--------- .../test/TestCertificates/https-rsa.pem | 19 ++++ .../InMemory.FunctionalTests.csproj | 1 + 18 files changed, 256 insertions(+), 164 deletions(-) delete mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa-protected.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.crt create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.pem create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-rsa-protected.key create mode 100644 src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.pem diff --git a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs index 2df4ffd16491..572144698277 100644 --- a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs +++ b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs @@ -437,19 +437,15 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp else if (certInfo.IsFileCert) { var environment = Options.ApplicationServices.GetRequiredService(); + var certificatePath = Path.Combine(environment.ContentRootPath, certInfo.Path); if (certInfo.KeyPath != null) { - X509Certificate2 certificate = null; - if (TryReadPemRSAKey(certInfo, environment, out var rsaKey)) - { - var publicCertificate = new X509Certificate2(Path.Combine(environment.ContentRootPath, certInfo.Path)); - certificate = publicCertificate.CopyWithPrivateKey(rsaKey); - } + var certificateKeyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); + X509Certificate2 certificate = GetCertificate(certInfo, certificatePath, certificateKeyPath); - if (TryReadPemDSAKey(certInfo, environment, out var dsaKey)) + if (!certificate.HasPrivateKey) { - var publicCertificate = new X509Certificate2(Path.Combine(environment.ContentRootPath, certInfo.Path)); - certificate = publicCertificate.CopyWithPrivateKey(dsaKey); + certificate = LoadCertificateKey(certificate, certificateKeyPath, certInfo.Password); } if (certificate != null) @@ -480,54 +476,89 @@ static X509Certificate2 PersistKey(X509Certificate2 fullCertificate) var certificateBytes = fullCertificate.Export(X509ContentType.Pkcs12, ""); return new X509Certificate2(certificateBytes, "", X509KeyStorageFlags.DefaultKeySet); } + + static X509Certificate2 LoadCertificateKey(X509Certificate2 certificate, string keyPath, string password) + { + var keyText = File.ReadAllText(keyPath); + return TryAttachPemRSAKey(certificate, keyText, password) ?? + TryAttachPemDSAKey(certificate, keyText, password) ?? + TryAttachPemECDSAKey(certificate, keyText, password); + } + + static X509Certificate2 GetCertificate(CertificateConfig certInfo, string certificatePath, string certificateKeyPath) + { + if (X509Certificate2.GetCertContentType(certificatePath) != X509ContentType.Unknown) + { + return new X509Certificate2(certificatePath); + } + + return certInfo.Password != null ? + X509Certificate2.CreateFromEncryptedPemFile(certificatePath, certInfo.Password, certificateKeyPath) : + X509Certificate2.CreateFromPemFile(certificatePath, certificateKeyPath); + } } - private static bool TryReadPemRSAKey(CertificateConfig certInfo, IHostEnvironment environment, out RSA key) + private static X509Certificate2 TryAttachPemRSAKey(X509Certificate2 certificate, string keyText, string password) { - try + const string RSAOid = "1.2.840.113549.1.1.1"; + if (string.Equals(RSAOid, certificate.PublicKey.Oid.Value, StringComparison.Ordinal)) { - var keyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); - var rsaKey = RSA.Create(); - if (certInfo.Password == null) + using var rsa = RSA.Create(); + if (password == null) { - rsaKey.ImportFromPem(File.ReadAllText(keyPath)); + rsa.ImportFromPem(keyText); } else { - rsaKey.ImportFromEncryptedPem(File.ReadAllText(keyPath), certInfo.Password); + rsa.ImportFromEncryptedPem(keyText, password); } - key = rsaKey; - return true; - } - catch - { - key = null; - return false; + + return certificate.CopyWithPrivateKey(rsa); } + + return null; } - private static bool TryReadPemDSAKey(CertificateConfig certInfo, IHostEnvironment environment, out DSA dsaKey) + private static X509Certificate2 TryAttachPemDSAKey(X509Certificate2 certificate, string keyText, string password) { - try + const string DSAOid = "1.2.840.10040.4.1"; + if (string.Equals(DSAOid, certificate.PublicKey.Oid.Value, StringComparison.Ordinal)) { - var keyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); - var dsa = DSA.Create(); - if (certInfo.Password == null) + using var dsa = DSA.Create(); + if (password == null) { - dsa.ImportFromPem(File.ReadAllText(keyPath)); + dsa.ImportFromPem(keyText); } else { - dsa.ImportFromEncryptedPem(File.ReadAllText(keyPath), certInfo.Password); + dsa.ImportFromEncryptedPem(keyText, password); } - dsaKey = dsa; - return true; + + return certificate.CopyWithPrivateKey(dsa); } - catch + + return null; + } + + private static X509Certificate2 TryAttachPemECDSAKey(X509Certificate2 certificate, string keyText, string password) + { + const string ECDsaOid = "1.2.840.10045.2.1"; + if (string.Equals(ECDsaOid, certificate.PublicKey.Oid.Value, StringComparison.Ordinal)) { - dsaKey = null; - return false; + using var ecdsa = ECDsa.Create(); + if (password == null) + { + ecdsa.ImportFromPem(keyText); + } + else + { + ecdsa.ImportFromEncryptedPem(keyText, password); + } + + return certificate.CopyWithPrivateKey(ecdsa); } + + return null; } private static X509Certificate2 LoadFromStoreCert(CertificateConfig certInfo) diff --git a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs index a52a96bd751e..66dedbabec89 100644 --- a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs +++ b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Security.Authentication; +using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using Microsoft.AspNetCore.Hosting; @@ -334,47 +335,33 @@ public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() Assert.Equal(CoreStrings.InvalidPemKey, ex.Message); } - [Fact] - public void ConfigureEndpoint_CanLoadDsaPemCerts() - { - var serverOptions = CreateServerOptions(); - var certificate = new X509Certificate2(TestResources.GetCertPath("https-dsa.crt")); - - var ran1 = false; - var config = new ConfigurationBuilder().AddInMemoryCollection(new[] - { - new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), - new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-dsa.crt")), - new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-dsa.key")), - new KeyValuePair("Certificates:Default:Password", "asdf"), - }).Build(); - - serverOptions - .Configure(config) - .Endpoint("End1", opt => - { - ran1 = true; - Assert.True(opt.IsHttps); - Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); - }).Load(); - - Assert.True(ran1); - Assert.NotNull(serverOptions.DefaultCertificate); - } - - [Fact] - public void ConfigureEndpoint_CanLoadUnprotectedDsaPemCerts() + [Theory] + [InlineData("https-rsa.pem", "https-rsa.key", null)] + [InlineData("https-rsa.pem", "https-rsa-protected.key", "aspnetcore")] + [InlineData("https-rsa.crt", "https-rsa.key", null)] + [InlineData("https-rsa.crt", "https-rsa-protected.key", "aspnetcore")] + [InlineData("https-ecdsa.pem", "https-ecdsa.key", null)] + [InlineData("https-ecdsa.pem", "https-ecdsa-protected.key", "aspnetcore")] + [InlineData("https-ecdsa.crt", "https-ecdsa.key", null)] + [InlineData("https-ecdsa.crt", "https-ecdsa-protected.key", "aspnetcore")] + //[InlineData("https-dsa.pem", "https-dsa.key", null)] + //[InlineData("https-dsa.pem", "https-dsa-protected.key", "aspnetcore")] + //[InlineData("https-dsa.crt", "https-dsa.key", null)] + //[InlineData("https-dsa.crt", "https-dsa-protected.key", "aspnetcore")] + public void ConfigureEndpoint_CanLoadPemCertificates(string certificateFile, string certificateKey, string password) { var serverOptions = CreateServerOptions(); - var certificate = new X509Certificate2(TestResources.GetCertPath("https-dsa.crt")); + var certificate = new X509Certificate2(TestResources.GetCertPath(Path.ChangeExtension(certificateFile, "crt"))); var ran1 = false; var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { - new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), - new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-dsa.crt")), - new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-dsa-no-pass.key")), - }).Build(); + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", certificateFile)), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", certificateKey)), + } + .Concat(password != null ? new[] { new KeyValuePair("Certificates:Default:Password", password) } : Array.Empty>())) + .Build(); serverOptions .Configure(config) diff --git a/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj b/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj index 731b0df05eec..f4106e104099 100644 --- a/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj +++ b/src/Servers/Kestrel/Kestrel/test/Microsoft.AspNetCore.Server.Kestrel.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes b/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes index 9fb7e61e8dba..911dbdca5c4b 100644 --- a/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes +++ b/src/Servers/Kestrel/shared/test/TestCertificates/.gitattributes @@ -1 +1,2 @@ *.key binary +*.pem binary diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key deleted file mode 100644 index c5230eb518b2..000000000000 --- a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-no-pass.key +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIDVgIBAAKCAQEAz9N+6hnrhi1kF8To+Rxfm2f3rjF+l6SV559K8KGJVP+m730V -eI4GzZBQ0vdpZ58LRom59mhx1RQ6JJpl4TPdDeLGAaEvabmYP0c4AsDZbVui8nqo -aQY/haIaOR7FdNb4hpJhe2Scy6h2ftDr6l6fvQA6flHzzv9nOLMPPtnZMVdWzgvg -3TnNEEFdPrJWeSQD/4R614ZkmnozTS3vv1vnD1oi/OBjcJmrArjorIfvbBAc/eRT -kuayW7lAjBVFP34vZTfjuzaOFe9+fdOfHq52rmWUHr06rrlC6v4ynWJi/Z+pBQfn -7tCPO7CNmscF5s8D1+pI6i1GEn548yqj8W51pQIhAMkQtTVtwn/gXFCWKGeDZCUM -Rq4/ZsudU59GFuc4/7K1AoIBADmyd+UXxB+zYWitB391FqqHW3Nz2MT6MoJUkwwf -vSPSM5BK9TPicZJwNPFfsjosb2spSmVJ47BoEHxUmZVaaFhiZERSCpRCQlHaZHwM -3Q5rn8w981+gv6qQ93CMYP16u7rBoalrvloYUyD6gKzKnNvHCOMstqIC5dwsBsMA -5oM/4w4V99Od34CIv0rLUadBWvIBC5zD4idf8dKo6Cugx3Xy8TC93xHHvXtBHIe5 -YawTx/hVRxDrPxNDW6/Saxn6dQRDykIYsQVWfD5Kf79aK6DFr9qfm8a4PVhpCnIc -KCAio/hKnPkI7Doa6qwdH43fl7GttA1UyOeNRfCl0+w2i2UCggEABqgs/uZ1x7RQ -lRicSvZ7cqzBDtdTaWmTPqjoqowGLPUbQcaMyoKYJ2KdmZEuNDmcaC5Em8NgFMVJ -NGbaI5l2pcJj319pXlWuPmDdDNH4iwsGMhpSR9YTvPG5H+A2hFroQ+RmkpTrsqVJ -PJoqdNNXVZpWofrFUP7gPi+vQ4CHLVBg/fOcY6Qv2PU6RmTwuwuXzUiOfSFxoIy+ -gAvhRWIAcUipkb0Yneb6pfP4UiPvijuVuEV3y1dQa9y9B8Tbd57hw5RzQaL0cw1G -HzzUGItC8KyffQPl+ey5QRatbZ9rsJ6tfy+QCx4pJtJ2wJbPw1ZYl9R9liYBktHo -T1EZGHq6LAIhAKzMePNnv3YJH1V6+Y9ikL5rbDM0irbXPkrvxnUUDfZd ------END DSA PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key new file mode 100644 index 000000000000..dea23f907c65 --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key @@ -0,0 +1,18 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICzTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIgeRX7Sed0OsCAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBC7vpWM+TQ9caiqYAn+h95YBIIC +cM8+gZPkVJZF1ICFi6lHHNjV9FSdH+qwvUOzBEVP1oZtmdMBhEVqqm+3H+Gcm6dn +C4JjMGCu3KqQ096JoWeFE/ksuTcL7MBtvyY35NIbbVxEW7YxvTiICADfjwL0mDYH +SlUr0LLrMhoYfN01HE2kkkJLZLt58zjzxyUdc//SlIC6rJyd6NZdNrmRQ9JZzd7G +SZtkXRMvrzyJoxwOc+5ERmYtOtOWmyF2pAFwoEnb8VOQgoM3gy/3lO5aVpPj76Rr +MmJwdruU39nUPTe6VI6ukF5T27pu0XmX5YWqy5+PZ5cFhmOxGSxwvw6dbJSM1+Sg +ZcKohhQQtNFYFgFpp8cz84o1lHWprjGxHRVKEeKAwgX8v8glDTKzwS0DKsTzdn0s +2RCwjr+GxH7wpjwzllny2xU/h5ZR2j8gldfCNFVPtFrGleuEduPA4U04Mkije0l9 +AdPHDK8drvUuIZLb2HCQu0wYmUDmtY/SWuMl1xRonrF+cPPcmAdQDP8IH2MGL8SO +9h/CCextHsqzXl7PJzHcjLmn8qmlocmSJRALCrWpgoE/d7Wjle8LmtQVWSw0UgTo +GEoWpFcz6JJBUrcasGQHokLtuyAjjSRgSt1DFK2iW+O7MARK9wJNCGUfDNWavO4p +hA7MR1muv/xwwr0oi2OJ5rc3N+6M/Fb1fRlU5+EsaE2xee7nV3JdVmdYKpOM8ksX +F5XV/b4BbaPbTRppr0aZk6RDqy5jlYVsNy1Npwqw/2pJqS7wTWZgaWQgePsRGsb5 +3SZC64XpHlzBgYOgpnOC9x9KJuWt2z4OS0l70Nvv7+VLzem0fVMb+Dh/5VFjYfp2 +4w== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt index c62c2a5e9903d1c457734cf907312bba2bca8244..26993c7406a5d6a1885fd17d0e369180ef436fa3 100644 GIT binary patch delta 979 zcmV;^11$Xf384udFoFb~FoFa_0u&+b)ChXJ#7fJra93!#1jpb3R0@$JaThW%H!v|Y zF*WrrckOX*&I{w?ts{$uO}p+w zqFPihIAe0CR?FQ>&V5iDC|3+R>6wN5Y)bLef7Ced6uDfWTZD>pQXH`@R5;(6szGKB zrh1E;m?gzb6raG#d{~Z8IpUezse*Bkx0#c5QhOk7d*SdWYAe>X!o zi)XsW^S-&x>+$34xevsmjqu_lKUWdTRI_L}6`8^V;S!u~m@#aX5t^51`yy2$w_8LD z**y<^hWS$af~&NfqR!-%$uv?NQ=~`VrUQJpcX=|K!I;onp6-uQWJmYqn@mycg%v7i z6|+PdTbJ^B=WY2;{CpvwcfgWse`f;%AppEK&|hu!cA^Kd2aisK?23C-nY&2)^D3#^`e+VHFiaf=ria%2NJ=sF~z=pKTyH-W^tUk z#JZ}MhN(HxJ9;&V>avGEWHX!Y_q(_53^a){Ud(G1LrB8rlqtzO&Mh|3e~ZZ*7{Ejt#v3cgNa%-~Xdpjq>rkCI#09zi4 zZ0EILt+a5n1A+ks00M#m04^y@EuCQ0DACkB6l_J5JK!YOQ+WaNJRjIFcFf#n34JHu zt*Mj(vJlB6kF09KG6}-b# ztgON36|FX(`S%U&Jnuz{SHXL~> delta 1070 zcmV+}1kwAU3H%8oFoFd5FoFb~paTK{0s<6lHqLaAD&#xtLv7wx3f|vZ843rH9&r~j zF*r3jG&Win4Kgt>H!v|VI5jymHd>J@T$2I;8Gp~ye(D+PhAm_l#OV1PUz=z5t}%X> zq?PBNO7NkHRR5;$eHD0)2F;LA()Vd+p9@Bbx%Oyr)f74;nq}cL-3{W#0iiExxtKpk zI0C@gZCj%9dZ=jzKZT+iIUdDy*7$~!VS8kp%cypK(Cg}6pS=J&eo^zz|7SR}4?fx1 zF@IN9&I{n(In5A3T|Tl_c_ah>gnHM8WSV+2O)c-gTjvj2BK+WEaG9$Dxah2h?`#kp z{p3@U=CWJ4K#UbdKYlM|H{-iDjur2Iebb*Fu6C|vlpei0uDL?${xY3nV*Q_~1qbKu z(2qN?jhe>==FbDy>PYG>MiPE_^D3k9Zhv*90wDm&5VbXJ!hhggP?jiXgJdNPMy@|* z%bio7Mi%Ed|FX3Lf&lR^Xsri-br!0JTXS>R#QHLVRFe!Jy(7{ykV^G4 z;&GC2H1S`uIxKH%DN1EY+~)1BXdh`&n9 zQKvy#@&OB+!{R4j@zSX1E1<`9^6@ae-x0^XdqEtBxnZmm$M{u85bHk^LtC%XYZ>}= z1VhR~7_kLbd_GElzgjDx#jo0*n}5c*Jy>Z9avUfiBBS_9ocRdsIvVP%9UqO~m$9w1 z4OGbIjYaUK)9f~jWdni%1poqq0RRT5EdJ(o$FxwD7@SJ>dvdJ74%bs@X_G#v=&Fnc zEcF{f#*E5>m?vVLnUO9uIh<%NM4Q846vat2X4)f}cBR5&-(P87Rjxi@-G2$0UuJen$W(^plRR-yXEQ2yXPFRw#@hb>TG{qvk- zq%YX@I!0vhy9<}iNRE9WaiEO8fD7S8VgPYSsgb=Ho#y(b^Y~ID?}|H>xJ7r%S5Rx* zy$8hGcb?(HlygC%^m7eHAAda57>h#ite<@Y<@xNnK^CoTpKGw5t$#0&3mz#Z(ssa> z&%;(&m(+chCIOPs=uc4@7<#%aqf;NC9O71OoyCNB}TJ0wDmapf8E?J||2|wHAl)m7(m o;1j|EAWZBU{*a09CG4nJy2crP@_E(AjA-owAdus+Tgw=lw9K07g#Z8m diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key index 6b9002b25aea..b2f48ec14938 100644 --- a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key @@ -1,23 +1,15 @@ ------BEGIN DSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,25877371F267513A - -0trY+6ZmQGWPwtcQUt948x5ZJ+aYpYLdOeGzqHqIUI0zVQ2PhuBOo5euR6tVNvHd -+R3EHDpt1I2xQVkr3Opnfe9AbXO4PT67sj8TQeUWFN1HcrpqfwL8nL3nQqLXtynp -jxQ4GdJQ/9pQPB6k4uLhLI43FM9nGIaeGTBPi5mCu5p2PpvPoScy1iwK9V2/ERnH -FJAmV/4ASJXQw9Ww2uY8raDvrVHpX0UHQPuxjQXtOghQjik9XWZA15cp6s18OKd/ -ck+fNg04b7tSsbwEcB4FTzw/UqZWSGeKLhDVXSPWhNjKD14j839tN6kqY5u6FSsJ -7kslskJow8pRuWiR/B/LiTVOJH99kwL3lslKejWhG0Skx8vXoQndLtp5D7WNufsd -78HaBhZhuI/JBR2Pwx/UQBfsz+h3rZHKgwLqxo6+Mii6TEc3qFMsfuvRJAbKun6q -sYSX+ZH7Ju44ZjWzHNuqsixifWMsIyw8jQ1ocK3MjKUFbracjPc6lnAPZjGeqHgg -cxkCS80LjNyZ64BXYhnPwQZs4KKGtGOXvwNuM0aspTFX+5o4Azde5tTSd86Bze2v -jAXa4ZhtlxBa5KInRNuTUOKdCFQX3KkNsvlVRmKrOFc6rlGdLpSe901XYBe6Zbu0 -OMq7wMYLe8iGSvtdvZXngKEjZ9F4RBwC313Q0rQ6diuVZ9u58PzcZC/Cp0Qx3AB7 -GJhsixSL+4rswQUX9Bvhrm3QhuFSNXIa/oQ/xC4kLajbyvnbOQSTk36dRdpjyFwx -LbyW1wl1wFB8lMXdzfssCd6S86ZZHIa2QJCL/ZSH2E+zahn+3RXgBMK2MN4aJM2n -r2Z2aLi6A1qN5eMVULwGY4eiciz2TbJwjsdTaQnM70hsb5/mu4liIygZ2Ly79Y9q -JTdKP0gP4lyFhrs+G6j2DoCD0YPqhn8E5jpokkKDAitqxe4nDyHVM97p/Ax7X4IR -XydpRaAiKAVBO3rquV1pBl/CVynD0QDeyjfq8ve8viPtU/9oXUiaXJurqIkJ/HN5 -MlprNG+Svaa5mtf7HgMqDk7YgGXyyBE4dFL68x/Ye4+7JfvQAUwyb46h3QIhwSKI -NrAjZxA0i+Lla4w2bXNZXxfK38EldZm7gpVzbay1c//TAxXZz7NnNLOed8b7u1zZ ------END DSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDJCLNPr0jF6+UOqnftcW7OC+Pj +rSOLhk277kKiWlQvOGNyqFbL3UvOfVAbKFcMOumZhftsSvHUf9Q47xS5XKBbhIpz +UhyxLVQ435mqQWYOpnqLm5glxUwUn8DKfFiOTznimdypgnGQt5mTdVJ7IG574fAn +5IdC6oE1KReDxdXqN0M4i2e6x/O+uc7r8ePsuQ/Eoo3w4iM/VxHKVLNoOBWZwgPh +EpxumDFslRGal2j7IlUit1tEC9k9D32G+VL7gqu0m6LO5JXJNFIcU6RH36YDfLd3 +eTKbwZjQW57uj1JkR/flm0xR7IUVKmcVs0QaW5fyeudt+U78fCGfd8CSa2cDAiEA +vDbQX231dqIHsQePToTsintUmbtI+/MqrR27x0fHysMCggEAHCTRNw9ZVDUcUtD0 +LKL1ophDNXZFjegz6DwHEsGwMcW+fT9QwfVmcZy5xLqqloapOdE7ejWJ6rKHPmQz +m+73u7fuDDSJMl7MaxVDSMLmlCnJO84tNtCLyRsYxsneSFs9rw0tEIJGAgJHnAgz +usj/hNEhTZT5oLjVPT/DjEqqOvVTlBaVZnd1fkeuI03M/J86R2mIm0VkFLpufnW/ +McebsHwpz9Y2jxr2Wvz0+xv5ooLwZeVFRVl95SsHypjkCGtWKcqxA+lZdYkqLbwt +WvIfo+gJJS6iLsxs9I6OBqh85+bp4xlYsXnmr3JrsuV7OyfCppfgIABbHops57Vg +rbRwswQjAiEAksfTXws/dqMjlRmytRcU4qDef3La1STF5WSsoMdYYqs= +-----END PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem new file mode 100644 index 000000000000..90edc37d8118 --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEnTCCBEMCFCHt1Ah6u8RKy69wV2i5BMfgAVQKMAsGCWCGSAFlAwQDAjBZMQsw +CQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJu +ZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjAwNzAy +MTcwMTQxWhcNMjEwNzAyMTcwMTQxWjBZMQswCQYDVQQGEwJBVTETMBEGA1UECAwK +U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIw +EAYDVQQDDAlsb2NhbGhvc3QwggNGMIICOQYHKoZIzjgEATCCAiwCggEBAMkIs0+v +SMXr5Q6qd+1xbs4L4+OtI4uGTbvuQqJaVC84Y3KoVsvdS859UBsoVww66ZmF+2xK +8dR/1DjvFLlcoFuEinNSHLEtVDjfmapBZg6meoubmCXFTBSfwMp8WI5POeKZ3KmC +cZC3mZN1Unsgbnvh8Cfkh0LqgTUpF4PF1eo3QziLZ7rH8765zuvx4+y5D8SijfDi +Iz9XEcpUs2g4FZnCA+ESnG6YMWyVEZqXaPsiVSK3W0QL2T0PfYb5UvuCq7Sbos7k +lck0UhxTpEffpgN8t3d5MpvBmNBbnu6PUmRH9+WbTFHshRUqZxWzRBpbl/J65235 +Tvx8IZ93wJJrZwMCIQC8NtBfbfV2ogexB49OhOyKe1SZu0j78yqtHbvHR8fKwwKC +AQAcJNE3D1lUNRxS0PQsovWimEM1dkWN6DPoPAcSwbAxxb59P1DB9WZxnLnEuqqW +hqk50Tt6NYnqsoc+ZDOb7ve7t+4MNIkyXsxrFUNIwuaUKck7zi020IvJGxjGyd5I +Wz2vDS0QgkYCAkecCDO6yP+E0SFNlPmguNU9P8OMSqo69VOUFpVmd3V+R64jTcz8 +nzpHaYibRWQUum5+db8xx5uwfCnP1jaPGvZa/PT7G/migvBl5UVFWX3lKwfKmOQI +a1YpyrED6Vl1iSotvC1a8h+j6AklLqIuzGz0jo4GqHzn5unjGVixeeavcmuy5Xs7 +J8Kml+AgAFseimzntWCttHCzA4IBBQACggEALilLLZ1g1CjR1DwUbEWUO+Ak11N5 +AfM8H9gwdszcZgl9J9+tqZ0/YcyTnXcxX/SG7NwjP8eEEekMzR6AKm1gW0OYnshI +3OiD2htmr9uHULsvqTDOKJfY2kcoKqIoTn6apszMf9RBs7EBmvJXxSk8139FLqzL +FBW8/jHxlb54mrGsEeUy/zoCxq/GrKzB5xWtNp/59w3tPO9FilfBjMjdLY7Ly1eh +vuTtZm1LX1wY47dP1p4WWDl5ZUGC5kSzlSLH4vSH1Xe/GTTiXcT6pt4yRFL+WMbi +dnhFKObWUMlz7ck6WPaiI0AMiGFAGn467a7r04sjnMBajaGUEGjm/dWqSDALBglg +hkgBZQMEAwIDRwAwRAIgKq7kQZ4JPNTvcGrt+6yEhjEcIvtZ9NJj3Cm2Q+FuryQC +ID69/GKE4WN5BUWMSi0Fwka80OywHW76nwtsrXRa4c/W +-----END CERTIFICATE----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa-protected.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa-protected.key new file mode 100644 index 000000000000..bc4741ec91ec --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa-protected.key @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjGHXmGVX2JFwICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEN5v5Ytosv3NT48Qg8C/Zh0EgZDK +aWxzYPTIuIA4Tb1kCTd7BVGTsdeBxb5clCbEehF3yIZskalbRfjDso4n2HtVY9eq ++UZilRDSAt/XUhJqqViwbGg3pc+IHTdM2kTosG9vZK7WILRPvPphBFyn1NGwYPak +zHeW1T2Y0PXdjxloqccS6xv4ySwHwv8Hp1pPbpUfRakH3KTrGzOlKouktkcrhfw= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.crt new file mode 100644 index 0000000000000000000000000000000000000000..42a18cbb414484277da43137ee20256ef1fcdfab GIT binary patch literal 522 zcmXqLVq!CBVqCj`nTe5!NhF}6TGXX;p@z^bA?;Nc3+&rQ`0E=ep&HB>Z^2MKcVNOw@3pPQ3=WpS`Upn)vVud;kBVk{!> zmVfWeeiQNJg|}Ud{{JY)D;~VI;Lws)W|1%uYrw96AEaNHk?}tZs{u2RLXHt;cLoC& zCIul2mY18lR#?q%Fjf;{pSU$yJ-__KM3Lj=;_iBF56&!RQqbwVUbM?aqFhJCmg~-% XJsSfp8T`yY9KJ0f?sD(r`kQV5s_CPh literal 0 HcmV?d00001 diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.key new file mode 100644 index 000000000000..e6ca224e8a22 --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.key @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHteKGH6xLqUHhvsgtz9jIBuj+YCwAPHRg2C47rzX0L6oAoGCCqGSM49 +AwEHoUQDQgAES8Hf3hm1ygXcZ+4NLuNgrlY9mmyiQTA4bq+aW4s56IrorHy1Se0j +WtOOngaYvYA7qvVV778h8DTKJcefzpxt1A== +-----END EC PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.pem b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.pem new file mode 100644 index 000000000000..73066f6b49a6 --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-ecdsa.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICBjCCAa2gAwIBAgIUUHh7FUSJoSgSmhI5lnio2/R++gUwCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu +dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIw +MDcwMjEyMTIzOFoXDTIxMDcwMjEyMTIzOFowWTELMAkGA1UEBhMCQVUxEzARBgNV +BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +S8Hf3hm1ygXcZ+4NLuNgrlY9mmyiQTA4bq+aW4s56IrorHy1Se0jWtOOngaYvYA7 +qvVV778h8DTKJcefzpxt1KNTMFEwHQYDVR0OBBYEFO6n94lr7Fjk6Es+XC//WkHU +SA09MB8GA1UdIwQYMBaAFO6n94lr7Fjk6Es+XC//WkHUSA09MA8GA1UdEwEB/wQF +MAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgEjgE6bKKqDqfgDMmEgeRtWMnb3fIkRTH +dxdHLobgzKMCICyJ13K6RBh3LCQ9CtysvLFROQBON/DD2xgXRN7xr9lG +-----END CERTIFICATE----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa-protected.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa-protected.key new file mode 100644 index 000000000000..34fba0f776de --- /dev/null +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa-protected.key @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNjBgBgkqhkiG9w0BBQ0wUzAyBgkqhkiG9w0BBQwwJQQQ93oRxzJ5UoNOb/zN +x5cdsAIDAYagMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBAuHsE18X/Z9ZVe +aBl7C55nBIIE0AABqjc9ERcLYNpCRpA6c/TFG62m4Mr9J4dU4g1WD07t7uLxZiRi +Pl0YOjCulljMsevAW5PlLxi4ffJ+I0/UB1WOfzEMhcj7o1qG0Uv55B7WRuWKw1Zr +jo0bDY5Man48ZjpqMMBdnWhyHdIDm+WD0OyN98mpsN6SCQMjvx91M+klrsp7LOMM +88HHS0RFVKGF9hYSy6rCwMJWf+7QGO2wXfq+MKvJ/bBgPGDLwN4phUCyocnR0swD +/XZNiiw0xIC8OxAKhc6BV4AJkjNs32THdBOCGY6B4P/9Zo5W29S3ja/hGsMQAA27 +QtIDg74HpX7TgIyqoc1oiLNIWW/+jUHSEYJsTPlg5VYWsXUfSHZpz8EJvKt2tyvt +vBGOCLDDZD4GVXhPigKG6zJSJeTe94/VlwPhNSEucKeaALdax5t3HvPNzWKFX57E +aC82/IxRrjgHmgsGSZdMi08HY6K9GAVBFpIGvXOGtRq7w8zO/KagAvSwAOLLtOs7 +iEuAQxD+cKLRT59c4E7r5W7BT+faq85ovqdXe5Edtl3cT81zsl27pZvQrcrTPbZe +4OeIdWxOmOnC/bXvRHNd9XuYadXXazBoFbe9yPwjqnflEh39CyvlOZXeaQXSdsEM +1IBhddRTorO/I8M/znu9glqIa5ya1NA+4ujmf4OnJLtsrlKQa65VPVTrFdeYuMr0 +VfOuuIye2OdyJ6jS0a1PYQm4bEEz6UR88dnmnhDx6i8/l2wW5+CArA/x8IBYboBM +NJpJY9bHpic1AhjnjnTtFz2s4uYPi5g9peBizarZn+6OJvgYqs4a8SI92dA3E2o4 +a/1j7xlLlgXnVRLBMibxqzjMt4Zt7Nj+BaN1owrB/q04AWS2M4TSQz+NYOZwNFxB +dzb+fysTLK5XNEYq6rSg+0i+EKZl8Jb/t4d8SLPVr/tdfDt9BtZ0nTgjvy1HWy1p +kQdm13XfK1/9KsePH/Jb6dvN/u6ubV+ZqI7Bc7VyTi0bKMdpH2K8/dtopNyDZ/P+ +/IsyyDYTorgJB/klSih/W0hqpSBbEAmlSBfBxP1/ozBEGR2oF20JOCFyD6UXQR/1 +V7r2KtplpyfXaIWh4fABitAMHz7VgmEIQ2H9cB4Ey9jdRPQ/1p+OgGjfaFJQ0uYM +987TDtjkuukJYnPZNIIx0Yv3iAX16XmhzJixWSMUIJiWfSiz0aTjBxsPQVPTQV+M +6BgFf3riBApZYlVVJsGIie2XTvu/tHRhfQrxccl63HN7yAeJheQnoscin6Z5TKN/ +U8Ouy/QGiATatKUEUjr4lN+BYySf8F6e3cAAeAx/ZnFvGw5z8fwNYBjVWg/83bTw +9rS+tSk8VsvTdkcKoNbbDtw+SwYfZSbMUBFm0B13190iJZoyWI+5ZKPnZ2CvOZhX +PjGTOnh6Diq907l2Q7S/v8SLe0bCHCHVBy+CcPWVDZ6Z7V5cJ/W8TvFPcSGw1UCl +tKPp862uDaPKvGxqGDq0vGouEUrtJKZ279Lnrtz1n8raUj0Gxa+KXqLACh8dXCzK +ZgCTPhfAjZcYgA73edW0whNNH9MNInDGulT/arCK3HTkFPczD+7wA8Ojw/LxKFJs +0d8vtILbmLv46CO+wvIdWrW1c7PCrGJDf9Zuw06vIH7hpW9swSM55k9/ +-----END ENCRYPTED PRIVATE KEY----- \ No newline at end of file diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-rsa.crt index 618ba1f992da31e9abbb91e23577b255eb219525..0421f377734d035790e8cd737bdfbad614e72667 100644 GIT binary patch literal 784 zcmXqLV&*YuV*IjznTe5!iNpJ`;q5=d21g8d**LY@JlekVGBR?rG8l*$3Kq1NMvk$A^D^^IA)Wq<$ntc*Wl4v@rY+C=FuVlmf z%bc?qF1|2rys>S6*u3_4@+|^q`j_`??GP?=nSQS>vDoHP<@q1`6dLTT=Dlq$pLCJ+ zl&k&16s{Ytzm)3~on=F6mTr~^wCz3I|Hh^8@H0lYe9jYLu^DWKj&2FoU=`5nZp~h~ z-A$+b)G0}kkFtxb&;JX$dR}y@hsr~~qwZ3>l0kw24=}`Kg&7(DvoIMj81R93{2(3+GZX6q12GU^ z6~yN;;9}#@W@BV!WoKqI5C@41g2Z_ZxSNooi=T}PsECEJ$vlJ+NHHSE0x*(+vB1cX zV(-cPey-AkleJ|DGGop$EPvMVonoxfNv zH=Vx7Ci4&1HQi~in*=N#-EVl9lo_q4DX?hWvkCupe%w`Bx5AF+_es&0la&hAMSi<} zJ6VEZ*{!Lk8;$ozvd3*)wrbbE^*0VmKQoFs65jRn2=CvOH^f#XtNl*An)OALN7}kQ zdwZnw&$VCHFHP3}&7u_4b>qaYPa7|sefX~V-L5-Hm$&oIPS-xL;Ed#ADT{EP?bQ>j P%Xzmis+z!lw__my11T}7 literal 1431 zcmXqLVx4Tz#9Y0AnTe5!NyPMH*yY_`hpwrwic8Ap@zZ+f*=kD4_9!0ZmMo@Nn%N=p`w92NRW$1!ZWWVwJ0yO zL?JvgB|WpGSRtUKQo*Mr#ZbsV0HlPOhchQXIWZ?AzqrIePMp`sz`)$V5J;LDnnnS+ zhDcmmTHVB?gzQm9RtDxKCVmEkCMGVXCMHIPz0-eYa8+DSXuPh+@TRHYex$D4fvZ+) zI|^r-zGn$*U=sPm)A{siYSq>Iob2V4@QQbo@VrCdc<2#mfZ|0F%#K~Z9J}VmcGm| z4BhkORKcX{wLiQTc1zS*+~el#ElK?U_7`jD!vl6)OsiX(ZC<+6^^_f-mbz#A%_}d? zHyn4on}1)lHTg?O?lxgr*0#*Ff+qQ0Zk=IS*Mzn_KK*R9@ZH~1s~iXm!UuJu|bu;ZB{bRfIV}A9fNt2t*d+&k435+jUtYq#x@%BWkR&bDwV{}snw zh1T}--RyYJiPiKk5!Nqmo+wj);nS6GJokU`=OoBPyUk#B_*5Ky+4WNXE$fLpPI<`f zU*T+=nb^~QU%|3eCi94;-rBWM71Nen+fno7{wK?|opKz0NB(@An=m^v`XCcCBLm~& zV1qydSzxl2l) zZER8f4xwE$XPCWcd~u<{K6>R{Te(HX->z87f1KnmHo1Ut$-#Qp-Wm5Sbmd!8wz^C8 zY&>5ft);PZhBW`R`KI%8vcx>t-uPeMwZuK3qqgJZYGv*>W*6Uh&2=nSe5J!>{h|ex_Tf@vi(g=Scjf zMW)i*tAo7HOKp;ieWqeuP{BK+$2io|PuBI%PEOSmd9NqepXB?>@>Y3?{^W-J9n|x!I?CWLhoaR+jdbIE3@J|SF6Y0zkMN6$`SUbvQ@d76ef(rzp|A3c zFJ6WB8k~2!aW!FMazoroZF5TMm!0t7>!rDUSd-=A3)H-F? zDQmAQ@%%O_t^Tj&{?%;dLB20%m)z0v^<;=pDDab?v3B$ABRxHN%4@f`ezf*UkodFa z`y!#%$FE;m-dAOdKHCv;Cb%}M|Ln%BCt8Ak>)STIIv%%7@>_A>ve~}pbgo{$68pe; zQu$LMv;4PL*M9ia`K^gFW8cnVuO)XHUjE-7$Qe>*JNa0OOWXWaJl0nGEtmf(KR9FW qk+p8T-;CcK + From 4ad1faf356d165a7fa105afb210713a3e1df8aa3 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 2 Jul 2020 10:33:59 -0700 Subject: [PATCH 6/9] Remove unnecessary tests --- .../test/KestrelConfigurationLoaderTests.cs | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs index 66dedbabec89..4056e4c1f9db 100644 --- a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs +++ b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs @@ -255,61 +255,6 @@ public void ConfigureEndpointDevelopmentCertificateGetsLoadedWhenPresent() } } - [Fact] - public void ConfigureEndpoint_CanLoadRsaPemCerts() - { - var serverOptions = CreateServerOptions(); - var certificate = new X509Certificate2(TestResources.GetCertPath("https-rsa.crt")); - - var ran1 = false; - var config = new ConfigurationBuilder().AddInMemoryCollection(new[] - { - new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), - new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-rsa.crt")), - new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-rsa.key")), - }).Build(); - - serverOptions - .Configure(config) - .Endpoint("End1", opt => - { - ran1 = true; - Assert.True(opt.IsHttps); - Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); - }).Load(); - - Assert.True(ran1); - Assert.NotNull(serverOptions.DefaultCertificate); - } - - [Fact] - public void ConfigureEndpoint_CanLoadProtectedRsaPemCerts() - { - var serverOptions = CreateServerOptions(); - var certificate = new X509Certificate2(TestResources.GetCertPath("https-aspnet.crt")); - - var ran1 = false; - var config = new ConfigurationBuilder().AddInMemoryCollection(new[] - { - new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), - new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-aspnet.crt")), - new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-aspnet.key")), - new KeyValuePair("Certificates:Default:Password", "aspnetcore"), - }).Build(); - - serverOptions - .Configure(config) - .Endpoint("End1", opt => - { - ran1 = true; - Assert.True(opt.IsHttps); - Assert.Equal(opt.HttpsOptions.ServerCertificate.SerialNumber, certificate.SerialNumber); - }).Load(); - - Assert.True(ran1); - Assert.NotNull(serverOptions.DefaultCertificate); - } - [Fact] public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() { From 2e68fd34c59fa3b7b2688c1836c7f3a5c3bfea47 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 2 Jul 2020 13:32:34 -0700 Subject: [PATCH 7/9] Address feedback, add DSA certificate tests --- .../Core/src/KestrelConfigurationLoader.cs | 13 ++---- .../test/KestrelConfigurationLoaderTests.cs | 8 ++-- .../TestCertificates/https-dsa-protected.key | 25 ++++------ .../test/TestCertificates/https-dsa.crt | Bin 1185 -> 861 bytes .../test/TestCertificates/https-dsa.key | 24 ++++------ .../test/TestCertificates/https-dsa.pem | 43 ++++++++---------- 6 files changed, 44 insertions(+), 69 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs index 572144698277..6d3dcd25033e 100644 --- a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs +++ b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs @@ -441,15 +441,12 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp if (certInfo.KeyPath != null) { var certificateKeyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); - X509Certificate2 certificate = GetCertificate(certInfo, certificatePath, certificateKeyPath); + var certificate = GetCertificate(certInfo, certificatePath, certificateKeyPath); - if (!certificate.HasPrivateKey) + if (certificate != null) { certificate = LoadCertificateKey(certificate, certificateKeyPath, certInfo.Password); - } - if (certificate != null) - { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return PersistKey(certificate); @@ -487,14 +484,12 @@ static X509Certificate2 LoadCertificateKey(X509Certificate2 certificate, string static X509Certificate2 GetCertificate(CertificateConfig certInfo, string certificatePath, string certificateKeyPath) { - if (X509Certificate2.GetCertContentType(certificatePath) != X509ContentType.Unknown) + if (X509Certificate2.GetCertContentType(certificatePath) == X509ContentType.Cert) { return new X509Certificate2(certificatePath); } - return certInfo.Password != null ? - X509Certificate2.CreateFromEncryptedPemFile(certificatePath, certInfo.Password, certificateKeyPath) : - X509Certificate2.CreateFromPemFile(certificatePath, certificateKeyPath); + return null; } } diff --git a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs index 4056e4c1f9db..43402c4e886b 100644 --- a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs +++ b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs @@ -289,10 +289,10 @@ public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() [InlineData("https-ecdsa.pem", "https-ecdsa-protected.key", "aspnetcore")] [InlineData("https-ecdsa.crt", "https-ecdsa.key", null)] [InlineData("https-ecdsa.crt", "https-ecdsa-protected.key", "aspnetcore")] - //[InlineData("https-dsa.pem", "https-dsa.key", null)] - //[InlineData("https-dsa.pem", "https-dsa-protected.key", "aspnetcore")] - //[InlineData("https-dsa.crt", "https-dsa.key", null)] - //[InlineData("https-dsa.crt", "https-dsa-protected.key", "aspnetcore")] + [InlineData("https-dsa.pem", "https-dsa.key", null)] + [InlineData("https-dsa.pem", "https-dsa-protected.key", "test")] + [InlineData("https-dsa.crt", "https-dsa.key", null)] + [InlineData("https-dsa.crt", "https-dsa-protected.key", "test")] public void ConfigureEndpoint_CanLoadPemCertificates(string certificateFile, string certificateKey, string password) { var serverOptions = CreateServerOptions(); diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key index dea23f907c65..196ea3217f94 100644 --- a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa-protected.key @@ -1,18 +1,11 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIICzTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIgeRX7Sed0OsCAggA -MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBC7vpWM+TQ9caiqYAn+h95YBIIC -cM8+gZPkVJZF1ICFi6lHHNjV9FSdH+qwvUOzBEVP1oZtmdMBhEVqqm+3H+Gcm6dn -C4JjMGCu3KqQ096JoWeFE/ksuTcL7MBtvyY35NIbbVxEW7YxvTiICADfjwL0mDYH -SlUr0LLrMhoYfN01HE2kkkJLZLt58zjzxyUdc//SlIC6rJyd6NZdNrmRQ9JZzd7G -SZtkXRMvrzyJoxwOc+5ERmYtOtOWmyF2pAFwoEnb8VOQgoM3gy/3lO5aVpPj76Rr -MmJwdruU39nUPTe6VI6ukF5T27pu0XmX5YWqy5+PZ5cFhmOxGSxwvw6dbJSM1+Sg -ZcKohhQQtNFYFgFpp8cz84o1lHWprjGxHRVKEeKAwgX8v8glDTKzwS0DKsTzdn0s -2RCwjr+GxH7wpjwzllny2xU/h5ZR2j8gldfCNFVPtFrGleuEduPA4U04Mkije0l9 -AdPHDK8drvUuIZLb2HCQu0wYmUDmtY/SWuMl1xRonrF+cPPcmAdQDP8IH2MGL8SO -9h/CCextHsqzXl7PJzHcjLmn8qmlocmSJRALCrWpgoE/d7Wjle8LmtQVWSw0UgTo -GEoWpFcz6JJBUrcasGQHokLtuyAjjSRgSt1DFK2iW+O7MARK9wJNCGUfDNWavO4p -hA7MR1muv/xwwr0oi2OJ5rc3N+6M/Fb1fRlU5+EsaE2xee7nV3JdVmdYKpOM8ksX -F5XV/b4BbaPbTRppr0aZk6RDqy5jlYVsNy1Npwqw/2pJqS7wTWZgaWQgePsRGsb5 -3SZC64XpHlzBgYOgpnOC9x9KJuWt2z4OS0l70Nvv7+VLzem0fVMb+Dh/5VFjYfp2 -4w== +MIIBoTBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQI+PhdT1Kk/SkCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECGV1ZmaiQtz2BIIBUA/6pNqTkXpkOLlI +22Lh0cm5+/foDRh3qTrAOSHHHV0Dz1xYvYMa9MFzONatLf55Rpb2ZPji3hXwUQfn +gOJeTBRTaMNz5LaKJiOIWj0qDckhgKt9cmgiBzVTvXO4pERp1uz5zcvaUOKj2TSv +ljxishj76MYQftIGMMkJQKf4OsHubCopuKUbzTPgJt0FuF4eT37+tiEMgbYrmA6p +REPE0vT1aY+LYdJLV/Dax/l4lMvYmQYOWs9TCLPlI5RZQxxte6zbcA13ESg/qLE3 +4Mx8xgXrPvCxp3h8KBKNMaJR1xzpr7UQOpkI9qja++3cJAl6O/0mdeqZct0V9Z8P +a3+wyUWo58z5sOPNdJHIMV6qw6m3w+IQoCJC7EbV0+Pyo5eSU5zbgm7YWZ9Yx6l8 +g1mCP4Q6Tqe6LjKfBsZAmYWSfKqoTKRjC3ocJMt53tIDpB5jFw== -----END ENCRYPTED PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.crt index 26993c7406a5d6a1885fd17d0e369180ef436fa3..2f087db08aa35ad61ed028cd16d1c4273304f97c 100644 GIT binary patch literal 861 zcmXqLVvaOuVisM%%*4pVBqA!p#(bAeM(;<#rTr~;F7WAHR|zxVX5&m~^I%M6W?^PB zh&ALk;ACSCWnmL$3Jo?CG~fquICwb1GKHxk8>6*j6jYYQ)45;oJFU!zV zPwINnB%K%YHspm)`J)MeJx|meHk@Cnyt>27GVI|lkLmWyrr$h%<+azISL}HUHBHqz z7kAC(idX#evU~4_rekpiuS4EUu@kk3msZ&mF1YYTuHt(cvlsGz8TJGo&MUSKH~Km$ z=YpGg+riIFq747rGmD~SCLh}8<=W_b_Vu|CjSUq#|EBEQeWFXz|CppTgJX}; zUY^!N_>RuGutgLYG<8gJDz==IlMGRBp zP9NX@ye)#$_t z!6Nl%*2%F~*~^_gXOuRaDEB>=5x%xyx601Pk9O=nazOM>nj7B)^`zgYFYK6pCT7K~ z#lZ%F2C~2eCCkSm#v&4%`f%3KI~Tq@(KuHA|K5IgPaTD719_0NGK++PSOaziprkA- z%*gnkh1Gx=NTH;BWX=glFtzIsSk#gv)@NjWeOmgE5tvg_+49(vaJL zlZ`o)g-w{rG1O4lKoG>?;Nc3+&rQ`0E=ep&HB>Z^2MKcVNOjk+Ng_h+th zOygTt)jfNL>QNt&`3FwbMD+PvKAL%FWmDmV?K3Br230HMRX_Zo{-oXMRimkPeFzncyYv_m?r(Y%i}gntgD_h3I+j`h!y3 zzdxPr6Zoc8R4ZL{vx`*p^iNgKbAS5%sZpF?eqd5|Ix~|Z!ydB>@ws2i7O`(+@AqqY z(^VZZbGOIu&su9`cOQ2@e(EqVoET(OE}HX4hM39(UHGE2=!LMnBb9NrtwQ5@1O3RDZRi>S zL+Vpk*T~wZ+U%!hJmJU=(>%42`DJ8jr-KbCUi(hc6>Mhbclk=sok8MTG^Jgy~ zOGa$0e73$Qd(+cuYxP6Rraw?%h?eWhdA>Da?UsVg%uS4}44{C})AZJzn{Y+r;uRZ_ z9M>t<4^*xPS2BLKk-uS3cIHkRXRZ4EwJYb^C!U!+x7;xPOWT_}%J#=w1Yh!;m21$- zO^9}$G4F)Oofplwq|?^lZV%Y4ztZ5G#`GJv+%>coY53L6T6X44{T0W}8yRPP3O}l8 zbG_bGZ_Q~D(LMhRKTh3OF>B)*!KX(5t(cCjKelGg!RMlD&F267&imHpy=zza!JZR$ zb^A`A4qv$M$=kGC@Aw#r$J_m{%@d2TtW0%mdgiius?zaCU)ryh@0T=r6no^?vU^4@ zLH{C-Ju0hk)p&L-;AHXJlU5Pm7AZUMbR;@R)mgn=_xf_T@|*)vy$h!ZWIX$Ob(IH7 zVZrRqVBo@}ptbIa<2+8AEAI=k-u_=l$Y>>_SHJ>|YZAsL_^Vb0RJ_S1f diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key index b2f48ec14938..7034a7b5a487 100644 --- a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.key @@ -1,15 +1,9 @@ ------BEGIN PRIVATE KEY----- -MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDJCLNPr0jF6+UOqnftcW7OC+Pj -rSOLhk277kKiWlQvOGNyqFbL3UvOfVAbKFcMOumZhftsSvHUf9Q47xS5XKBbhIpz -UhyxLVQ435mqQWYOpnqLm5glxUwUn8DKfFiOTznimdypgnGQt5mTdVJ7IG574fAn -5IdC6oE1KReDxdXqN0M4i2e6x/O+uc7r8ePsuQ/Eoo3w4iM/VxHKVLNoOBWZwgPh -EpxumDFslRGal2j7IlUit1tEC9k9D32G+VL7gqu0m6LO5JXJNFIcU6RH36YDfLd3 -eTKbwZjQW57uj1JkR/flm0xR7IUVKmcVs0QaW5fyeudt+U78fCGfd8CSa2cDAiEA -vDbQX231dqIHsQePToTsintUmbtI+/MqrR27x0fHysMCggEAHCTRNw9ZVDUcUtD0 -LKL1ophDNXZFjegz6DwHEsGwMcW+fT9QwfVmcZy5xLqqloapOdE7ejWJ6rKHPmQz -m+73u7fuDDSJMl7MaxVDSMLmlCnJO84tNtCLyRsYxsneSFs9rw0tEIJGAgJHnAgz -usj/hNEhTZT5oLjVPT/DjEqqOvVTlBaVZnd1fkeuI03M/J86R2mIm0VkFLpufnW/ -McebsHwpz9Y2jxr2Wvz0+xv5ooLwZeVFRVl95SsHypjkCGtWKcqxA+lZdYkqLbwt -WvIfo+gJJS6iLsxs9I6OBqh85+bp4xlYsXnmr3JrsuV7OyfCppfgIABbHops57Vg -rbRwswQjAiEAksfTXws/dqMjlRmytRcU4qDef3La1STF5WSsoMdYYqs= ------END PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBAJyiyioeXx1O98gRCMEjlPKMpr79 +KrcDkoroghtuXO1U6Cx34pBRjOQmQLDPqSOriEo5VuG6SJc/ppfZx9TrSrzqB26h +KTUmiaOKmwpfIfzpi72wgsZeMOtU7JQ+FThfGyS8VxGh6G0h7xw26B/9ALxRw25z +O1cy9ZJs0EY3hsHzAhUA/4dpclsck8K+SkWBTcPfU+x7wTUCgYB4LP6UvrvIiiFP +xhk7AEGMMr0MhcJ3hhsgKWukUqIYsJKBM5MpKCnej5BHvnLXdKodIxygcKR4dJX7 +BRv69L+2RJk+UrYL1qBco5HpUslumA0e3gNdwRLoOoGD14dn1LD1LdESsyMgwfHH +J0RRkYwacgCVXsvHv/eAkA8qq136dwQXAhUA216Tqp4OvdUBNv8QLv8Z5QPopGQ= +-----END PRIVATE KEY----- diff --git a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem index 90edc37d8118..4f64dac50996 100644 --- a/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem +++ b/src/Servers/Kestrel/shared/test/TestCertificates/https-dsa.pem @@ -1,27 +1,20 @@ -----BEGIN CERTIFICATE----- -MIIEnTCCBEMCFCHt1Ah6u8RKy69wV2i5BMfgAVQKMAsGCWCGSAFlAwQDAjBZMQsw -CQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJu -ZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjAwNzAy -MTcwMTQxWhcNMjEwNzAyMTcwMTQxWjBZMQswCQYDVQQGEwJBVTETMBEGA1UECAwK -U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIw -EAYDVQQDDAlsb2NhbGhvc3QwggNGMIICOQYHKoZIzjgEATCCAiwCggEBAMkIs0+v -SMXr5Q6qd+1xbs4L4+OtI4uGTbvuQqJaVC84Y3KoVsvdS859UBsoVww66ZmF+2xK -8dR/1DjvFLlcoFuEinNSHLEtVDjfmapBZg6meoubmCXFTBSfwMp8WI5POeKZ3KmC -cZC3mZN1Unsgbnvh8Cfkh0LqgTUpF4PF1eo3QziLZ7rH8765zuvx4+y5D8SijfDi -Iz9XEcpUs2g4FZnCA+ESnG6YMWyVEZqXaPsiVSK3W0QL2T0PfYb5UvuCq7Sbos7k -lck0UhxTpEffpgN8t3d5MpvBmNBbnu6PUmRH9+WbTFHshRUqZxWzRBpbl/J65235 -Tvx8IZ93wJJrZwMCIQC8NtBfbfV2ogexB49OhOyKe1SZu0j78yqtHbvHR8fKwwKC -AQAcJNE3D1lUNRxS0PQsovWimEM1dkWN6DPoPAcSwbAxxb59P1DB9WZxnLnEuqqW -hqk50Tt6NYnqsoc+ZDOb7ve7t+4MNIkyXsxrFUNIwuaUKck7zi020IvJGxjGyd5I -Wz2vDS0QgkYCAkecCDO6yP+E0SFNlPmguNU9P8OMSqo69VOUFpVmd3V+R64jTcz8 -nzpHaYibRWQUum5+db8xx5uwfCnP1jaPGvZa/PT7G/migvBl5UVFWX3lKwfKmOQI -a1YpyrED6Vl1iSotvC1a8h+j6AklLqIuzGz0jo4GqHzn5unjGVixeeavcmuy5Xs7 -J8Kml+AgAFseimzntWCttHCzA4IBBQACggEALilLLZ1g1CjR1DwUbEWUO+Ak11N5 -AfM8H9gwdszcZgl9J9+tqZ0/YcyTnXcxX/SG7NwjP8eEEekMzR6AKm1gW0OYnshI -3OiD2htmr9uHULsvqTDOKJfY2kcoKqIoTn6apszMf9RBs7EBmvJXxSk8139FLqzL -FBW8/jHxlb54mrGsEeUy/zoCxq/GrKzB5xWtNp/59w3tPO9FilfBjMjdLY7Ly1eh -vuTtZm1LX1wY47dP1p4WWDl5ZUGC5kSzlSLH4vSH1Xe/GTTiXcT6pt4yRFL+WMbi -dnhFKObWUMlz7ck6WPaiI0AMiGFAGn467a7r04sjnMBajaGUEGjm/dWqSDALBglg -hkgBZQMEAwIDRwAwRAIgKq7kQZ4JPNTvcGrt+6yEhjEcIvtZ9NJj3Cm2Q+FuryQC -ID69/GKE4WN5BUWMSi0Fwka80OywHW76nwtsrXRa4c/W +MIIDWTCCAxWgAwIBAgIUFRQGA90GHC74cNK/hNzQDi7XJFYwCwYJYIZIAWUDBAMC +MF0xCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhWaXJnaW5pYTETMBEGA1UEBwwKQWxl +eGFuZHJpYTEQMA4GA1UECgwHQ29udG9zbzEUMBIGA1UECwwLRGV2ZWxvcG1lbnQw +HhcNMjAwNjE5MTkyODIwWhcNMjAwNzE5MTkyODIwWjBdMQswCQYDVQQGEwJVUzER +MA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkFsZXhhbmRyaWExEDAOBgNVBAoM +B0NvbnRvc28xFDASBgNVBAsMC0RldmVsb3BtZW50MIIBtjCCASsGByqGSM44BAEw +ggEeAoGBAJyiyioeXx1O98gRCMEjlPKMpr79KrcDkoroghtuXO1U6Cx34pBRjOQm +QLDPqSOriEo5VuG6SJc/ppfZx9TrSrzqB26hKTUmiaOKmwpfIfzpi72wgsZeMOtU +7JQ+FThfGyS8VxGh6G0h7xw26B/9ALxRw25zO1cy9ZJs0EY3hsHzAhUA/4dpclsc +k8K+SkWBTcPfU+x7wTUCgYB4LP6UvrvIiiFPxhk7AEGMMr0MhcJ3hhsgKWukUqIY +sJKBM5MpKCnej5BHvnLXdKodIxygcKR4dJX7BRv69L+2RJk+UrYL1qBco5HpUslu +mA0e3gNdwRLoOoGD14dn1LD1LdESsyMgwfHHJ0RRkYwacgCVXsvHv/eAkA8qq136 +dwOBhAACgYAHltgzkK3zD8yGdcGY0YgvN5l3lna1voLmcK+XtmehjMVy7OSSFICN +KybLBOvO8paydhCb1J0klkLPAoAjgP2cEd+KueeRyJpx+jD1MsjIEXIn5jtjXdUH +d0JJmHWAyHdNzmhXrXC7JLnj4ri7xMAV3GZGDpAnYvvL0LiXzFyomqNTMFEwHQYD +VR0OBBYEFF1l4ZrF3ND05CjGd//ev0dJLCB7MB8GA1UdIwQYMBaAFF1l4ZrF3ND0 +5CjGd//ev0dJLCB7MA8GA1UdEwEB/wQFMAMBAf8wCwYJYIZIAWUDBAMCAzEAMC4C +FQD6plYf60MDCvMjf1yQ8SBaFX3YYwIVAKqRQklh2b0Qhv+US222hb8xySJV -----END CERTIFICATE----- From 2c1f5ccb1f8bae8a0024d1131a9ec3c99bf9a221 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 3 Jul 2020 06:07:31 -0700 Subject: [PATCH 8/9] Final feedback and cleanups --- src/Servers/Kestrel/Core/src/CoreStrings.resx | 3 + .../Core/src/Internal/LoggerExtensions.cs | 15 +++ .../Core/src/KestrelConfigurationLoader.cs | 103 +++++++++--------- .../test/KestrelConfigurationLoaderTests.cs | 55 +++++++++- 4 files changed, 123 insertions(+), 53 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/CoreStrings.resx b/src/Servers/Kestrel/Core/src/CoreStrings.resx index 57fb521b78d7..49c2f5fb482c 100644 --- a/src/Servers/Kestrel/Core/src/CoreStrings.resx +++ b/src/Servers/Kestrel/Core/src/CoreStrings.resx @@ -617,4 +617,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l The provided key file is missing or invalid. + + Unknown algorithm for certificate with public key type '{0}'. + \ No newline at end of file diff --git a/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs b/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs index 1fedf58ae5cd..2da09825c811 100644 --- a/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs +++ b/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs @@ -46,6 +46,18 @@ internal static class LoggerExtensions new EventId(5, "DeveloperCertificateFirstRun"), "{Message}"); + private static readonly Action _failedToLoadCertificate = + LoggerMessage.Define( + LogLevel.Warning, + new EventId(6, "MissingOrInvalidCertificateFile"), + "The certificate file at '{CertificateFilePath}' can not be found, contains malformed data or does not contain a certificate."); + + private static readonly Action _failedToLoadCertificateKey = + LoggerMessage.Define( + LogLevel.Warning, + new EventId(7, "MissingOrInvalidCertificateKeyFile"), + "The certificate key file at '{CertificateKeyFilePath}' can not be found, contains malformed data or does not contain a PEM encoded key in PKCS8 format."); + public static void LocatedDevelopmentCertificate(this ILogger logger, X509Certificate2 certificate) => _locatedDevelopmentCertificate(logger, certificate.Subject, certificate.Thumbprint, null); public static void UnableToLocateDevelopmentCertificate(this ILogger logger) => _unableToLocateDevelopmentCertificate(logger, null); @@ -57,5 +69,8 @@ internal static class LoggerExtensions public static void BadDeveloperCertificateState(this ILogger logger) => _badDeveloperCertificateState(logger, null); public static void DeveloperCertificateFirstRun(this ILogger logger, string message) => _developerCertificateFirstRun(logger, message, null); + + public static void FailedToLoadCertificate(this ILogger logger, string certificatePath) => _failedToLoadCertificate(logger, certificatePath, null); + public static void FailedToLoadCertificateKey(this ILogger logger, string certificateKeyPath) => _failedToLoadCertificateKey(logger, certificateKeyPath, null); } } diff --git a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs index 6d3dcd25033e..04349031e2d1 100644 --- a/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs +++ b/src/Servers/Kestrel/Core/src/KestrelConfigurationLoader.cs @@ -430,6 +430,7 @@ private bool TryGetCertificatePath(out string path) private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endpointName) { + var logger = Options.ApplicationServices.GetRequiredService>(); if (certInfo.IsFileCert && certInfo.IsStoreCert) { throw new InvalidOperationException(CoreStrings.FormatMultipleCertificateSources(endpointName)); @@ -441,12 +442,19 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp if (certInfo.KeyPath != null) { var certificateKeyPath = Path.Combine(environment.ContentRootPath, certInfo.KeyPath); - var certificate = GetCertificate(certInfo, certificatePath, certificateKeyPath); + var certificate = GetCertificate(certificatePath); if (certificate != null) { certificate = LoadCertificateKey(certificate, certificateKeyPath, certInfo.Password); + } + else + { + logger.FailedToLoadCertificate(certificateKeyPath); + } + if (certificate != null) + { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return PersistKey(certificate); @@ -454,6 +462,10 @@ private X509Certificate2 LoadCertificate(CertificateConfig certInfo, string endp return certificate; } + else + { + logger.FailedToLoadCertificateKey(certificateKeyPath); + } throw new InvalidOperationException(CoreStrings.InvalidPemKey); } @@ -476,13 +488,22 @@ static X509Certificate2 PersistKey(X509Certificate2 fullCertificate) static X509Certificate2 LoadCertificateKey(X509Certificate2 certificate, string keyPath, string password) { + // OIDs for the certificate key types. + const string RSAOid = "1.2.840.113549.1.1.1"; + const string DSAOid = "1.2.840.10040.4.1"; + const string ECDsaOid = "1.2.840.10045.2.1"; + var keyText = File.ReadAllText(keyPath); - return TryAttachPemRSAKey(certificate, keyText, password) ?? - TryAttachPemDSAKey(certificate, keyText, password) ?? - TryAttachPemECDSAKey(certificate, keyText, password); + return certificate.PublicKey.Oid.Value switch + { + RSAOid => AttachPemRSAKey(certificate, keyText, password), + ECDsaOid => AttachPemECDSAKey(certificate, keyText, password), + DSAOid => AttachPemDSAKey(certificate, keyText, password), + _ => throw new InvalidOperationException(string.Format(CoreStrings.UnrecognizedCertificateKeyOid, certificate.PublicKey.Oid.Value)) + }; } - static X509Certificate2 GetCertificate(CertificateConfig certInfo, string certificatePath, string certificateKeyPath) + static X509Certificate2 GetCertificate(string certificatePath) { if (X509Certificate2.GetCertContentType(certificatePath) == X509ContentType.Cert) { @@ -493,67 +514,49 @@ static X509Certificate2 GetCertificate(CertificateConfig certInfo, string certif } } - private static X509Certificate2 TryAttachPemRSAKey(X509Certificate2 certificate, string keyText, string password) + private static X509Certificate2 AttachPemRSAKey(X509Certificate2 certificate, string keyText, string password) { - const string RSAOid = "1.2.840.113549.1.1.1"; - if (string.Equals(RSAOid, certificate.PublicKey.Oid.Value, StringComparison.Ordinal)) + using var rsa = RSA.Create(); + if (password == null) { - using var rsa = RSA.Create(); - if (password == null) - { - rsa.ImportFromPem(keyText); - } - else - { - rsa.ImportFromEncryptedPem(keyText, password); - } - - return certificate.CopyWithPrivateKey(rsa); + rsa.ImportFromPem(keyText); + } + else + { + rsa.ImportFromEncryptedPem(keyText, password); } - return null; + return certificate.CopyWithPrivateKey(rsa); } - private static X509Certificate2 TryAttachPemDSAKey(X509Certificate2 certificate, string keyText, string password) + private static X509Certificate2 AttachPemDSAKey(X509Certificate2 certificate, string keyText, string password) { - const string DSAOid = "1.2.840.10040.4.1"; - if (string.Equals(DSAOid, certificate.PublicKey.Oid.Value, StringComparison.Ordinal)) + using var dsa = DSA.Create(); + if (password == null) { - using var dsa = DSA.Create(); - if (password == null) - { - dsa.ImportFromPem(keyText); - } - else - { - dsa.ImportFromEncryptedPem(keyText, password); - } - - return certificate.CopyWithPrivateKey(dsa); + dsa.ImportFromPem(keyText); + } + else + { + dsa.ImportFromEncryptedPem(keyText, password); } - return null; + return certificate.CopyWithPrivateKey(dsa); } - private static X509Certificate2 TryAttachPemECDSAKey(X509Certificate2 certificate, string keyText, string password) + private static X509Certificate2 AttachPemECDSAKey(X509Certificate2 certificate, string keyText, string password) { - const string ECDsaOid = "1.2.840.10045.2.1"; - if (string.Equals(ECDsaOid, certificate.PublicKey.Oid.Value, StringComparison.Ordinal)) + using var ecdsa = ECDsa.Create(); + if (password == null) { - using var ecdsa = ECDsa.Create(); - if (password == null) - { - ecdsa.ImportFromPem(keyText); - } - else - { - ecdsa.ImportFromEncryptedPem(keyText, password); - } - - return certificate.CopyWithPrivateKey(ecdsa); + ecdsa.ImportFromPem(keyText); + } + else + { + ecdsa.ImportFromEncryptedPem(keyText, password); } - return null; + return certificate.CopyWithPrivateKey(ecdsa); } private static X509Certificate2 LoadFromStoreCert(CertificateConfig certInfo) diff --git a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs index 43402c4e886b..5053b3cffb12 100644 --- a/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs +++ b/src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs @@ -256,7 +256,7 @@ public void ConfigureEndpointDevelopmentCertificateGetsLoadedWhenPresent() } [Fact] - public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() + public void ConfigureEndpoint_ThrowsWhen_The_PasswordIsMissing() { var serverOptions = CreateServerOptions(); var certificate = new X509Certificate2(TestResources.GetCertPath("https-aspnet.crt")); @@ -268,7 +268,57 @@ public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-aspnet.key")) }).Build(); - var ex = Assert.Throws(() => + var ex = Assert.Throws(() => + { + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + Assert.True(opt.IsHttps); + }).Load(); + }); + } + + [Fact] + public void ConfigureEndpoint_ThrowsWhen_TheKeyDoesntMatchTheCertificateKey() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-aspnet.crt")); + + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-aspnet.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-ecdsa.key")), + new KeyValuePair("Certificates:Default:Password", "aspnetcore") + }).Build(); + + var ex = Assert.Throws(() => + { + serverOptions + .Configure(config) + .Endpoint("End1", opt => + { + Assert.True(opt.IsHttps); + }).Load(); + }); + } + + [Fact] + public void ConfigureEndpoint_ThrowsWhen_The_PasswordIsIncorrect() + { + var serverOptions = CreateServerOptions(); + var certificate = new X509Certificate2(TestResources.GetCertPath("https-aspnet.crt")); + + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Endpoints:End1:Url", "https://*:5001"), + new KeyValuePair("Certificates:Default:Path", Path.Combine("shared", "TestCertificates", "https-aspnet.crt")), + new KeyValuePair("Certificates:Default:KeyPath", Path.Combine("shared", "TestCertificates", "https-aspnet.key")), + new KeyValuePair("Certificates:Default:Password", "abcde"), + }).Build(); + + var ex = Assert.Throws(() => { serverOptions .Configure(config) @@ -277,7 +327,6 @@ public void ConfigureEndpoint_ThrowsWhen_TheKeyCannotBeRead() Assert.True(opt.IsHttps); }).Load(); }); - Assert.Equal(CoreStrings.InvalidPemKey, ex.Message); } [Theory] From 4aa4ef74b6e0e767ebc25cf636e8d275859b7e3e Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Fri, 3 Jul 2020 06:18:09 -0700 Subject: [PATCH 9/9] Update from warning to error --- src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs b/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs index 2da09825c811..a28c74ae872e 100644 --- a/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs +++ b/src/Servers/Kestrel/Core/src/Internal/LoggerExtensions.cs @@ -48,13 +48,13 @@ internal static class LoggerExtensions private static readonly Action _failedToLoadCertificate = LoggerMessage.Define( - LogLevel.Warning, + LogLevel.Error, new EventId(6, "MissingOrInvalidCertificateFile"), "The certificate file at '{CertificateFilePath}' can not be found, contains malformed data or does not contain a certificate."); private static readonly Action _failedToLoadCertificateKey = LoggerMessage.Define( - LogLevel.Warning, + LogLevel.Error, new EventId(7, "MissingOrInvalidCertificateKeyFile"), "The certificate key file at '{CertificateKeyFilePath}' can not be found, contains malformed data or does not contain a PEM encoded key in PKCS8 format.");