����C %# , #&')*)-0-(0%()(��C (((((((((((((((((((((((((((((((((((((((((((((((((((����"�������@�@�hC��}!���Ѱ��<"� 9iׂIIIHk�+?�c?��*Y�����!�du)b�T�9вU�$8G��I.�澬��D���Sq� q�}.<��Z�l�V!X� *x�-�\����t3i�Ũ�sNv71�ƛ\��z|t�L���$�����*f��kʮ��7�H;���~F%�'3�@�H�q�` 9mOL����/x@ @��G
d�8F�ه��Ka�Kdr�Fh.�]y4 JЛ��]�K�B�E$��$ $ �PR�����G�]��u�i$�$���'! "#031���C/Td=S�Q?���62Ccj{ ����̏d�چ/c�V�`��Wz͈�{Y`�d�h�L �]OB���l���o���mr���n��s-ڗEZ��N�_��1%b���H�ϣ������V�7):�ӷ)�}�~�(�;�!�b1�5K��[E�vϻ>��q.%� ���O���(�c�#x�$�'+��`٥v��v(�����M�"�v��B��.�a ���T�~�ϕ�hy(6nݱl��1yNɓx�������AR�8�rqv1.cS�+��_���&@�� �u�M�5Ĉ�Xm���eL�X�q��y#�9]�c�}ɄL��d�eJ몓���I1T�d��CaM�$��T�,�X �bʭ�!�%F5��X1x#���!�q��\��F��2��&Rq���C�ol~�̱�.0ϦL�d�`.������ ���m{�Y~k{C��}bv�;U��c<�r�~ɜs�1�j��]W�l��*նCr��Q�N9�-������d��E؛��nF��eړ�8(q��5UgRȱGTA��*������̆��V�珰����ezN��h�U]�T�FG�^���<��ay�,!���5.� �u�bΚ�V�J%��m�Dxn'�����6�@BPa�`��Hts� �ɮ���Ŏ�Zɬ��%B�X��d5Z���hC}�䅸�p+ k=��ʒ(�aՏFG&�%@/�{+�Yu+�ȣGѩ"O%�|vȲxF>�N(��ou�h6 &Y5��8�7�E$-��']n,@TD\��+���Ry�U��U^�Q,f>��1�����q��f��U��� ����F���ڥ��>I�����fNUw�u��#OMMQ6� N�*��_�� k� ����rS��`���1�:��!�F'<+� � b?O��2 !Q12A��� "3a������#$��?�,�7�!`yǮ(�1�6w��a���� �F�#��?*"s���v>��Ⱥ����f�v��͑���s����������]Gn��S ���ȥpG ы�E�g�)Z���x�rY�q�]�@f�_܃�pչEڎّC ����Ŝ*/ �h�O�Sv�و\��5��U��y��|o�Hm2C�S�BW����)��5��{T��W���=o*RA��<����L0g4{��쁢�ep�rw�8��7��U���t<Ԍѻ7�fGf�k}���Ê�㛆Gռz�Q@��{C��'G��8�!�S$�j��x���|���צV<��,����u�k�uu�rM�f�_dϣi ߫�ԟn�!K����mxu�=�槻�'j�X�����������%!A "1QR#Br��?�R:��R�n�b[�II?#��6<:�$gN����lGNlrr��dעMMn`ɿy�,�%B�e�W��dVS��r���� %�tT��(�ɷ��S�]�O]#�_LEMHN�M���kv���~X���O6�U�V_�����b���J�t�774����D!1AQa"2q�#3BRb����0���� 4CSr����cst�����?��^q���7�dG�U�"p��moz��'��n_x���唹e������<6��O�t���R>k��s=�Cr���e�?�i��� ����/��ں$be���o`ޮ�GHy�;fNAl�8��.�\�S������"���a�úF�YvNk�-*`v�k�ʈ2f�EE��Wa�,� �fF^#�;��[9��^~������Y$:0#W3������Z*���I�Z�ڹ�k�n--9=��G��;7F)m{T�Ɇ��=�����Ȭ5�5�B�aڞ5M����#m�5Ʀ��m�8��+Hh���$�}�:&�e�Q�[;i]С�:�:��o����$<~��5RB�?�s3�5�r��O��ֿ�w�P/��̅���(�Z6�R>)��N��4�!ʊ�wz�-�r�w+�yk���q�1�bKhƸ�4N�Ӑ�X����Q��_��})�+e1�5��n��q?��[�^�9�<�z3Fsi�8�'�)9p)�{��RP�Z+�*��p(aY��V����6l�g�9��;���d�u���Nt@�3�sTwzaŇ�GT�b�H��(#��*zc�������9K�b1�����t����Ê��
�Z?g�iD���H�R���B���^M����v���O���L�D,'d�q�C�P�����$Δ��U�֟֊=�s��F�$��J�ދZ?�N��������A�N�WP��,�� �¦�&;�x��dup�����i���Ipd���;�Dž!��ֿѮAb%�u��}j��-p��>I�[�N�bi����G�'�;4w�m]H�]����#LӘNN��R��������s�.]��en��-�8e��Ps����Q��;���ț�E�ݫ���7��g�_L��W��EZ:/��I���a�g�n�ܤ��iٹ���ŷ�T���H~i�a�����֎�~KV������ A-2m]�F"�m�9-Zbǰ�״ @����~�4�N�[�Uxč�tl>������u#r�gѐ�3���;M9�<�J�����1�vfL8����1�P�HgP�Xv��������{����O�}�n��KQ؋����7<�l�fey<�}�>�bX���4<`Y7���si��V)�s�:�{�rO�h�z �@4VW�B���&�������ɡob܋�F��4>y�s�fXWS�N�O$�,.u:�ԫ��g�yao4��$h��D#��ٸf^kh�7�#1Z�֥&���*�v-��;bޭ����Q�����h�ow�y]�ه.+�7�M�ⴻ �JY��g�f�i3q��KC��3�¹�?5�Z.N��^Z w���KF͂���7��ރ۞��wj��T�J.�q��\Sv1U����R��욽&�N����pЖ`�`у��m`v�n#z��4��>e��V�`'���h�����'�j�AҔ�-�4:H���n]9�h<��n����U�6m��2c�E�1/�Y�%���I��~ʏ�|VBƟ@����;�������%�M9M���}��1�D��d����%g���O��]��у&�r��f�7�uܲ���(!1AQaq�������0� ���?!��*��@)�Je�G��j��{�['��v+���������)���(�/����д%젍Z��kk�Lu�Rm���j.c���@Z� V�J��d��j���h6���2AO�� a;oBu���H�=���nK�W8�B�ɰ�u?��бأm,�sr����|����8˨i��qI2tZ�ۄJP��XE��������zޔj~]UMu����zv!����N�&�1�Y��zJ�ՠ��\p��o'ሸ�C؊Y��TD"HM5�Ъ��i߯a���F����A)�����ڮ����z�E���@�hg�֝8�1jk��\�M�3�8ܢ�� ������s�7����N}�ޭ������GN�Bc���L pk�;�J�δ3�e�iU�gAYW]\�>�GyگQ=��f�KA;T�a`eM+Q �� �Ln���̌]GM�����<Ħ�j���H��N�M�x�}aX{̣S� ��ԅ��n�MA�S�r�(����(�L��zo9���.�;
�ӳf������`Ӕ٢3�� IW��\9~_���saa�\ԊW�ܭX:���ӆ�38�ty*����N�qP����BI�Y��jE��>DP�!�R%-��4��'�皺;��~J�!�7m���X��h�P!曭���$�\�AYj�.lC��4��+�jD�dgC0-*���|��`ZD�+л�C"��)��s��8Kq�pq���Ms��4� ��7\U`�.��[Ey8��AH!/��,���(:M -�T䓥�~O�4-���Ԓn��}HDN7���K���$�_Ԕ䚞`�R�hB�_aX?4V��ŗ�@ه�u�a�;�{PcT+�������7YBo�?��r-ͩ{�ĎA�� ����˼n��M286��G���1���V�˜Jв"l��V5���5�C]h���̊�A���%� �'p���Ԃ���Ր��9=�d�=�e�{�'<3�_ �:^�~��4�(�n�-C�s��5m![�jmIqU�~�Tw8��`���p�H8�u�Д l m�aP�0�������9y����CM��F1G糞�.�U~�������FC�{�!e(Y�:���P����7~;�L�N^{�1r�\���ԬG(���0d�ÏO�qK�Z�⑼�T�{ 2��s��Kd�Տ?mMQ��=���6�7�i�����H+����9��d��=��;�QؤH8n�Lb�D��yS%�(�{b���Cu���p�t#C���$A"�H{���jqᶯ�:�n=E����hH�`�!�m��MA������?�v6���+MԿ⟚qK�i�D�*Q5��CZ���2�|]�:Xd+�t�:o@��M��� :�32��b����[\5=�ֵ7])�|t��Ϻ����w�B�ń�e���!`�:��I,��9:����j@/a 8����+<�u�(T^ۺ~��2oE�B�%b)��z��ݳځ�)��i�j��&��Fi`qr��w���7�@��P�� �3Z&<�m�S�C����7t�T����ƴ�q~J�e�r6�Z]�rL���ه�E17'�x���+[�ܜTc6�/�����W�`�qpMJ���N5^����x�}{l�Fm������1�oZ\�����/d�/6� �uӸ�0elXuX;M��$M�}mB��������Z%e���3f�js����O�J~2�z�86�*PB��v�Ν��e-��.�/��L�O����2����9���4}|��T5M���hÐ7�F*��l+y0����:|��=k[�d�;|�ԉe�=w�<��õ�<��'!1AQaq����� ������?��5����)�(���+>v����6&{���Ǹ@����M�����v��iA 6T'�w��h�s �E}�x��G&'g�� J~1q�f�f���&��q˘���-���vYm
�/i1 �I��6��u,)�#�,����l}*&`�$�ͬe�%�w3�x�Ѥ�Xc�D��执g�峕�5B/�|$��=���%8 a��2.l� c�@G� �\�/x[өq�]�v5?�����N|�!���\��,>��{�"r�/��?��&!1QAa�� ��ᑱ����?ĊD�肭�� nv@�yޝ (�����I ����U - ���b�m�E>,��1v!�d�&�� ���&�檔�5D�&0P��Ԕ�͒@Z��:E"� Q��`>PH:~�O�����P�3W��@hM��k�U��\�O��R�������5ʄ�,��f�|��r���}јxo)�"+h�QK���/��0�`�5�{M~�� ���'!1AQaq���0 �������?�?�k��#^�~�G��#V,������#Z�1'ܤ����������~p�O%O�O�\�q�`�~��}��E�Ű5 �輸�du����x\�$���s[�{T2t`B��gq�4Z]b� 㛪�3,(@����bAp�r)9:@|b�!r�g:N�^�Ʌ��� �x_�\��pm7I��0?>^k��������w���|.K�[sF@�]Gn*L �yO� le�P�.p��֍�j�S�=�ʨ�ןQF�"��5zʼn���k�*8�u" ����Fg��� �cSy�V������Ƈ��N��ؐ(�����48hV�A�ӎ^��^ ���jyB� ��p"�����y]�ļlU�(�7�U`3�pCGF'&yg������o��z������X��ν:�P"@�G@x[��o&MJ�$F.����hi w;}�/^͇q���n�mN�/�TQ���އ��O1\,}��bQ #¯^S!)��X���#GPȏ�t�� c^\��' }iIZ���a�)��������z��4͊�Ξy��48,��f���#�����KP!Jx�|w�ʆ�������������#��Z�������< �~K��r�p&qH/;�R���沽�+�E�R���~0v���V#ʀ�T��S(-ڝ��B�y�b�C�D������b��������8��~�= �Y�ͧ]��@n����M�k2�%�;�%,�r6�LR腻?^��;KŇ=�ք ���=`�ɥ��/����z�&�I{���#J��M���C��}�H9^UJ�,P ��pS����G�d69Ϭu���%"��ˢP��K�"k)��=��9� ����㇌,��Oli��Xzh� " � ������R��^�s����N�k��Q>�63(���� ��PQ�Py�����3����$f+W՛=4�ǁ`*��^��Eb�K�t�6��^��!�籷��ȭ��K{/;�L���p�x�����;a���Oلz�[�.NP4�]Gc�T�v����~sg'LED��]j��'�G�]�6rY����UPw�*O�İՋi�'8�۴�#g�Xx+=�eU6�R��c�"�u2��~�?n�y�;�u��3�'��6�f������b��߬M�$*��k&?6���*^1n����ێz)<��Gz� �����7����Y� ��ۃ)$A��2�L6� ե�H�<�r��#ʽ2��O��R���z�A��XW��@���������<�G� Ϥ�^�˓i�M�W���6 ��0��m){c�;ݧ�>R�a����}1�ٯ%�EY2�Q��Ep���$ ��E��qS��t#+x� *�h�UI��XM?�'//��a'�G�����q@���<��z��؟����cd��z�ˬT_u�Ѯ����&�z�k ��n ]�a%�py»�`Qd�xc������n�� ��*��oTd�;'j�<�!j���'�(~�ʹW�M� P�mȘ��@֨V+��R�`�$��`�+@��_[�kG����P���Zh9�R����&5b�v���Z���#p�&�Ա+��8�etZ7G���;��@"�e0���v7����?��z�?_���_�q1�T�"�p�ˎ/U 6_�B�>��0( ��}G#������Ȣ�p�� �9��;/& `�B&$�y��t(�*z�x���Ӕ������S�?Kȏ3���{p� b � ۍ-�z܈֦��6?<���ǬP�N�G �更� �6�/h�����0Z���������i�ua��e�*M'A� �x��v�q.>�F� oN{��Q���{gD��L��u��=|���O xN���d���q�8(��E�Uu��,��O� t�DJ ����;��G����e���C��VYZ�� ���T4{����(�Ӳ'c�t�f��w�c�jr�e�m �#7,�6��B�E4Q�P�.P�(&��^{9H-�m�o ��q�g1���=��>p�)/"p0!4�mS6ú�FN���h��D �)��XdT �FؤZ⸚�k���H�c8v� <���u�P�Հ���:��_�EN��|�ӛ��u?-�/�o�Lhk�ܸ�S�;�Rī�����T"�N����M��px7<�� j�$��`�Y)Pjh 5` K�Qf�4�C�bX"�D���;HD�Z�9R b�F)�UA����v�#��HD�!{������>I� �`�ԁ i�4�)t*�ç�Le�_���>ru�GEQg��ǔct��ō0��l6v���d�� ��GG8���v^�|�#JyZPSO�� Y�CuAߐ�"�x���OfHF@�K�V�!少Eҕ]h� ��[���)��.q����*0I<8��^�6�}p��^tho���ig�i����DK���p,��2�3�I��5����쓄OY�6s7Qs�Ow^�w�J/�A➰������0������g(Մ��y��Kԇ����QS��?H���w�X�=��ҞX�~���Q=�'���p?7�@g�~�G�}�r��g�T?���
One Hat Cyber Team
One Hat Cyber Team
Your IP :
18.117.120.35
Server IP :
162.0.235.113
Server :
Linux premium146.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software :
LiteSpeed
PHP Version :
5.6.40
Buat File
|
Buat Folder
Dir :
~
/
opt
/
alt
/
ruby34
/
share
/
rubygems
/
rubygems
/
Edit File Name:
security.rb
# frozen_string_literal: true #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require_relative "exceptions" require_relative "openssl" ## # = Signing gems # # The Gem::Security implements cryptographic signatures for gems. The section # below is a step-by-step guide to using signed gems and generating your own. # # == Walkthrough # # === Building your certificate # # In order to start signing your gems, you'll need to build a private key and # a self-signed certificate. Here's how: # # # build a private key and certificate for yourself: # $ gem cert --build you@example.com # # This could take anywhere from a few seconds to a minute or two, depending on # the speed of your computer (public key algorithms aren't exactly the # speediest crypto algorithms in the world). When it's finished, you'll see # the files "gem-private_key.pem" and "gem-public_cert.pem" in the current # directory. # # First things first: Move both files to ~/.gem if you don't already have a # key and certificate in that directory. Ensure the file permissions make the # key unreadable by others (by default the file is saved securely). # # Keep your private key hidden; if it's compromised, someone can sign packages # as you (note: PKI has ways of mitigating the risk of stolen keys; more on # that later). # # === Signing Gems # # In RubyGems 2 and newer there is no extra work to sign a gem. RubyGems will # automatically find your key and certificate in your home directory and use # them to sign newly packaged gems. # # If your certificate is not self-signed (signed by a third party) RubyGems # will attempt to load the certificate chain from the trusted certificates. # Use <code>gem cert --add signing_cert.pem</code> to add your signers as # trusted certificates. See below for further information on certificate # chains. # # If you build your gem it will automatically be signed. If you peek inside # your gem file, you'll see a couple of new files have been added: # # $ tar tf your-gem-1.0.gem # metadata.gz # metadata.gz.sig # metadata signature # data.tar.gz # data.tar.gz.sig # data signature # checksums.yaml.gz # checksums.yaml.gz.sig # checksums signature # # === Manually signing gems # # If you wish to store your key in a separate secure location you'll need to # set your gems up for signing by hand. To do this, set the # <code>signing_key</code> and <code>cert_chain</code> in the gemspec before # packaging your gem: # # s.signing_key = '/secure/path/to/gem-private_key.pem' # s.cert_chain = %w[/secure/path/to/gem-public_cert.pem] # # When you package your gem with these options set RubyGems will automatically # load your key and certificate from the secure paths. # # === Signed gems and security policies # # Now let's verify the signature. Go ahead and install the gem, but add the # following options: <code>-P HighSecurity</code>, like this: # # # install the gem with using the security policy "HighSecurity" # $ sudo gem install your.gem -P HighSecurity # # The <code>-P</code> option sets your security policy -- we'll talk about # that in just a minute. Eh, what's this? # # $ gem install -P HighSecurity your-gem-1.0.gem # ERROR: While executing gem ... (Gem::Security::Exception) # root cert /CN=you/DC=example is not trusted # # The culprit here is the security policy. RubyGems has several different # security policies. Let's take a short break and go over the security # policies. Here's a list of the available security policies, and a brief # description of each one: # # * NoSecurity - Well, no security at all. Signed packages are treated like # unsigned packages. # * LowSecurity - Pretty much no security. If a package is signed then # RubyGems will make sure the signature matches the signing # certificate, and that the signing certificate hasn't expired, but # that's it. A malicious user could easily circumvent this kind of # security. # * MediumSecurity - Better than LowSecurity and NoSecurity, but still # fallible. Package contents are verified against the signing # certificate, and the signing certificate is checked for validity, # and checked against the rest of the certificate chain (if you don't # know what a certificate chain is, stay tuned, we'll get to that). # The biggest improvement over LowSecurity is that MediumSecurity # won't install packages that are signed by untrusted sources. # Unfortunately, MediumSecurity still isn't totally secure -- a # malicious user can still unpack the gem, strip the signatures, and # distribute the gem unsigned. # * HighSecurity - Here's the bugger that got us into this mess. # The HighSecurity policy is identical to the MediumSecurity policy, # except that it does not allow unsigned gems. A malicious user # doesn't have a whole lot of options here; they can't modify the # package contents without invalidating the signature, and they can't # modify or remove signature or the signing certificate chain, or # RubyGems will simply refuse to install the package. Oh well, maybe # they'll have better luck causing problems for CPAN users instead :). # # The reason RubyGems refused to install your shiny new signed gem was because # it was from an untrusted source. Well, your code is infallible (naturally), # so you need to add yourself as a trusted source: # # # add trusted certificate # gem cert --add ~/.gem/gem-public_cert.pem # # You've now added your public certificate as a trusted source. Now you can # install packages signed by your private key without any hassle. Let's try # the install command above again: # # # install the gem with using the HighSecurity policy (and this time # # without any shenanigans) # $ gem install -P HighSecurity your-gem-1.0.gem # Successfully installed your-gem-1.0 # 1 gem installed # # This time RubyGems will accept your signed package and begin installing. # # While you're waiting for RubyGems to work it's magic, have a look at some of # the other security commands by running <code>gem help cert</code>: # # Options: # -a, --add CERT Add a trusted certificate. # -l, --list [FILTER] List trusted certificates where the # subject contains FILTER # -r, --remove FILTER Remove trusted certificates where the # subject contains FILTER # -b, --build EMAIL_ADDR Build private key and self-signed # certificate for EMAIL_ADDR # -C, --certificate CERT Signing certificate for --sign # -K, --private-key KEY Key for --sign or --build # -A, --key-algorithm ALGORITHM Select key algorithm for --build from RSA, DSA, or EC. Defaults to RSA. # -s, --sign CERT Signs CERT with the key from -K # and the certificate from -C # -d, --days NUMBER_OF_DAYS Days before the certificate expires # -R, --re-sign Re-signs the certificate from -C with the key from -K # # We've already covered the <code>--build</code> option, and the # <code>--add</code>, <code>--list</code>, and <code>--remove</code> commands # seem fairly straightforward; they allow you to add, list, and remove the # certificates in your trusted certificate list. But what's with this # <code>--sign</code> option? # # === Certificate chains # # To answer that question, let's take a look at "certificate chains", a # concept I mentioned earlier. There are a couple of problems with # self-signed certificates: first of all, self-signed certificates don't offer # a whole lot of security. Sure, the certificate says Yukihiro Matsumoto, but # how do I know it was actually generated and signed by matz himself unless he # gave me the certificate in person? # # The second problem is scalability. Sure, if there are 50 gem authors, then # I have 50 trusted certificates, no problem. What if there are 500 gem # authors? 1000? Having to constantly add new trusted certificates is a # pain, and it actually makes the trust system less secure by encouraging # RubyGems users to blindly trust new certificates. # # Here's where certificate chains come in. A certificate chain establishes an # arbitrarily long chain of trust between an issuing certificate and a child # certificate. So instead of trusting certificates on a per-developer basis, # we use the PKI concept of certificate chains to build a logical hierarchy of # trust. Here's a hypothetical example of a trust hierarchy based (roughly) # on geography: # # -------------------------- # | rubygems@rubygems.org | # -------------------------- # | # ----------------------------------- # | | # ---------------------------- ----------------------------- # | seattlerb@seattlerb.org | | dcrubyists@richkilmer.com | # ---------------------------- ----------------------------- # | | | | # --------------- ---------------- ----------- -------------- # | drbrain | | zenspider | | pabs@dc | | tomcope@dc | # --------------- ---------------- ----------- -------------- # # # Now, rather than having 4 trusted certificates (one for drbrain, zenspider, # pabs@dc, and tomecope@dc), a user could actually get by with one # certificate, the "rubygems@rubygems.org" certificate. # # Here's how it works: # # I install "rdoc-3.12.gem", a package signed by "drbrain". I've never heard # of "drbrain", but his certificate has a valid signature from the # "seattle.rb@seattlerb.org" certificate, which in turn has a valid signature # from the "rubygems@rubygems.org" certificate. Voila! At this point, it's # much more reasonable for me to trust a package signed by "drbrain", because # I can establish a chain to "rubygems@rubygems.org", which I do trust. # # === Signing certificates # # The <code>--sign</code> option allows all this to happen. A developer # creates their build certificate with the <code>--build</code> option, then # has their certificate signed by taking it with them to their next regional # Ruby meetup (in our hypothetical example), and it's signed there by the # person holding the regional RubyGems signing certificate, which is signed at # the next RubyConf by the holder of the top-level RubyGems certificate. At # each point the issuer runs the same command: # # # sign a certificate with the specified key and certificate # # (note that this modifies client_cert.pem!) # $ gem cert -K /mnt/floppy/issuer-priv_key.pem -C issuer-pub_cert.pem # --sign client_cert.pem # # Then the holder of issued certificate (in this case, your buddy "drbrain"), # can start using this signed certificate to sign RubyGems. By the way, in # order to let everyone else know about his new fancy signed certificate, # "drbrain" would save his newly signed certificate as # <code>~/.gem/gem-public_cert.pem</code> # # Obviously this RubyGems trust infrastructure doesn't exist yet. Also, in # the "real world", issuers actually generate the child certificate from a # certificate request, rather than sign an existing certificate. And our # hypothetical infrastructure is missing a certificate revocation system. # These are that can be fixed in the future... # # At this point you should know how to do all of these new and interesting # things: # # * build a gem signing key and certificate # * adjust your security policy # * modify your trusted certificate list # * sign a certificate # # == Manually verifying signatures # # In case you don't trust RubyGems you can verify gem signatures manually: # # 1. Fetch and unpack the gem # # gem fetch some_signed_gem # tar -xf some_signed_gem-1.0.gem # # 2. Grab the public key from the gemspec # # gem spec some_signed_gem-1.0.gem cert_chain | \ # ruby -rpsych -e 'puts Psych.load($stdin)' > public_key.crt # # 3. Generate a SHA1 hash of the data.tar.gz # # openssl dgst -sha1 < data.tar.gz > my.hash # # 4. Verify the signature # # openssl rsautl -verify -inkey public_key.crt -certin \ # -in data.tar.gz.sig > verified.hash # # 5. Compare your hash to the verified hash # # diff -s verified.hash my.hash # # 6. Repeat 5 and 6 with metadata.gz # # == OpenSSL Reference # # The .pem files generated by --build and --sign are PEM files. Here's a # couple of useful OpenSSL commands for manipulating them: # # # convert a PEM format X509 certificate into DER format: # # (note: Windows .cer files are X509 certificates in DER format) # $ openssl x509 -in input.pem -outform der -out output.der # # # print out the certificate in a human-readable format: # $ openssl x509 -in input.pem -noout -text # # And you can do the same thing with the private key file as well: # # # convert a PEM format RSA key into DER format: # $ openssl rsa -in input_key.pem -outform der -out output_key.der # # # print out the key in a human readable format: # $ openssl rsa -in input_key.pem -noout -text # # == Bugs/TODO # # * There's no way to define a system-wide trust list. # * custom security policies (from a YAML file, etc) # * Simple method to generate a signed certificate request # * Support for OCSP, SCVP, CRLs, or some other form of cert status check # (list is in order of preference) # * Support for encrypted private keys # * Some sort of semi-formal trust hierarchy (see long-winded explanation # above) # * Path discovery (for gem certificate chains that don't have a self-signed # root) -- by the way, since we don't have this, THE ROOT OF THE CERTIFICATE # CHAIN MUST BE SELF SIGNED if Policy#verify_root is true (and it is for the # MediumSecurity and HighSecurity policies) # * Better explanation of X509 naming (ie, we don't have to use email # addresses) # * Honor AIA field (see note about OCSP above) # * Honor extension restrictions # * Might be better to store the certificate chain as a PKCS#7 or PKCS#12 # file, instead of an array embedded in the metadata. # # == Original author # # Paul Duncan <pabs@pablotron.org> # https://pablotron.org/ module Gem::Security ## # Gem::Security default exception type class Exception < Gem::Exception; end ## # Used internally to select the signing digest from all computed digests DIGEST_NAME = "SHA256" # :nodoc: ## # Length of keys created by RSA and DSA keys RSA_DSA_KEY_LENGTH = 3072 ## # Default algorithm to use when building a key pair DEFAULT_KEY_ALGORITHM = "RSA" ## # Named curve used for Elliptic Curve EC_NAME = "secp384r1" ## # Cipher used to encrypt the key pair used to sign gems. # Must be in the list returned by OpenSSL::Cipher.ciphers KEY_CIPHER = OpenSSL::Cipher.new("AES-256-CBC") if defined?(OpenSSL::Cipher) ## # One day in seconds ONE_DAY = 86_400 ## # One year in seconds ONE_YEAR = ONE_DAY * 365 ## # The default set of extensions are: # # * The certificate is not a certificate authority # * The key for the certificate may be used for key and data encipherment # and digital signatures # * The certificate contains a subject key identifier EXTENSIONS = { "basicConstraints" => "CA:FALSE", "keyUsage" => "keyEncipherment,dataEncipherment,digitalSignature", "subjectKeyIdentifier" => "hash", }.freeze def self.alt_name_or_x509_entry(certificate, x509_entry) alt_name = certificate.extensions.find do |extension| extension.oid == "#{x509_entry}AltName" end return alt_name.value if alt_name certificate.send x509_entry end ## # Creates an unsigned certificate for +subject+ and +key+. The lifetime of # the key is from the current time to +age+ which defaults to one year. # # The +extensions+ restrict the key to the indicated uses. def self.create_cert(subject, key, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1) cert = OpenSSL::X509::Certificate.new cert.public_key = get_public_key(key) cert.version = 2 cert.serial = serial cert.not_before = Time.now cert.not_after = Time.now + age cert.subject = subject ef = OpenSSL::X509::ExtensionFactory.new nil, cert cert.extensions = extensions.map do |ext_name, value| ef.create_extension ext_name, value end cert end ## # Gets the right public key from a PKey instance def self.get_public_key(key) # Ruby 3.0 (Ruby/OpenSSL 2.2) or later return OpenSSL::PKey.read(key.public_to_der) if key.respond_to?(:public_to_der) return key.public_key unless key.is_a?(OpenSSL::PKey::EC) ec_key = OpenSSL::PKey::EC.new(key.group.curve_name) ec_key.public_key = key.public_key ec_key end ## # Creates a self-signed certificate with an issuer and subject from +email+, # a subject alternative name of +email+ and the given +extensions+ for the # +key+. def self.create_cert_email(email, key, age = ONE_YEAR, extensions = EXTENSIONS) subject = email_to_name email extensions = extensions.merge "subjectAltName" => "email:#{email}" create_cert_self_signed subject, key, age, extensions end ## # Creates a self-signed certificate with an issuer and subject of +subject+ # and the given +extensions+ for the +key+. def self.create_cert_self_signed(subject, key, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1) certificate = create_cert subject, key, age, extensions sign certificate, key, certificate, age, extensions, serial end ## # Creates a new digest instance using the specified +algorithm+. The default # is SHA256. def self.create_digest(algorithm = DIGEST_NAME) OpenSSL::Digest.new(algorithm) end ## # Creates a new key pair of the specified +algorithm+. RSA, DSA, and EC # are supported. def self.create_key(algorithm) if defined?(OpenSSL::PKey) case algorithm.downcase when "dsa" OpenSSL::PKey::DSA.new(RSA_DSA_KEY_LENGTH) when "rsa" OpenSSL::PKey::RSA.new(RSA_DSA_KEY_LENGTH) when "ec" OpenSSL::PKey::EC.generate(EC_NAME) else raise Gem::Security::Exception, "#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported." end end end ## # Turns +email_address+ into an OpenSSL::X509::Name def self.email_to_name(email_address) email_address = email_address.gsub(/[^\w@.-]+/i, "_") cn, dcs = email_address.split "@" dcs = dcs.split "." OpenSSL::X509::Name.new([ ["CN", cn], *dcs.map {|dc| ["DC", dc] }, ]) end ## # Signs +expired_certificate+ with +private_key+ if the keys match and the # expired certificate was self-signed. #-- # TODO increment serial def self.re_sign(expired_certificate, private_key, age = ONE_YEAR, extensions = EXTENSIONS) raise Gem::Security::Exception, "incorrect signing key for re-signing " + expired_certificate.subject.to_s unless expired_certificate.check_private_key(private_key) unless expired_certificate.subject.to_s == expired_certificate.issuer.to_s subject = alt_name_or_x509_entry expired_certificate, :subject issuer = alt_name_or_x509_entry expired_certificate, :issuer raise Gem::Security::Exception, "#{subject} is not self-signed, contact #{issuer} " \ "to obtain a valid certificate" end serial = expired_certificate.serial + 1 create_cert_self_signed(expired_certificate.subject, private_key, age, extensions, serial) end ## # Resets the trust directory for verifying gems. def self.reset @trust_dir = nil end ## # Sign the public key from +certificate+ with the +signing_key+ and # +signing_cert+, using the Gem::Security::DIGEST_NAME. Uses the # default certificate validity range and extensions. # # Returns the newly signed certificate. def self.sign(certificate, signing_key, signing_cert, age = ONE_YEAR, extensions = EXTENSIONS, serial = 1) signee_subject = certificate.subject signee_key = certificate.public_key alt_name = certificate.extensions.find do |extension| extension.oid == "subjectAltName" end extensions = extensions.merge "subjectAltName" => alt_name.value if alt_name issuer_alt_name = signing_cert.extensions.find do |extension| extension.oid == "subjectAltName" end extensions = extensions.merge "issuerAltName" => issuer_alt_name.value if issuer_alt_name signed = create_cert signee_subject, signee_key, age, extensions, serial signed.issuer = signing_cert.subject signed.sign signing_key, Gem::Security::DIGEST_NAME end ## # Returns a Gem::Security::TrustDir which wraps the directory where trusted # certificates live. def self.trust_dir return @trust_dir if @trust_dir dir = File.join Gem.user_home, ".gem", "trust" @trust_dir ||= Gem::Security::TrustDir.new dir end ## # Enumerates the trusted certificates via Gem::Security::TrustDir. def self.trusted_certificates(&block) trust_dir.each_certificate(&block) end ## # Writes +pemmable+, which must respond to +to_pem+ to +path+ with the given # +permissions+. If passed +cipher+ and +passphrase+ those arguments will be # passed to +to_pem+. def self.write(pemmable, path, permissions = 0o600, passphrase = nil, cipher = KEY_CIPHER) path = File.expand_path path File.open path, "wb", permissions do |io| if passphrase && cipher io.write pemmable.to_pem cipher, passphrase else io.write pemmable.to_pem end end path end reset end if Gem::HAVE_OPENSSL require_relative "security/policy" require_relative "security/policies" require_relative "security/trust_dir" end require_relative "security/signer"
Save