Convert-PEM-0.13000755001750001750 014723477042 12253 5ustar00timtim000000000000README100644001750001750 3416614723477042 13246 0ustar00timtim000000000000Convert-PEM-0.13NAME Convert::PEM - Read/write encrypted ASN.1 PEM files SYNOPSIS use Convert::PEM; my $pem = Convert::PEM->new( Name => "DSA PRIVATE KEY", Macro => "DSAPrivateKey", ASN => qq( DSAPrivateKey SEQUENCE { version INTEGER, p INTEGER, q INTEGER, g INTEGER, pub_key INTEGER, priv_key INTEGER } )); my $keyfile = 'private-key.pem'; my $pwd = 'foobar'; my $pkey = $pem->read( Filename => $keyfile, Password => $pwd ); $pem->write( Content => $pkey, Password => $pwd, Filename => $keyfile ); DESCRIPTION *Convert::PEM* reads and writes PEM files containing ASN.1-encoded objects. The files can optionally be encrypted using a symmetric cipher algorithm, such as 3DES. An unencrypted PEM file might look something like this: -----BEGIN DH PARAMETERS----- MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM= -----END DH PARAMETERS----- The string beginning "MB4C..." is the Base64-encoded, ASN.1-encoded "object." An encrypted file would have headers describing the type of encryption used, and the initialization vector: -----BEGIN DH PARAMETERS----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,C814158661DC1449 AFAZFbnQNrGjZJ/ZemdVSoZa3HWujxZuvBHzHNoesxeyqqidFvnydA== -----END DH PARAMETERS----- The two headers ("Proc-Type" and "DEK-Info") indicate information about the type of encryption used, and the string starting with "AFAZ..." is the Base64-encoded, encrypted, ASN.1-encoded contents of this "object." The initialization vector ("C814158661DC1449") is chosen randomly. USAGE $pem = Convert::PEM->new( %arg ) Constructs a new *Convert::PEM* object designed to read/write an object of a specific type (given in *%arg*, see below). Returns the new object on success, "undef" on failure (see *ERROR HANDLING* for details). *%arg* can contain: * Name The name of the object; when decoding a PEM-encoded stream, the name in the encoding will be checked against the value of *Name*. Similarly, when encoding an object, the value of *Name* will be used as the name of the object in the PEM-encoded content. For example, given the string "FOO BAR", the output from *encode* will start with a header like: -----BEGIN FOO BAR----- *Name* is a required argument. * ASN An ASN.1 description of the content to be either encoded or decoded. *ASN* is an optional argument. * Macro If your ASN.1 description (in the *ASN* parameter) includes more than one ASN.1 macro definition, you will want to use the *Macro* parameter to specify which definition to use when encoding/decoding objects. For example, if your ASN.1 description looks like this: Foo ::= SEQUENCE { x INTEGER, bar Bar } Bar ::= INTEGER If you want to encode/decode a "Foo" object, you will need to tell *Convert::PEM* to use the "Foo" macro definition by using the *Macro* parameter and setting the value to "Foo". *Macro* is an optional argument when an ASN.1 description is provided. * InForm Specify what type of file to expect when using the *read* method. Value may be either PEM or DER. Default is "PEM". If "DER" is specified, encryption options are ignored when using the *read* method and file is read as an unencrypted blob. This option does not affect the *decode* behavior. *InForm* is an optional argument. * OutForm Specify what type of file the *write* method should output. Value may be either PEM or DER. Default is "PEM". If "DER" is specified, encryption options are ignored when using the *write* method and the file is written as an uncrypted blob. This option does not affect the *encode* behavior. *OutForm* is an optional argument. $obj = $pem->decode(%args) Decodes, and, optionally, decrypts a PEM file, returning the object as decoded by *Convert::ASN1*. The difference between this method and *read* is that *read* reads the contents of a PEM file on disk; this method expects you to pass the PEM contents as an argument. If an error occurs while reading the file or decrypting/decoding the contents, the function returns *undef*, and you should check the error message using the *errstr* method (below). *%args* can contain: * Content The PEM contents. * Password The password with which the file contents were encrypted. If the file is encrypted, this is a mandatory argument (well, it's not strictly mandatory, but decryption isn't going to work without it). Otherwise it's not necessary. $blob = $pem->encode(%args) Constructs the contents for the PEM file from an object: ASN.1-encodes the object, optionally encrypts those contents. Returns *undef* on failure (encryption failure, file-writing failure, etc.); in this case you should check the error message using the *errstr* method (below). On success returns the constructed PEM string. *%args* can contain: * Content This method requires either Content or DER. An error will be generated if one of these arguments are not present. A hash reference that will be passed to *Convert::ASN1::encode*, and which should correspond to the ASN.1 description you gave to the *new* method. The hash reference should have the exact same format as that returned from the *read* method. This is required unless DER is specified. * DER A string containing actual binary of the contents to be encoded. This bypasses ASN.1 encoding. May be used in lieu of Content. If specified, will override Content. * Password A password used to encrypt the contents of the PEM file. This is an optional argument; if not provided the contents will be unencrypted. * Cipher The Cipher to use if a password is provided. This is an optional argument; if not provided, the default of DES-EDE3-CBC will be used or the cipher configured is $Convert::PEM::DefaultCipher. See below for a list of supported ciphers. $obj = $pem->read(%args) Reads, decodes, and, optionally, decrypts a PEM file, returning the object as decoded by *Convert::ASN1* (or binary blob if ASN.1 description was not provided). This is implemented as a wrapper around *decode*, with the bonus of reading the PEM file from disk for you. If an error occurs while reading the file or decrypting/decoding the contents, the function returns *undef*, and you should check the error message using the *errstr* method (below). In addition to the arguments that can be passed to the *decode* method (minus the *Content* argument), *%args* can contain: * Filename The location of the PEM file that you wish to read. * InForm Specify what file type to read. Description can be found under *new* method. If specified, will override InForm provided in *new* method. $pem->write(%args) Constructs the contents for the PEM file from an object: ASN.1-encodes the object, optionally encrypts those contents; then writes the file to disk. This is implemented as a wrapper around *encode*, with the bonus of writing the file to disk for you. Returns *undef* on failure (encryption failure, file-writing failure, etc.); in this case you should check the error message using the *errstr* method (below). On success returns the constructed PEM string. In addition to the arguments for *encode*, *%args* can contain: * Filename The location on disk where you'd like the PEM file written. * OutForm Specify format to write out. Description can be found under *new* method. If specified, will override OutForm provided in *new* method. $pem->from_der(%args) Method used internally, but may be accessed directly decode an ASN.1 string into a perl structure object. If the Convert::PEM object has no ASN.1 definition, this method has no effect. * DER Binary string to convert to an object. This option is required. * Macro If the object has an ASN definition, a Macro may be specified. If specified, it will override the object's Macro if one exists. Macro is an optional argument. $pem->to_der(%args) Method used internally, but may be accessed directly to encode Content into binary data. If the Convert::PEM object has no ASN.1 definition, this method has no effect. * Content An object to be ASN.1 encoded to a binary string. * Macro If the object has an ASN definition, a Macro may be specified. If specified, it will override the object's Macro if one exists. Macro is an optional argument. $pem->errstr Returns the value of the last error that occurred. This should only be considered meaningful when you've received *undef* from one of the functions above; in all other cases its relevance is undefined. $pem->asn Returns the *Convert::ASN1* object used internally to decode and encode ASN.1 representations. This is useful when you wish to interact directly with that object; for example, if you need to call *configure* on that object to set the type of big-integer class to be used when decoding/encoding big integers: $pem->asn->configure( decode => { bigint => 'Math::Pari' }, encode => { bigint => 'Math::Pari' } ); CONFIGURATION To support any encryption/decryption, the appropriate cipher module needs to be installed. Some settings may be viewed or configured through variables or methods. Configuration settings are global to the package. If a setting is changed, it affects all Convert::PEM objects. $Convert::PEM::DefaultCipher *or* $OBJ->DefaultCipher(*[NEW_CIPHER]*) Used to configure a default cipher when writing to the disk. When using the method form " $OBJ-"DefaultCipher([NEW_CIPHER]) >, if NEW_CIPHER is not specified, will return the current setting. If the specified cipher is not recognized/valid, an error will be raised. To list supported ciphers, use "Convert::PEM::list_ciphers". Here is a list of supported Ciphers: * DES-CBC * DES-EDE3-CBC * AES-128-CBC * AES-192-CBC * AES-256-CBC * CAMELLIA-128-CBC * CAMELLIA-192-CBC * CAMELLIA-256-CBC * IDEA-CBC * SEED-CBC Convert::PEM->has_cipher(*$cipher_name*) Will see if the cipher is supported and is configured with an encryption module. Convert::PEM->has_cipher_module(*$cipher_name*) Will see if the cipher is supported and if the configured encryption module is usable. If it is not usable, will return "undef". If it is usable, will return the name of the cipher module. Convert::PEM->set_cipher_module($cipher,$module[,$all]) This function/method is used to specify a module name for a supported cipher. It accepts 2 or 3 arguments. Convert::PEM->set_cipher_module(, [,0]) or $OBJ->set_cipher_module(, [,0]) "cipher_name" A supported cipher name. Use Convert::PEM::list_ciphers() to retrieve a list of supported ciphers. "module_name" A cipher module. The module must support the following methods: $cipher_object = Cipher->new($key) $cipher_object->encrypt($plaintext) $cipher_object->decrypt($ciphertext) $cipher_object->blocksize() "all" An optional boolean argument. If true will replace the modules for all supported ciphers matching the cipher being set. Default is true. If setting a cipher, only set this to false if it is desired to use a separate cipher for different key lengths of the same algorithm. Convert::PEM->list_cipher_modules([$cipher_name]) If a *cipher_name* is provided, will return the module configured for the matching cipher name or "undef" if cipher is not supported. If *cipher_name* is not provided, will return a list of modules names configured as an array in array context or as a colon separated list in scalar context. Here is a list of the cipher modules used by default. * Crypt::DES * Crypt::DES_EDE3 * Crypt::Rijndael - "AES-128-CBC, AES-192-CBC and AES-256-CBC" * Crypt::Camellia - "CAMELLIA-128-CBC, CAMELLIA-192-CBC and CAMELLIA-256-CBC" * Crypt::IDEA * Crypt::SEED ERROR HANDLING If an error occurs in any of the above methods, the method will return "undef". You should then call the method *errstr* to determine the source of the error: $pem->errstr In the case that you do not yet have a *Convert::PEM* object (that is, if an error occurs while creating a *Convert::PEM* object), the error can be obtained as a class method: Convert::PEM->errstr For example, if you try to decode an encrypted object, and you do not give a passphrase to decrypt the object: my $obj = $pem->read( Filename => "encrypted.pem" ) or die "Decryption failed: ", $pem->errstr; LICENSE Convert::PEM is free software; you may redistribute it and/or modify it under the same terms as Perl itself. AUTHOR & COPYRIGHTS Except where otherwise noted, Convert::PEM is Copyright Benjamin Trott, cpan@stupidfool.org. All rights reserved. LICENSE100644001750001750 4653714723477042 13400 0ustar00timtim000000000000Convert-PEM-0.13This software is copyright (c) 2024 by Benjamin Trott . This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2024 by Benjamin Trott . This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Perl Artistic License 1.0 --- This software is Copyright (c) 2024 by Benjamin Trott . This is free software, licensed under: The Perl Artistic License 1.0 The "Artistic License" Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder as specified below. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as uunet.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) give non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. You may embed this Package's interpreter within an executable of yours (by linking); this shall be construed as a mere form of aggregation, provided that the complete Standard Version of the interpreter is so embedded. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whoever generated them, and may be sold commercially, and may be aggregated with this Package. If such scripts or library files are aggregated with this Package via the so-called "undump" or "unexec" methods of producing a binary executable image, then distribution of such an image shall neither be construed as a distribution of this Package nor shall it fall under the restrictions of Paragraphs 3 and 4, provided that you do not represent such an executable image as a Standard Version of this Package. 7. C subroutines (or comparably compiled subroutines in other languages) supplied by you and linked into this Package in order to emulate subroutines and variables of the language defined by this Package shall not be considered part of this Package, but are the equivalent of input as in Paragraph 6, provided these subroutines do not change the language in any way that would cause it to fail the regression tests for the language. 8. Aggregation of this Package with a commercial distribution is always permitted provided that the use of this Package is embedded; that is, when no overt attempt is made to make this Package's interfaces visible to the end user of the commercial distribution. Such use shall not be construed as a distribution of this Package. 9. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Changes100644001750001750 1101014723477042 13640 0ustar00timtim000000000000Convert-PEM-0.13Revision history for Convert::PEM 0.13 -- Mon Dec 02 23:42:25 AST 2024 [Changes Since 0.12] - Fix several issue implemented in 0.10 that caused issues in Crypt::DSA [Detailed Changes] - b430b68 Fix recent issues in Crypt::DSA in RT156495 - 3af8d80 Handle undefined values and redefined iv 0.12 -- Mon Oct 21 22:46:47 ADT 2024 [Changes Since 0.09] - Release 0.11-TRIAL as 0.12 - Added extra cipher support from @jeremy-church - see release 0.10 - Miscellaneous cleanups [Detailed Changes] - ae82ce2 v0.11 - 43861a2 Bump repo version - 4e8c59d openssl version differences - only test in author testing - 9b3e183 v0.10 0.11 -- Sun Oct 20 20:35:17 ADT 2024 [Changes Since 0.08] - Added extra cipher support from @jeremy-church - see release 0.09 - Miscellaneous cleanups [Detailed Changes] - 43861a2 Bump repo version - 4e8c59d openssl version differences - only test in author testing - 9b3e183 v0.10 0.10 -- Sun Oct 20 11:57:20 ADT 2024 - Merge PR#1 from @jeremy-church to add extra cipher support - Add DES support - Add AES 128/192/256 support - Add IDEA support - Add SEED Support - Add Camellia 128/192/256 support - Add tests and test files for additional ciphers and alternate cipher modules (if available) - Add supporting function(s)/method(s) for additional ciphers - Add tests to verify OpenSSL can read files encrypted by Convert::PEM (if available) - Change key bytes_to_key in Convert::PEM::CBC to match openssl algorithm - Make some modifications to accommodate SEED and IDEA (realy old) cipher modules - Make ASN optional - Add DER support and documentation - Add other access methods to documentation - Additional encode/decode testing with DER [Detailed Changes] - c4128fd no need to use eval for blocksize call - 0cdf983 Remove execution attributes on test files - aa16478 Move the pem and der files to a sub directory - e7b4d1a Fix spelling typos - f047d32 rand is not secure for crypto operations - 3e2847b DES and IDEA are deprecated in OpenSSL versions - bd40886 Replace tabs with spaces - 7971073 Added changes - 53a3142 Additional documentation and make ASN optional. - 879b190 Add support for additional ciphers. - 6c68073 typo fix 0.09 -- Tue Oct 15 22:59:26 ADT 2024 - 55f01eb Bump Repo Version - 4072ab2 Fixes RT#27574: encode test occasionlly fails - 204ffeb Convert build to Dist::Zilla 0.08 2010.12.06 - Altered explode() to canonicalize line endings to \n, handling DOS (\r\n) and older mac (\r) line breaks cleanly. Thanks to Matt Gramlich for the patch. - Removed sign() and auto_install() from Makefile.PL. - Removed magic svn keywords. - Converted test suite to Test::More. - Added author tests (xt/) and modified SYNOPSIS for all modules to make them pass the compilation test. 0.07 2005.05.25 - Allow passing in Name and Macro parameters on encode and decode, rather than just at initialization. - Use Class::ErrorHandler instead of our own built-in error-handling class. - Switched to using Module::Install in Makefile.PL. 0.06 2001.09.14 - Use Convert::PEM::ErrorHandler instead of defining error/errstr methods for each class. This also lets us use error/errstr as class methods. - Added Macro param to constructor; this is useful when dealing with an ASN.1 description that defines multiple ASN.1 macros, and we want to decode/encode using a specific macro. - Removed Crypt::DES_EDE3 from this distribution; it is now packaged and distributed separately, and has been added as a prereq for Convert::PEM. 0.05 2001.05.11 - Changed explode/implode so that they return/get list of headers in order in which they appear in the file. This fixes the bug where openssl-compatible PEM readers (like ssh-keygen in OpenSSH) could sometimes not read encrypted files (depending on the order given to the headers by the hash). 0.04 2001.04.22 - Changed 'Source' param back to 'Content'. 0.03 2001.04.21 - Added test suite. - Added encode/decode methods, which are the encoding and decoding routines, broken out into separate methods. read and write are now implemented as wrappers around decode and encode. This allows for more flexibility. 0.02 2001.04.20 - Added Content parameter to read method; bypasses file-reading. 0.01 2001.04.20 - original version; created by h2xs 1.19 META.yml100644001750001750 163514723477042 13612 0ustar00timtim000000000000Convert-PEM-0.13--- abstract: 'Read/write encrypted ASN.1 PEM files' author: - 'Benjamin Trott ' build_requires: Test::Exception: '0' Test::More: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.032, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Convert-PEM requires: Class::ErrorHandler: '0' Convert::ASN1: '0.34' Crypt::DES_EDE3: '0' Crypt::PRNG: '0' Digest::MD5: '0' MIME::Base64: '0' resources: homepage: https://github.com/perl-Crypt-OpenPGP/Convert-PEM repository: https://github.com/perl-Crypt-OpenPGP/Convert-PEM.git version: '0.13' x_generated_by_perl: v5.38.2 x_maintainers: - 'Timothy Legge ' x_serialization_backend: 'YAML::Tiny version 1.74' x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' MANIFEST100644001750001750 212314723477042 13463 0ustar00timtim000000000000Convert-PEM-0.13# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.032. Changes LICENSE MANIFEST META.json META.yml Makefile.PL README SIGNATURE dist.ini lib/Convert/PEM.pm lib/Convert/PEM/CBC.pm t/00-compile.t t/01-readwrite.t t/02-encode.t t/03-ede3.t t/04-explode.t t/05-des.t t/06-aes.t t/07-3des.t t/08-idea.t t/09-seed.t t/10-camellia.t t/20-opt-ciphers.t t/21-err.t t/30-opt-noasn-form.t t/31-opt-asn-form.t t/32-noasn-encode.t t/data/rsakey-3des.pem t/data/rsakey-aes128-b.pem t/data/rsakey-aes128.pem t/data/rsakey-aes192.pem t/data/rsakey-aes256.pem t/data/rsakey-bad.pem t/data/rsakey-camellia128.pem t/data/rsakey-camellia192.pem t/data/rsakey-camellia256.pem t/data/rsakey-des.pem t/data/rsakey-des3.pem t/data/rsakey-idea.pem t/data/rsakey-seed.pem t/data/rsakey.der t/data/rsakey.pem t/data/rsakey2-3des.pem t/data/rsakey2-aes128.pem t/data/rsakey2-aes192.pem t/data/rsakey2-aes256.pem t/data/rsakey2-camellia128.pem t/data/rsakey2-camellia192.pem t/data/rsakey2-camellia256.pem t/data/rsakey2-des.pem t/data/rsakey2-idea.pem t/data/rsakey2-seed.pem t/func.pl xt/pod.t xt/synopsis.t dist.ini100644001750001750 214314723477042 14000 0ustar00timtim000000000000Convert-PEM-0.13name = Convert-PEM author = Benjamin Trott license = Perl_5 abstract = Read/write encrypted ASN.1 PEM files copyright_holder = Benjamin Trott [Meta::Maintainers] maintainer = Timothy Legge [@Filter] -bundle = @Basic -remove = Readme -remove = GatherDir [Git::NextVersion] first_version = 0.09 ; this is the default version_by_branch = 0 ; this is the default version_regexp = ^(0.\d+)$ ; this is the default [Git::GatherDir] exclude_filename = Makefile.PL [CopyFilesFromBuild::Filtered] copy = Makefile.PL [OurPkgVersion] [Prereqs] Class::ErrorHandler = 0 MIME::Base64 = 0 Convert::ASN1 = 0.34 Crypt::DES_EDE3 = 0 Crypt::PRNG = 0 Digest::MD5 = 0 [Prereqs/TestRequires] Test::More = 0 Test::Exception = 0 [GithubMeta] remote = upstream [NextRelease] format = %v -- %{EEE MMM dd HH:mm:ss VVV yyyy}d filename = Changes [MetaJSON] [Git::Tag] tag_format = %V ; this is the default tag_message = %V ; this is the default [Git::Commit] changelog = Changes ; this is the default [Signature] [SignReleaseNotes] xt000755001750001750 014723477042 12627 5ustar00timtim000000000000Convert-PEM-0.13pod.t100644001750001750 20114723477042 13707 0ustar00timtim000000000000Convert-PEM-0.13/xtuse Test::More; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); t000755001750001750 014723477042 12437 5ustar00timtim000000000000Convert-PEM-0.13func.pl100644001750001750 1265014723477042 14113 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Digest::MD5 qw(md5 md5_hex); ### supporting functions sub miss { my($i,$r,$m) = @_; return $i if $r; push @{$m}, $i unless grep(/^$i$/,@{$m}); return ""; } sub run_tests { my($pem,$modules,$tests) = @_; #### files my %ciphs; my @fmiss; my @files = grep { miss($_,-e $_->{rx},\@fmiss) } map { $ciphs{$_->{name}}++;$_ } @{$tests}; if (!@files) { plan skip_all => "because these tests require existing encrypted files"; exit; } if (@fmiss) { diag("Some test files are missing\n ".join("\n ", map {colored(['yellow'],$_)} @fmiss)); } #### modules my %mods; my @mods; my @mmiss; foreach my$c (keys %ciphs) { push @mods, grep { !$mods{$_}++ } grep { miss($_,$pem->set_cipher_module($c, $_),\@mmiss) } @{$modules}; } if (!@mods) { plan skip_all => "because there are no modules installed that support cipher(s) being tested: '".join("', '", sort keys %ciphs)."'. Usually OK"; exit; } my $ossl = !system('openssl version > /dev/null'); my $ossl_ver = `openssl version`; my $cnt = 15; $cnt += 1 if $ossl; my $test_count = 1; # object creation $test_count += scalar(@mods); # setting ciphers $test_count += ( scalar(@mods) * scalar(@files) * $cnt ); # file tests plan tests => $test_count; diag "Some cipher modules failed to load and cannot be tested: '".join("', '", @mmiss)."'. usually OK" if @mmiss; diag "Some test files are missing and cannot be tested: '".join("', '", @fmiss)."'. usually OK" if @fmiss; isa_ok $pem, "Convert::PEM"; # 11 tests per file/cipher foreach my $m (@mods) { note("Start testing module $m"); ok $pem->set_cipher_module($tests->[0]->{name}, $m), "Setting all $tests->[0]->{name} related ciphers to use modules '$m'"; foreach my $t (@files) { my($obj1,$obj2); my($dec1,$dec2); my($der1,$der2); my($h1,$h2); # read the file ok -e $t->{rx} , "file '$t->{rx}' exists"; lives_ok { $obj1 = $pem->read( Filename => $t->{rx}, Password => "test" ) } "can read '$t->{rx}' file using module $m"; diag("error occurred reading file $t->{rx}: ".$pem->errstr()) if $pem->errstr(); ok defined $obj1, "Load $t->{name} encrypted object using module $m"; lives_ok { $der1 = $pem->to_der( Content => $obj1 ) } "encode object into DER format"; $h1 = lc md5_hex($der1); ok $h1 eq $t->{hash}, "hash '$h1' of key from file $t->{rx} matches expected value of '$t->{hash}'"; # encode the read object lives_ok { $dec1 = $pem->encode( Content => $obj1) } "Encode $t->{name} object from file $t->{rx} without encryption"; ok defined $dec1, $t->{name}." object encoded successfully"; diag("error occurred reading file $t->{tx}: ".$pem->errstr()) if $pem->errstr(); # write the file lives_ok { $pem->write( Filename => $t->{tx}, Password => "test", Content => $obj1, Cipher => $t->{name} ) } "can write '$t->{tx}' file using module $m"; diag("error occurred writing file $t->{tx}: ".$pem->errstr()) if $pem->errstr(); # re-read the written file lives_ok { $obj2 = $pem->read( Filename => $t->{tx}, Password => "test", Cipher => $t->{name} ) } "can re-read '$t->{tx}' file using module $m"; diag("error occurred reading file $t->{tx}: ".$pem->errstr()) if $pem->errstr(); ok defined $obj2, "read $t->{name} object from file '$t->{tx}' using module $m"; lives_ok { $dec2 = $pem->encode( Content => $obj2) } "Encode $t->{name} object from file $t->{tx} without encryption"; ok defined $dec2, "Write and re-read $t->{name} object encripted using cipher module $m"; lives_ok { $der2 = $pem->to_der( Content => $obj2 ) } "DER Encode $t->{name} object from file $t->{tx}"; $h2 = lc md5_hex($der2); ok $h2 eq $t->{hash}, "hash '$h2' of key from file $t->{tx} matches expected value of '$t->{hash}'"; # compare the original with the written/re-read ok defined $dec1 && defined $dec2 && $dec1 eq $dec2, "Read original $t->{name} file '$t->{rx}' and match contents to written file '$t->{tx}'"; # openssl tests if ($ossl) { SKIP: { skip("Author Tests only for openssl test", 1) if !$ENV{AUTHOR_TESTING}; skip("No support for IDEA-CBC", 1) if (`openssl enc -ciphers` !~ /idea-cbc/m) && ($t->{tx} =~ /idea/); skip("No support for DES", 1) if (`openssl enc -ciphers` !~ /des-cbc/m) || (($t->{tx} =~ /des.wr.pem/) && ($ossl_ver =~ /OpenSSL 3/)); ok !system("openssl rsa -in $t->{tx} -passin pass:test -noout 2> /dev/null"), "use openssl to read file '$t->{tx}' encrypted with $t->{name} using module $m"; } } unlink $t->{tx}; } } } sub get_rsa { my $rsa_asn = <new( Name => "RSA PRIVATE KEY", ASN => $rsa_asn, Macro => "RSAPrivateKey", @_, ); } 1; META.json100644001750001750 300714723477042 13755 0ustar00timtim000000000000Convert-PEM-0.13{ "abstract" : "Read/write encrypted ASN.1 PEM files", "author" : [ "Benjamin Trott " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.032, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Convert-PEM", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Class::ErrorHandler" : "0", "Convert::ASN1" : "0.34", "Crypt::DES_EDE3" : "0", "Crypt::PRNG" : "0", "Digest::MD5" : "0", "MIME::Base64" : "0" } }, "test" : { "requires" : { "Test::Exception" : "0", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "homepage" : "https://github.com/perl-Crypt-OpenPGP/Convert-PEM", "repository" : { "type" : "git", "url" : "https://github.com/perl-Crypt-OpenPGP/Convert-PEM.git", "web" : "https://github.com/perl-Crypt-OpenPGP/Convert-PEM" } }, "version" : "0.13", "x_generated_by_perl" : "v5.38.2", "x_maintainers" : [ "Timothy Legge " ], "x_serialization_backend" : "Cpanel::JSON::XS version 4.38", "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later" } SIGNATURE100644001750001750 1420414723477042 13641 0ustar00timtim000000000000Convert-PEM-0.13This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.89. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: RIPEMD160 SHA256 3067c15645c76e56649893cc6d428ea6a625b707a218df9d39f44b1a529c057d Changes SHA256 a6baf35c651ea8b931bfb6c0542d59bf42835eb55f997ee31081886d8b5e2244 LICENSE SHA256 9f7af0b6c828b50a4d09f3e90a9723b0f22bb81f88a0a3bc0020773b0ea6df82 MANIFEST SHA256 54312777cc744a170fa6d7967c0befd66ae0303579bd0e15c8f964e6a93f7663 META.json SHA256 5f0a1327fcf80c9f07fdcde985f0fba6df456ff6d163054e234d7ab9df99a308 META.yml SHA256 539ee249316cf9e2c99a85b46303e6ce6b299c6f12f199288cbc701802658abb Makefile.PL SHA256 52bf7bd189b41b3cd33c02daf92bf89b52a3a656b592a5832022fafc98d889b3 README SHA256 19d56026573c7c74b9b21866e5cfcdaa40f9b3f5ef0771949424661013f6dd41 dist.ini SHA256 0178cc76ba367c726bc9031f6d5fcf7e55a2a19e8c90ca76da20d068d152535e lib/Convert/PEM.pm SHA256 2538d282eb8ce0bcdd65fd161feb3805b7fd02d416fdeb959ec0b7e66eeadb58 lib/Convert/PEM/CBC.pm SHA256 7bccdccfcf97374ba5669237bced4efc9f7b7fb24ddb10a76b3f284e5eeaefd4 t/00-compile.t SHA256 1c086554d12bbd7df18671a9e7d45af499a33576c4cac0d891bccd12e7c02f0e t/01-readwrite.t SHA256 54977ffdd2048bef5008d7d4430c9f2a91bc2e006eb2e65291fec4363f612e79 t/02-encode.t SHA256 ff9b80fa2c9d6dc25349851f81c94ac31b691c1a7855c47261ab46a4730069c5 t/03-ede3.t SHA256 f5520c318f9d4fc6a8b2dc581214433aae377eae82ca76727848b06093b01252 t/04-explode.t SHA256 ae3ac8f462cf5219087b0eb1fc732c314008e66136ba415c05cb69dec8e005aa t/05-des.t SHA256 a19f351465fb9b9b2fc27c9cd69cde4c49e565acd2b3093f463c6b579ccac52e t/06-aes.t SHA256 6d56fb629ae45061a0d39c9b1a13095ff8e3b03f19f71c963365eb35c38b5c0c t/07-3des.t SHA256 93e686a7e0805bc995c8a1d1693312192244a80b4a4a93fd6283e7647fb6d74a t/08-idea.t SHA256 d0ba9ed404f29524768facb7ae9d193cc6f8ae4e8bef2e20b82ebb9bfd221918 t/09-seed.t SHA256 251d73b2ad01bca79d6920bfd512dee9f1713c2dae6da7918126c3305f37e196 t/10-camellia.t SHA256 4309e3b14fe434b5e319a8512f94f9d0bbcd865afb9e45ab7a56616b3149a789 t/20-opt-ciphers.t SHA256 14c6f3405ee937e714e8569a4e257fe8180f36ffbaab57f8440ba8a071d2ef1e t/21-err.t SHA256 3e9a52be6a3b2ae6cc06395c03b462d926cf70e04e171b974bf2370ccd43840f t/30-opt-noasn-form.t SHA256 34343d4c82b7fb30f02ebaf5855494546e0bcba539d662adacaac5eabd0149e7 t/31-opt-asn-form.t SHA256 f6c0b5cf8e9fe375aa662e5784fbd1e29af9370fb71d6ca92c59765918265f80 t/32-noasn-encode.t SHA256 32e07345eea64d1060a9aa15dffc4c8a5102889fab8e1e1d3e7e747a75b1ca26 t/data/rsakey-3des.pem SHA256 6d7832ec5210f33e519b2d985cca46a873e7af0b44d57ace2b75bc5691182157 t/data/rsakey-aes128-b.pem SHA256 59ad9cf70037bf4954582a7116d2a221dd4ff8dc3117112057f967186f9234d6 t/data/rsakey-aes128.pem SHA256 57385afe117901f689730ba4ead1f0ebc548a256959e3b346e9f40b7a7897b94 t/data/rsakey-aes192.pem SHA256 b109f73427ca738437bfe598f11d251841f59410149595a6bc78abdcae572f58 t/data/rsakey-aes256.pem SHA256 67cabdf472b8f868376291f655cd7bbde8b47da4c4d725e01ca14524d6cdfdc0 t/data/rsakey-bad.pem SHA256 b7bfd8a9441e963104e2a2476efc928ac5465c5af6a38fd21570b658a91ea994 t/data/rsakey-camellia128.pem SHA256 990209a36872f75c41863c8dd479ae994c2f582c481da1bbe71addc7fa019305 t/data/rsakey-camellia192.pem SHA256 68a46405afd9bb9d2476df062a7792f4a33f74c9324a99581a1ace55fb213368 t/data/rsakey-camellia256.pem SHA256 92733769aedcbf79252b97a2b27f2e5431a9d301a103feba74f541ddd66e131a t/data/rsakey-des.pem SHA256 eb841dcbfd6231d0e9074d8eccdc288199649b08228298c53fc5203584380d62 t/data/rsakey-des3.pem SHA256 bb04fd60c3f85568776a618ca61ea985401ebaebc13c329c3304688440a338d7 t/data/rsakey-idea.pem SHA256 0751e18bf5a5c7e083ee44e57f14dd776cada483524652365e18d182b6b14b84 t/data/rsakey-seed.pem SHA256 0fee820f6fda4d9bf0f4fe62501c9b0f532bc6bf77cbf9693e8227020d35d4b9 t/data/rsakey.der SHA256 f61558a0acad8327f646167a2be4272909412e77122e174d9f7048631cf235be t/data/rsakey.pem SHA256 786a0556f284ecd4cc0da8d22f8d78ce07d92d373bc3d000dcee6306eb6a8aae t/data/rsakey2-3des.pem SHA256 7ceab59627d6d7b72f2ca1f00d28fe8b401ded6677a77d1e40685abf085beaea t/data/rsakey2-aes128.pem SHA256 c66865ca68e371b69af3c73a4727d66364114ec9263839f90244e5708090a8ac t/data/rsakey2-aes192.pem SHA256 14a42b72f4b61eb439f7fbd1e36035a7152bfd9de667a053b51f356353697ffb t/data/rsakey2-aes256.pem SHA256 64eff90733312ea26ce0054d6f15e272365b3d03f901e93a2815b389aba25658 t/data/rsakey2-camellia128.pem SHA256 a2f5a55ac052e8961007b3230561d3c937852dd27390cc6f132f7fd87f91cb29 t/data/rsakey2-camellia192.pem SHA256 6538ac4c44c97ef6790ef7c8ae8b7c89f8257c898540af9f7889c754ee01caf4 t/data/rsakey2-camellia256.pem SHA256 78b046b9b346e048bf1de976c8fee01cb09a0df974bdb77f9480203f90bf5d2e t/data/rsakey2-des.pem SHA256 29dfed7fdd98cd0e69b7f586b351fb2ee6cf98bb7033f94540b379ec161cf42b t/data/rsakey2-idea.pem SHA256 15db77e94b382b79473ab28e593d20f204462d09ff0e461eb22be6f321cdd677 t/data/rsakey2-seed.pem SHA256 cde4a97500dae4ac6c396465dc73c1398f963697d345d34b35eff876c3ac1718 t/func.pl SHA256 b0db96e65e2b5300f140170b054f3b6c4bb171240b085f4d5e21f16f961bcac9 xt/pod.t SHA256 4d08fdb69fdc6a461a32b5f4248525360ff123184ffc49b0de19768714d06fd8 xt/synopsis.t -----BEGIN PGP SIGNATURE----- iQIzBAEBAwAdFiEEMguXHBCUSzAt6mNu1fh7LgYGpfkFAmdOfiIACgkQ1fh7LgYG pflEHhAAr9h8sznh4ZkbHSlk6H3WZBRFD0umCDqM3RZpuiNnaUEi6OROJgmkrFDt g6IWVHnBc7snYPnxW70rX4v43efRCppY04BFx/9fXwGiAvBrJ7p27MqiqI6SgHZA P2t9Ap8PXTpA7Phsx1tDcsKyBY4STKPeRZ/9Zv0N176aTR0uQqCceR15TVSsGxsH 63w5wgcw44foZ4Mta8aIVOkzuKHeHWP+oBrKqxNBhuCIp75DTCsxWHbgI+2Bw/AS 6JtmkhSZH3xLYndK3yprxNIdItpwTbdNYwHT09iRlC5kbcfCspvTUVRQWtLmTqhQ SP+Hf0mhxXWJYs6JX9IFHpsjeUJ8U4QCxnOEWieStxwl4SbwDUpTrEvedl2kMc2h GMlxYgaVQyg3adsJIKDDTaY5Q5WziXCo99UITvhj5bi5z/E86wFB1nnXHC2a0Vj+ 0Rtf9aUvjnHRaAfO9f+wvPgRT2whBHS1xqK37jJslqKFAVYDz6dxwYeziEMtdo0B ePKyahUT47boiJtEotmrAp1+7MDg5q9R2S3bpFSv/NeU1Jb4kCrKCSd+6aP5qvH7 WWW/YAVMFI2O/HKSO+Mb9U146jsnayVyDyf0z8sRx2rSJltmPuL8bSNzNszcOY56 Q/9OleVA820P/3QzxJgxtyRzJPq+DjvBJzjLJhiC4j2xNr6UPCk= =ok0l -----END PGP SIGNATURE----- 05-des.t100644001750001750 100214723477042 13752 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; my $pem = get_rsa(); # choose some modules to test my @modules = ("Crypt::DES"); my @tests = ( { name => "DES-CBC", rx => "t/data/rsakey-des.pem", tx => "t/data/rsakey-des.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "DES-CBC", rx => "t/data/rsakey2-des.pem", tx => "t/data/rsakey2-des.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, ); run_tests($pem,\@modules,\@tests); 06-aes.t100644001750001750 250414723477042 13760 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; my $pem = get_rsa(); # choose some modules to test # my @modules = grep { $_ ne "" } map { $pem->set_cipher_module("AES-128-CBC", $_) } ("Crypt::Cipher::AES", "Crypt::OpenSSL::AES"); my @modules = ("Crypt::Cipher::AES", "Crypt::OpenSSL::AES","Crypt::Rijndael","Crypt::Rijndael_PP"); my @tests = ( { name => "AES-128-CBC", rx => "t/data/rsakey-aes128.pem", tx => "t/data/rsakey-aes128.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "AES-192-CBC", rx => "t/data/rsakey-aes192.pem", tx => "t/data/rsakey-aes192.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "AES-256-CBC", rx => "t/data/rsakey-aes256.pem", tx => "t/data/rsakey-aes256.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "AES-128-CBC", rx => "t/data/rsakey2-aes128.pem", tx => "t/data/rsakey2-aes128.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, { name => "AES-192-CBC", rx => "t/data/rsakey2-aes192.pem", tx => "t/data/rsakey2-aes192.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, { name => "AES-256-CBC", rx => "t/data/rsakey2-aes256.pem", tx => "t/data/rsakey2-aes256.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, ); run_tests($pem,\@modules,\@tests); 21-err.t100644001750001750 57314723477042 13761 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; plan tests => 3; my $pem = get_rsa(); isa_ok $pem, "Convert::PEM", '$pem'; my $bad = "t/data/rsakey-bad.pem"; my $obj; lives_ok { $obj = $pem->read( Filename => $bad, Password => "test") } "read bad file"; ok $pem->errstr() =~ m/Decryption failed:/, "Decryption failed for bad file"; Makefile.PL100644001750001750 245214723477042 14311 0ustar00timtim000000000000Convert-PEM-0.13# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.032. use strict; use warnings; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Read/write encrypted ASN.1 PEM files", "AUTHOR" => "Benjamin Trott ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "Convert-PEM", "LICENSE" => "perl", "NAME" => "Convert::PEM", "PREREQ_PM" => { "Class::ErrorHandler" => 0, "Convert::ASN1" => "0.34", "Crypt::DES_EDE3" => 0, "Crypt::PRNG" => 0, "Digest::MD5" => 0, "MIME::Base64" => 0 }, "TEST_REQUIRES" => { "Test::Exception" => 0, "Test::More" => 0 }, "VERSION" => "0.13", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Class::ErrorHandler" => 0, "Convert::ASN1" => "0.34", "Crypt::DES_EDE3" => 0, "Crypt::PRNG" => 0, "Digest::MD5" => 0, "MIME::Base64" => 0, "Test::Exception" => 0, "Test::More" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); 03-ede3.t100644001750001750 171014723477042 14023 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More tests => 6; use Convert::PEM::CBC; my $KEY = pack "H64", ("0123456789ABCDEF" x 4); my $IV = "\0" x 8; my($cbc1, $cbc2); $cbc1 = Convert::PEM::CBC->new( Cipher => 'Crypt::DES_EDE3', Key => $KEY, IV => $IV, ); isa_ok $cbc1, 'Convert::PEM::CBC'; $cbc2 = Convert::PEM::CBC->new( Cipher => 'Crypt::DES_EDE3', Key => $KEY, IV => $IV, ); isa_ok $cbc2, 'Convert::PEM::CBC'; my($enc, $dec); $enc = $cbc1->encrypt( _checkbytes() ); ok defined $enc, 'got something from encrypt'; $dec = $cbc2->decrypt($enc); ok defined $dec, 'got something from decrypt'; is vec($dec, 0, 8), vec($dec, 2, 8), 'input1 matches output1'; is vec($dec, 1, 8), vec($dec, 3, 8), 'input2 matches output2'; sub _checkbytes { my($check1, $check2) = (chr int rand 255, chr int rand 255); "$check1$check2$check1$check2"; } 07-3des.t100644001750001750 102614723477042 14045 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; my $pem = get_rsa(); # choose some modules to test my @modules = ("Crypt::DES_EDE3"); my @tests = ( { name => "DES-EDE3-CBC", rx => "t/data/rsakey-3des.pem", tx => "t/data/rsakey-3des.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "DES-EDE3-CBC", rx => "t/data/rsakey2-3des.pem", tx => "t/data/rsakey2-3des.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, ); run_tests($pem,\@modules,\@tests); 08-idea.t100644001750001750 117214723477042 14114 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; my $pem = get_rsa(); # choose some modules to test my @modules = ("Crypt::IDEA"); if (!@modules) { plan skip_all => "because tests require at least 1 IDEA cipher module to be installed" if !@modules; exit; } my @tests = ( { name => "IDEA-CBC", rx => "t/data/rsakey-idea.pem", tx => "t/data/rsakey-idea.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "IDEA-CBC", rx => "t/data/rsakey2-idea.pem", tx => "t/data/rsakey2-idea.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, ); run_tests($pem,\@modules,\@tests); 09-seed.t100644001750001750 101114723477042 14123 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; my $pem = get_rsa(); # choose some modules to test my @modules = ("Crypt::SEED"); my @tests = ( { name => "SEED-CBC", rx => "t/data/rsakey-seed.pem", tx => "t/data/rsakey-seed.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "SEED-CBC", rx => "t/data/rsakey2-seed.pem", tx => "t/data/rsakey2-seed.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, ); run_tests($pem,\@modules,\@tests); 02-encode.t100644001750001750 220214723477042 14434 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More tests => 8; use Convert::PEM; use Math::BigInt; my $pem = Convert::PEM->new( Name => 'TEST OBJECT', ASN => qq( TestObject SEQUENCE { int INTEGER } )); isa_ok $pem, 'Convert::PEM'; my($obj, $obj2, $blob); $obj = { TestObject => { int => 4 } }; $blob = $pem->encode( Content => $obj ); ok $blob, 'encode gave us something'; $obj2 = $pem->decode( Content => $blob ); is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output'; $blob = $pem->encode( Content => $obj, Password => 'xx' ); ok $blob, 'encode gave us something'; $obj2 = $pem->decode( Content => $blob ); ok !defined $obj2, 'decode fails on encrypted input'; $obj2 = $pem->decode( Content => $blob, Password => 'xx' ); is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output'; $obj->{TestObject}{int} = Math::BigInt->new("110982309809809850938509"); $blob = $pem->encode( Content => $obj ); ok $blob, 'encode gave us something'; $obj2 = $pem->decode( Content => $blob ); is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output'; synopsis.t100644001750001750 16014723477042 15020 0ustar00timtim000000000000Convert-PEM-0.13/xtuse Test::More; eval "use Test::Synopsis"; plan skip_all => "Test::Synopsis required" if $@; all_synopsis_ok(); 00-compile.t100644001750001750 11014723477042 14601 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More tests => 1; BEGIN { use_ok 'Convert::PEM' } 04-explode.t100644001750001750 177114723477042 14653 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More tests => 4; use Convert::PEM; my $pem = Convert::PEM->new( 'Name' => 'TEST OBJECT', 'ASN' => q( TestObject SEQUENCE { int INTEGER } ) ); isa_ok( $pem, 'Convert::PEM' ); my %pemhash = ( 'Object' => 'TEST OBJECT', 'Content' => 'Simple test content that is long enough to wrap in base64.', 'Headers' => [ [ 'A' => 'Alpha' ], [ 'B' => 'Bravo' ], [ 'C' => 'Charlie' ] ], ); my $pemData = $pem->implode( %pemhash ); my $pemUnix = my $pemDos = my $pemOldMac = $pemData; $pemUnix =~ s/\r\n|\n|\r/\n/g; $pemDos =~ s/\r\n|\n|\r/\r\n/g; $pemOldMac =~ s/\r\n|\n|\r/\r/g; my $explodeUnix = $pem->explode( $pemUnix ); is_deeply( $explodeUnix, \%pemhash, "explode with unix line break" ); my $explodeDos = $pem->explode( $pemDos ); is_deeply( $explodeDos, \%pemhash, "explode with dos line break" ); my $explodeOldMac = $pem->explode( $pemOldMac ); is_deeply( $explodeOldMac, \%pemhash, "explode with old mac line break" ); 10-camellia.t100644001750001750 235614723477042 14757 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; require "./t/func.pl"; my $pem = get_rsa(); # choose some modules to test my @modules = ("Crypt::Camellia","Crypt::Camellia_PP"); my @tests = ( { name => "CAMELLIA-128-CBC", rx => "t/data/rsakey-camellia128.pem", tx => "t/data/rsakey-camellia128.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "CAMELLIA-192-CBC", rx => "t/data/rsakey-camellia192.pem", tx => "t/data/rsakey-camellia192.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "CAMELLIA-256-CBC", rx => "t/data/rsakey-camellia256.pem", tx => "t/data/rsakey-camellia256.wr.pem", hash => "45f605c6186eaea0730958b0e3da52e4", }, { name => "CAMELLIA-128-CBC", rx => "t/data/rsakey2-camellia128.pem", tx => "t/data/rsakey2-camellia128.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, { name => "CAMELLIA-192-CBC", rx => "t/data/rsakey2-camellia192.pem", tx => "t/data/rsakey2-camellia192.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, { name => "CAMELLIA-256-CBC", rx => "t/data/rsakey2-camellia256.pem", tx => "t/data/rsakey2-camellia256.wr.pem", hash => "9b334c60a2c0c2a543ac742ebf1f8ccd", }, ); run_tests($pem,\@modules,\@tests); 01-readwrite.t100644001750001750 274514723477042 15200 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More tests => 16; use Test::Exception; use Convert::PEM; use Math::BigInt; my $objfile = "./object.pem"; my $pem = Convert::PEM->new( Name => 'TEST OBJECT', ASN => qq( TestObject SEQUENCE { int INTEGER } )); isa_ok $pem, 'Convert::PEM'; my($obj, $obj2); $obj = { TestObject => { int => 4 } }; lives_ok { $pem->write( Filename => $objfile, Content => $obj) } 'can write'; ok -e $objfile, 'output file exists'; lives_ok { $obj2 = $pem->read( Filename => $objfile ) } 'can read'; is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output'; unlink $objfile; lives_ok { $pem->write( Filename => $objfile, Content => $obj, Password => 'xx' ) } 'can write'; ok -e $objfile, 'output file exists'; lives_ok { $obj2 = $pem->read( Filename => $objfile ) } 'can read'; ok !defined $obj2, 'cannot read encrypted file'; ok -e $objfile, 'encrypted output file exists'; lives_ok { $obj2 = $pem->read( Filename => $objfile, Password => 'xx') } 'can read'; is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output'; unlink $objfile; $obj->{TestObject}{int} = Math::BigInt->new("110982309809809850938509"); lives_ok { $pem->write( Filename => $objfile, Content => $obj) } 'can write'; ok -e $objfile, 'output file exists'; lives_ok { $obj2 = $pem->read( Filename => $objfile ) } 'can read'; is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'input matches output'; unlink $objfile; data000755001750001750 014723477042 13350 5ustar00timtim000000000000Convert-PEM-0.13/trsakey.der100644001750001750 71514723477042 15465 0ustar00timtim000000000000Convert-PEM-0.13/t/data0‚ÉaÜÑÐûGWñΤò¨HA*\Yص䬰B앱;&døN±PF‹0?Lr›7‡º©_¾WàŒº° ÉdÛîæ‰K»ã©³ßv`u'(§‚i°Ëv:+;¸ê¬žÅìÀ``Çhs(Ò‡} ×ù)È;b R‡“îÐçÎta qŸsCH—¡åJ)”"Ý›pòp]®¦Ê§5õ\)1?€žÃEFc¬ v…K,õÕË ÷ƒPõ{}Ù˜Ÿæ6Ä¡1øÉVÒ¬˜œ™øä÷<͹ÃÚdèøãlÑWÏ*ÜߦK7;æÎkÏöyÔˆ;ºa0YÉŠÐyµ.öÛZLùv·³ P÷F¾¡†.fз/!Ä#7<ÊwJSrsakey.pem100644001750001750 126014723477042 15510 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- MIIByQIBAAJhANzR0PtHV/HOpPKoSEEqFlxZ2LUW5KyBsELslbE7JmT4TrEDUEaL GzA/THKbN4e6qV++V+CMurAJyWTb7uaJH0u746mz33ZgdRcbJyingmmwy3Y6CCs7 uOoeEqyexezAnQIDAQABAmBgx2hzKNKHfQzX+R8pyDtioFIVFAKHBJPu0OfOdGEg cZ9zf0NIl6ED5UopFJQi3ZCbcPJwXQaupsqnNfVcKTE/gJ7DRUZjHKwNdoVLLPXV ywr3g1D1f3sFfdmYn+Y2xKECMQD4yRdW0qyYnJn45PcBPM0ducPaZI3o+ONs0VfP KtwZ36ZLPFPlwN5o9HVeoOr9dIUCMQDjOR1WwnxvD6Avd/mPsgnI0IE6Dp/LLZce WoFyOfJgB8FrtnFbO19d3oz/wqGzQzkCMFhenZKyjKo83hhhxDdFUJqhdKcrlpjN Z4MsrSMiV0I9hgUtbaOrqZTgWJx/TlkvPQIwByuCNX6llouTrmvGwDYKAQAzU7Wq bSrfHeIVO5mAgG8+Nzvmj85rz/Z51Ig7ugBhAjBZyYrQebUuF/YF21oaTPl2t7MP DBNQjfcEHgVGvqGGLmbQty8hFB4CxCM3PMp3SlM= -----END RSA PRIVATE KEY----- Convert000755001750001750 014723477042 14362 5ustar00timtim000000000000Convert-PEM-0.13/libPEM.pm100644001750001750 6140214723477042 15524 0ustar00timtim000000000000Convert-PEM-0.13/lib/Convertpackage Convert::PEM; use strict; use 5.008_001; use base qw( Class::ErrorHandler ); use MIME::Base64; use Digest::MD5 qw( md5 ); use Convert::ASN1; use Carp qw( croak ); use Convert::PEM::CBC; use Crypt::PRNG qw( random_bytes ); use vars qw( $VERSION $DefaultCipher ); our $VERSION = '0.13'; # VERSION our $DefaultCipher = 'DES-EDE3-CBC'; sub new { my $class = shift; my $pem = bless { }, $class; $pem->init(@_); } sub init { my $pem = shift; my %param = @_; unless (exists $param{Name}) { return (ref $pem)->error("init: Name is required"); } else { $pem->{Name} = $param{Name}; $pem->{ASN} = $param{ASN} if exists $param{ASN}; $pem->{Cipher} = $param{Cipher} if exists $param{Cipher}; } if (exists $pem->{ASN}) { $pem->{Macro} = $param{Macro}; my $asn = $pem->{_asn} = Convert::ASN1->new; $asn->prepare( $pem->{ASN} ) or return (ref $pem)->error("ASN prepare failed: $asn->{error}"); } $pem->_getform(%param) or return; $pem; } sub _getform { my $pem = shift; my %param = @_; my $in = defined $param{InForm} ? uc($param{InForm}) : 'PEM'; $in =~ m/^(PEM|DER)$/ or return $pem->error("Invalid InForm '$in': must be PEM or DER"); $pem->{InForm} = $in; my $out = defined $param{OutForm} ? uc($param{OutForm}) : 'PEM'; $out =~ m/^(PEM|DER)$/ or return $pem->error("Invalid OutForm '$out': must be PEM or DER"); $pem->{OutForm} = $out; $pem; } sub asn { my $pem = shift; my $asn = $pem->{_asn} || return; my %prm = @_; my $m = $prm{Macro} || $pem->{Macro}; $m ? $asn->find($m) : $asn; } sub ASN { $_[0]->{ASN} } sub name { $_[0]->{Name} } sub cipher { $_[0]->{Cipher} } sub inform { $_[0]->{InForm} } sub outform { $_[0]->{OutForm} } sub macro { $_[0]->{Macro} } sub read { my $pem = shift; my %param = @_; my $blob; my $fname = delete $param{Filename}; open my $FH, $fname or return $pem->error("Can't open $fname: $!"); binmode $FH; read($FH, $blob, -s $fname); close $FH; $pem->{InForm} eq 'DER' ? $pem->from_der( DER => $blob ) : $pem->decode(%param, Content => $blob); } sub write { my $pem = shift; my %param = @_; my $fname = delete $param{Filename} or return $pem->error("write: Filename is required"); my $blob = $pem->{OutForm} eq 'DER' ? $pem->to_der(%param) : $pem->encode(%param); open my $FH, ">$fname" or return $pem->error("Can't open $fname: $!"); binmode $FH; print $FH $blob; close $FH; $blob; } sub from_der { my $pem = shift; my %param = @_; # should always be unencrypted at this point my $obj; if (exists $pem->{ASN}) { my $asn = $pem->asn; if (my $macro = ($param{Macro} || $pem->{Macro})) { $asn = $asn->find($macro) or return $pem->error("Can't find Macro $macro"); } $obj = $asn->decode( $param{DER} ) or return $pem->error("ASN encode failed: $asn->{error}"); } else { $obj = $param{DER}; } $obj; } sub decode { my $pem = shift; my %param = @_; if (exists $param{DER}) { return $pem->from_der(%param) } my $blob = $param{Content} or return $pem->error("'Content' is required"); chomp $blob; my $dec = $pem->explode($blob) or return; my $name = $param{Name} || $pem->name; return $pem->error("Object $dec->{Object} does not match " . $name) unless $dec->{Object} eq $name; my $head = $dec->{Headers}; my $buf = $dec->{Content}; my %headers = map { $_->[0] => $_->[1] } @$head; if (%headers && $headers{'Proc-Type'} eq '4,ENCRYPTED') { $buf = $pem->decrypt( Ciphertext => $buf, Info => $headers{'DEK-Info'}, Password => $param{Password} ) or return; } $param{DER} = $buf; my $obj = $pem->from_der( %param ) or return; $obj; } sub to_der { my $pem = shift; my %param = @_; my $buf; if (exists $pem->{ASN}) { my $asn = $pem->asn; if (my $macro = ($param{Macro} || $pem->{Macro})) { $asn = $asn->find($macro) or return $pem->error("Can't find Macro $macro"); } $buf = $asn->encode( $param{Content} ) or return $pem->error("ASN encode failed: $asn->{error}"); } else { $buf = $param{Content} } $buf; } sub encode { my $pem = shift; my %param = @_; my $buf = $param{DER} || $pem->to_der(%param); my (@headers); if ($param{Password}) { my ($info); ($buf, $info) = $pem->encrypt( Plaintext => $buf, %param ) or return; push @headers, [ 'Proc-Type' => '4,ENCRYPTED' ]; push @headers, [ 'DEK-Info' => $info ]; } $pem->implode( Object => $param{Name} || $pem->name, Headers => \@headers, Content => $buf ); } sub explode { my $pem = shift; my ($message) = @_; # Canonicalize line endings into "\n". $message =~ s/\r\n|\n|\r/\n/g; my ($head, $object, $headers, $content, $tail) = $message =~ m:(-----BEGIN ([^\n\-]+)-----)\n(.*?\n\n)?(.+)(-----END .*?-----)$:s; my $buf = decode_base64($content); my @headers; if ($headers) { for my $h ( split /\n/, $headers ) { my ($k, $v) = split /:\s*/, $h, 2; push @headers, [ $k => $v ] if $k; } } { Content => $buf, Object => $object, Headers => \@headers } } sub implode { my $pem = shift; my %param = @_; my $head = "-----BEGIN $param{Object}-----"; my $tail = "-----END $param{Object}-----"; my $content = encode_base64( $param{Content}, '' ); $content =~ s!(.{1,64})!$1\n!g; my $headers = join '', map { "$_->[0]: $_->[1]\n" } @{ $param{Headers} }; $headers .= "\n" if $headers; "$head\n$headers$content$tail\n"; } use vars qw( %CTYPES ); %CTYPES = ( 'DES-CBC' => {c => 'Crypt::DES', ks=>8, bs=>8, }, 'DES-EDE3-CBC' => {c => 'Crypt::DES_EDE3', ks=>24, bs=>8, }, 'AES-128-CBC' => {c => 'Crypt::Rijndael', ks=>16, bs=>16, }, 'AES-192-CBC' => {c => 'Crypt::Rijndael', ks=>24, bs=>16, }, 'AES-256-CBC' => {c => 'Crypt::Rijndael', ks=>32, bs=>16, }, 'CAMELLIA-128-CBC' => {c => 'Crypt::Camellia', ks=>16, bs=>16, }, 'CAMELLIA-192-CBC' => {c => 'Crypt::Camellia', ks=>24, bs=>16, }, 'CAMELLIA-256-CBC' => {c => 'Crypt::Camellia', ks=>32, bs=>16, }, 'IDEA-CBC' => {c => 'Crypt::IDEA', ks=>16, bs=>8, }, 'SEED-CBC' => {c => 'Crypt::SEED', ks=>16, bs=>16, }, ); #### cipher module support and configuration sub list_ciphers { return wantarray ? sort keys %CTYPES : join(':', sort keys %CTYPES); } sub list_cipher_modules { # expect a cipher name, if found, return the module name used for encryption/decryption my $pem = ref($_[0]) || $_[0] eq __PACKAGE__ ? shift : ''; if (defined $_[0]) { my $cn = has_cipher(shift) || return undef; return $CTYPES{$cn}->{c}; } return wantarray ? map { $CTYPES{$_}->{c} } sort keys %CTYPES : join(':', map { $CTYPES{$_}->{c} } sort keys %CTYPES); } sub has_cipher { # expect a cipher name, return the cipher name if found my $pem = ref($_[0]) || $_[0] eq __PACKAGE__ ? shift : ''; my $cn = uc(+shift); return $cn if exists $CTYPES{$cn} && exists $CTYPES{$cn}->{c}; # try to figure out what cipher is meant in an overkill fashion $cn =~ s/(DES.*3|3DES|EDE)|(DES)|([a-zA-Z]+)(?:-?(\d+)(?:-?(\w+))?)/ if ($1) { 'DES-EDE3-CBC' } elsif ($2) { 'DES-CBC' } else { $3.($4 ? "-".$4 : "").($5 ? "-$5" : "") } /e; my @c = sort grep { $_ =~ m/$cn/ } keys %CTYPES; # return undef unless @c; $c[0]; } sub has_cipher_module { my $pem = ref($_[0]) || $_[0] eq __PACKAGE__ ? shift : ''; if (my $cn = has_cipher($_[0])) { eval "use $CTYPES{$cn}->{c};"; if ($@) { undef $@; return undef; } return $CTYPES{$cn}->{c}; } } sub set_cipher_module { my $pem = ref($_[0]) || $_[0] eq __PACKAGE__ ? shift : ''; # cipher name, cipher module name, replace all my ($cn,$cm,$all) = @_; $all = 1 unless defined $all; # when setting ciphers, must use exact name if (exists $CTYPES{$cn}) { eval "use $cm ;"; if ($@) { undef $@; return undef; } if ($all && exists $CTYPES{$cn}->{c}) { my $old_cm = $CTYPES{$cn}->{c}; foreach my $def (values %CTYPES) { $def->{c} = $cm if $def->{c} eq $old_cm; } } else { $CTYPES{$cn}->{c} = $cm; } return $cm; } return undef; } #### cipher functions sub decrypt { my $pem = shift; my %param = @_; my $passphrase = $param{Password} || ""; my ($ctype, $iv) = split /,/, $param{Info}; my $cmod = $CTYPES{$ctype} or return $pem->error("Unrecognized cipher: '$ctype'"); $iv = pack "H*", $iv; eval "use $cmod->{c}; 1;" || croak "Failed loading cipher module '$cmod->{c}'"; my $key = Convert::PEM::CBC::bytes_to_key($passphrase,$iv,\&md5,$cmod->{ks}); my $cm = $cmod->{c}; $cm =~ s/^Crypt::(?=IDEA$)//; # fix IDEA my $cbc = Convert::PEM::CBC->new( Cipher => $cm->new($key), IV => $iv ); my $buf = $cbc->decrypt($param{Ciphertext}) or return $pem->error("Decryption failed: " . $cbc->errstr); $buf; } sub encrypt { my $pem = shift; my %param = @_; $param{Password} or return $param{Plaintext}; $param{Cipher} = $DefaultCipher if !$param{Cipher}; my $ctype = $pem->has_cipher( $param{Cipher} ); my $cmod = $CTYPES{$ctype} or return $pem->error("Unrecognized cipher: '$ctype'"); eval "use $cmod->{c}; 1;" || croak "Error loading cypher module '$cmod->{c}'"; ## allow custom IV for encryption my $iv = $pem->_getiv(%param, bs => $cmod->{bs}) or return; my $key = Convert::PEM::CBC::bytes_to_key( $param{Password}, $iv, \&md5, $cmod->{ks} ); my $cm = $cmod->{c}; $cm =~ s/^Crypt::(?=IDEA$)//; # fix IDEA my $cbc = Convert::PEM::CBC->new( IV => $iv, Cipher => $cm->new($key) ); $iv = uc join '', unpack "H*", $cbc->iv; my $buf = $cbc->encrypt($param{Plaintext}) or return $pem->error("Encryption failed: " . $cbc->errstr); ($buf, "$ctype,$iv"); } sub _getiv { my $pem = shift; my %p = @_; my $iv; if (exists $p{IV}) { if ($p{IV} =~ m/^[a-fA-F\d]+$/) { $iv = pack("H*",$p{IV}); return length($iv) == $p{bs} ? $iv : $pem->error("Provided IV length is invalid"); } else { return $pem->error("Provided IV must be in hex format"); } } $iv = random_bytes($p{bs}); croak "Internal error: unexpected IV length" if length($iv) != $p{bs}; $iv; } 1; __END__ =head1 NAME Convert::PEM - Read/write encrypted ASN.1 PEM files =head1 SYNOPSIS use Convert::PEM; my $pem = Convert::PEM->new( Name => "DSA PRIVATE KEY", Macro => "DSAPrivateKey", ASN => qq( DSAPrivateKey SEQUENCE { version INTEGER, p INTEGER, q INTEGER, g INTEGER, pub_key INTEGER, priv_key INTEGER } )); my $keyfile = 'private-key.pem'; my $pwd = 'foobar'; my $pkey = $pem->read( Filename => $keyfile, Password => $pwd ); $pem->write( Content => $pkey, Password => $pwd, Filename => $keyfile ); =head1 DESCRIPTION I reads and writes PEM files containing ASN.1-encoded objects. The files can optionally be encrypted using a symmetric cipher algorithm, such as 3DES. An unencrypted PEM file might look something like this: -----BEGIN DH PARAMETERS----- MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM= -----END DH PARAMETERS----- The string beginning C is the Base64-encoded, ASN.1-encoded "object." An encrypted file would have headers describing the type of encryption used, and the initialization vector: -----BEGIN DH PARAMETERS----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,C814158661DC1449 AFAZFbnQNrGjZJ/ZemdVSoZa3HWujxZuvBHzHNoesxeyqqidFvnydA== -----END DH PARAMETERS----- The two headers (C and C) indicate information about the type of encryption used, and the string starting with C is the Base64-encoded, encrypted, ASN.1-encoded contents of this "object." The initialization vector (C) is chosen randomly. =head1 USAGE =head2 $pem = Convert::PEM->new( %arg ) Constructs a new I object designed to read/write an object of a specific type (given in I<%arg>, see below). Returns the new object on success, C on failure (see I for details). I<%arg> can contain: =over 4 =item * Name The name of the object; when decoding a PEM-encoded stream, the name in the encoding will be checked against the value of I. Similarly, when encoding an object, the value of I will be used as the name of the object in the PEM-encoded content. For example, given the string C, the output from I will start with a header like: -----BEGIN FOO BAR----- I is a required argument. =item * ASN An ASN.1 description of the content to be either encoded or decoded. I is an optional argument. =item * Macro If your ASN.1 description (in the I parameter) includes more than one ASN.1 macro definition, you will want to use the I parameter to specify which definition to use when encoding/decoding objects. For example, if your ASN.1 description looks like this: Foo ::= SEQUENCE { x INTEGER, bar Bar } Bar ::= INTEGER If you want to encode/decode a C object, you will need to tell I to use the C macro definition by using the I parameter and setting the value to C. I is an optional argument when an ASN.1 description is provided. =item * InForm Specify what type of file to expect when using the I method. Value may be either B or B. Default is "PEM". If "DER" is specified, encryption options are ignored when using the I method and file is read as an unencrypted blob. This option does not affect the I behavior. I is an optional argument. =item * OutForm Specify what type of file the I method should output. Value may be either B or B. Default is "PEM". If "DER" is specified, encryption options are ignored when using the I method and the file is written as an uncrypted blob. This option does not affect the I behavior. I is an optional argument. =back =head2 $obj = $pem->decode(%args) Decodes, and, optionally, decrypts a PEM file, returning the object as decoded by I. The difference between this method and I is that I reads the contents of a PEM file on disk; this method expects you to pass the PEM contents as an argument. If an error occurs while reading the file or decrypting/decoding the contents, the function returns I, and you should check the error message using the I method (below). I<%args> can contain: =over 4 =item * Content The PEM contents. =item * Password The password with which the file contents were encrypted. If the file is encrypted, this is a mandatory argument (well, it's not strictly mandatory, but decryption isn't going to work without it). Otherwise it's not necessary. =back =head2 $blob = $pem->encode(%args) Constructs the contents for the PEM file from an object: ASN.1-encodes the object, optionally encrypts those contents. Returns I on failure (encryption failure, file-writing failure, etc.); in this case you should check the error message using the I method (below). On success returns the constructed PEM string. I<%args> can contain: =over 4 =item * Content This method requires either Content or DER. An error will be generated if one of these arguments are not present. A hash reference that will be passed to I, and which should correspond to the ASN.1 description you gave to the I method. The hash reference should have the exact same format as that returned from the I method. This is required unless DER is specified. =item * DER A string containing actual binary of the contents to be encoded. This bypasses ASN.1 encoding. May be used in lieu of Content. If specified, will override Content. =item * Password A password used to encrypt the contents of the PEM file. This is an optional argument; if not provided the contents will be unencrypted. =item * Cipher The Cipher to use if a password is provided. This is an optional argument; if not provided, the default of B will be used or the cipher configured is B<$Convert::PEM::DefaultCipher>. See below for a list of supported ciphers. =back =head2 $obj = $pem->read(%args) Reads, decodes, and, optionally, decrypts a PEM file, returning the object as decoded by I (or binary blob if ASN.1 description was not provided). This is implemented as a wrapper around I, with the bonus of reading the PEM file from disk for you. If an error occurs while reading the file or decrypting/decoding the contents, the function returns I, and you should check the error message using the I method (below). In addition to the arguments that can be passed to the I method (minus the I argument), I<%args> can contain: =over 4 =item * Filename The location of the PEM file that you wish to read. =item * InForm Specify what file type to read. Description can be found under I method. If specified, will override InForm provided in I method. =back =head2 $pem->write(%args) Constructs the contents for the PEM file from an object: ASN.1-encodes the object, optionally encrypts those contents; then writes the file to disk. This is implemented as a wrapper around I, with the bonus of writing the file to disk for you. Returns I on failure (encryption failure, file-writing failure, etc.); in this case you should check the error message using the I method (below). On success returns the constructed PEM string. In addition to the arguments for I, I<%args> can contain: =over 4 =item * Filename The location on disk where you'd like the PEM file written. =item * OutForm Specify format to write out. Description can be found under I method. If specified, will override OutForm provided in I method. =back =head2 $pem->from_der(%args) Method used internally, but may be accessed directly decode an ASN.1 string into a perl structure object. If the Convert::PEM object has no ASN.1 definition, this method has no effect. =over 4 =item * DER Binary string to convert to an object. This option is required. =item * Macro If the object has an ASN definition, a Macro may be specified. If specified, it will override the object's Macro if one exists. Macro is an optional argument. =back =head2 $pem->to_der(%args) Method used internally, but may be accessed directly to encode Content into binary data. If the Convert::PEM object has no ASN.1 definition, this method has no effect. =over 4 =item * Content An object to be ASN.1 encoded to a binary string. =item * Macro If the object has an ASN definition, a Macro may be specified. If specified, it will override the object's Macro if one exists. Macro is an optional argument. =back =head2 $pem->errstr Returns the value of the last error that occurred. This should only be considered meaningful when you've received I from one of the functions above; in all other cases its relevance is undefined. =head2 $pem->asn Returns the I object used internally to decode and encode ASN.1 representations. This is useful when you wish to interact directly with that object; for example, if you need to call I on that object to set the type of big-integer class to be used when decoding/encoding big integers: $pem->asn->configure( decode => { bigint => 'Math::Pari' }, encode => { bigint => 'Math::Pari' } ); =head2 $pem->inform Retruns the I configured for the object. =head2 $pem->outform Retruns the I configured for the object. =head2 $pem->cipher Returns the I configured for the object. =head2 $pem->name Returns the PEM I of the object. =head1 CONFIGURATION To support any encryption/decryption, the appropriate cipher module needs to be installed. Some settings may be viewed or configured through variables or methods. Configuration settings are global to the package. If a setting is changed, it affects all Convert::PEM objects. =head2 $Convert::PEM::DefaultCipher I $OBJ->DefaultCipher(I<[NEW_CIPHER]>) Used to configure a default cipher when writing to the disk. When using the method form C< $OBJ->DefaultCipher([NEW_CIPHER]) >, if NEW_CIPHER is not specified, will return the current setting. If the specified cipher is not recognized/valid, an error will be raised. To list supported ciphers, use C. Here is a list of supported Ciphers: =over 4 =item * DES-CBC =item * DES-EDE3-CBC =item * AES-128-CBC =item * AES-192-CBC =item * AES-256-CBC =item * CAMELLIA-128-CBC =item * CAMELLIA-192-CBC =item * CAMELLIA-256-CBC =item * IDEA-CBC =item * SEED-CBC =back =head2 Convert::PEM->has_cipher(I<$cipher_name>) Will see if the cipher is supported and is configured with an encryption module. =head2 Convert::PEM->has_cipher_module(I<$cipher_name>) Will see if the cipher is supported and if the configured encryption module is usable. If it is not usable, will return C. If it is usable, will return the name of the cipher module. =head2 Convert::PEM->set_cipher_module($cipher,$module[,$all]) This function/method is used to specify a module name for a supported cipher. It accepts 2 or 3 arguments. Convert::PEM->set_cipher_module(, [,0]) or $OBJ->set_cipher_module(, [,0]) =over 4 =item C A supported cipher name. Use Convert::PEM::list_ciphers() to retrieve a list of supported ciphers. =item C A cipher module. The module must support the following methods: $cipher_object = Cipher->new($key) $cipher_object->encrypt($plaintext) $cipher_object->decrypt($ciphertext) $cipher_object->blocksize() =item C An optional boolean argument. If true will replace the modules for all supported ciphers matching the cipher being set. Default is true. If setting a cipher, only set this to false if it is desired to use a separate cipher for different key lengths of the same algorithm. =back =head2 Convert::PEM->list_cipher_modules([$cipher_name]) If a I is provided, will return the module configured for the matching cipher name or C if cipher is not supported. If I is not provided, will return a list of modules names configured as an array in array context or as a colon separated list in scalar context. Here is a list of the cipher modules used by default. =over 4 =item * L =item * L =item * L - C =item * L - C =item * Crypt::L =item * L =back =head1 ERROR HANDLING If an error occurs in any of the above methods, the method will return C. You should then call the method I to determine the source of the error: $pem->errstr In the case that you do not yet have a I object (that is, if an error occurs while creating a I object), the error can be obtained as a class method: Convert::PEM->errstr For example, if you try to decode an encrypted object, and you do not give a passphrase to decrypt the object: my $obj = $pem->read( Filename => "encrypted.pem" ) or die "Decryption failed: ", $pem->errstr; =head1 LICENSE Convert::PEM is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR & COPYRIGHTS Except where otherwise noted, Convert::PEM is Copyright Benjamin Trott, cpan@stupidfool.org. All rights reserved. =cut 20-opt-ciphers.t100644001750001750 431614723477042 15444 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; plan tests => 18; my $expected = join ':', sort qw(DES-CBC DES-EDE3-CBC AES-128-CBC AES-192-CBC AES-256-CBC CAMELLIA-128-CBC CAMELLIA-192-CBC CAMELLIA-256-CBC IDEA-CBC SEED-CBC); my @ciphers; my $ciphers; # object oriented ok (Convert::PEM->has_cipher('idea') eq 'IDEA-CBC', "IDEA-CBC cipher recognized via OO interface"); ok (Convert::PEM->has_cipher('aes') eq 'AES-128-CBC', "AES-128-CBC cipher recognized via OO interface"); ok (Convert::PEM->has_cipher('aes128') eq 'AES-128-CBC', "AES-128-CBC cipher recognized via OO interface"); ok (Convert::PEM->has_cipher('aes192') eq 'AES-192-CBC', "AES-192-CBC cipher recognized via OO interface"); ok (Convert::PEM->has_cipher('aes256') eq 'AES-256-CBC', "AES-256-CBC cipher recognized via OO interface"); ok (Convert::PEM->has_cipher('des') eq 'DES-CBC', "DES-CBC cipher recognized via OO interface"); ok (Convert::PEM->has_cipher('3des') eq 'DES-EDE3-CBC',"DES-EDE3-CBC cipher recognized via OO interface"); lives_ok { @ciphers = Convert::PEM->list_ciphers } "retrieve list of supported ciphers as array"; ok @ciphers >= 1, "list of ciphers contains one or more items"; lives_ok { $ciphers = Convert::PEM->list_ciphers } "retrieve list of supported ciphers as scalar"; ok $ciphers eq $expected, "list of ciphers contains items"; note("ciphers: $ciphers"); note("retrieved ciphers:".$/." ".join("$/ ",@ciphers)); # directly access functions ok (Convert::PEM::has_cipher('idea') eq 'IDEA-CBC', "IDEA-CBC cipher recognized via functional interface"); ok (Convert::PEM::has_cipher('aes') eq 'AES-128-CBC', "AES-128-CBC cipher recognized via functional interface"); ok (Convert::PEM::has_cipher('aes128') eq 'AES-128-CBC', "AES-128-CBC cipher recognized via functional interface"); ok (Convert::PEM::has_cipher('aes192') eq 'AES-192-CBC', "AES-192-CBC cipher recognized via functional interface"); ok (Convert::PEM::has_cipher('aes256') eq 'AES-256-CBC', "AES-256-CBC cipher recognized via functional interface"); ok (Convert::PEM::has_cipher('des') eq 'DES-CBC', "DES-CBC cipher recognized via functional interface"); ok (Convert::PEM::has_cipher('3des') eq 'DES-EDE3-CBC', "DES-EDE3-CBC cipher recognized via functional interface"); 31-opt-asn-form.t100644001750001750 1202214723477042 15544 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; use Digest::MD5 qw(md5 md5_hex); sub undefl { @_[0..$#_]=(); } my $pem_in = './t/data/rsakey.pem'; my $der_in = './t/data/rsakey.der'; unless (-e $pem_in && -e $der_in) { plan skip_all => "because the necessary test files do not exist"; exit; } my $pem_out = './t/data/rsakey.t.pem'; my $der_out = './t/data/rsakey.t.der'; my $md5hash = '45f605c6186eaea0730958b0e3da52e4'; require "./t/func.pl"; plan tests => 41; my $pem = get_rsa(); isa_ok $pem, "Convert::PEM"; ok $pem->inform() eq "PEM", "Verify correct InForm of PEM"; ok $pem->outform() eq "PEM", "Verify correct OutForm of PEM"; my $derout = get_rsa( OutForm => 'DER' ); isa_ok $derout, "Convert::PEM"; ok $derout->inform() eq "PEM", "Verify correct InForm of PEM"; ok $derout->outform() eq "DER", "Verify correct OutForm of DER"; my $derin = get_rsa( InForm => 'DER' ); isa_ok $derin, "Convert::PEM"; ok $derin->inform() eq "DER", "Verify correct InForm of DER"; ok $derin->outform() eq "PEM", "Verify correct OutForm of PEM"; my $der = get_rsa( InForm => 'DER', OutForm => 'DER' ); isa_ok $der, "Convert::PEM"; ok $der->inform() eq "DER", "Verify correct InForm of DER"; ok $der->outform() eq "DER", "Verify correct OutForm of DER"; my($dec,$dec2,$bin,$bin2,$fh,$asn); $asn=$pem->asn; #### read/write PEM lives_ok { $dec = $pem->read( Filename => $pem_in ) } "read PEM file with ASN decoding"; $bin = $asn->encode($dec); ok md5_hex( $bin ) eq $md5hash, "verify PEM file hash. expecting: \"$md5hash\", actual: \"".md5_hex($bin)."\""; lives_ok { $pem->write( Filename => $pem_out, Content => $dec ) } "write PEM file with ASN encoding"; ok !$pem->error(), "Check for errors after writing PEM file: ".($pem->error() ? ": ".$pem->error() : ""); lives_ok { $dec2 = $pem->read( Filename => $pem_out ) } "re-read written PEM file with ASN decoding"; ok !$pem->error(), "Check for errors after re-reading PEM file".($pem->error() ? ": ".$pem->error() : ""); $bin2 = $asn->encode($dec2); ok defined $bin && $bin eq $bin2, "Compare original read to what was written"; unlink $pem_out; undefl $dec,$dec2,$bin,$bin2; #### read PEM/write DER lives_ok { $dec = $derout->read( Filename => $pem_in ) } "read PEM file with ASN decoding and OutForm as DER"; $bin = $asn->encode($dec); ok md5_hex( $bin ) eq $md5hash, "verify PEM file hash. expecting: \"$md5hash\", actual: \"".md5_hex($bin)."\""; lives_ok { $derout->write( Filename => $der_out, Content => $dec ) } "write DER file with ASN encoding"; ok !$derout->error(), "Check for errors after writing DER file".($derout->error() ? ": ".$derout->error() : ""); lives_ok { $dec2 = $derin->read( Filename => $der_out ) } "re-read written DER file with ASN decoding"; ok !$derin->error(), "Check for errors in \$derin after re-reading DER file written by \$derout".($derin->error() ? ": ".$derin->error() : ""); $bin2 = $asn->encode($dec2); is md5_hex( $bin2 ), $md5hash, "verify written DER file hash. expecting: \"$md5hash\", actual: \"".md5_hex($bin2)."\""; ok defined $bin && $bin eq $bin2, "Compare original read to what was written and re-read"; ok open($fh,'<',$der_out), "Use open to Open the der_out file and compare the hash just to double check"; binmode($fh); read($fh,$bin2,-s $der_out); close($fh); is md5_hex( $bin2 ), $md5hash, "verify written DER file hash from direct open. expecting: \"$md5hash\", actual: \"".md5_hex($bin2)."\""; #### write with a password even though it should have no effect lives_ok { $derout->write( Filename => $der_out, Content => $dec, Password => 'test' ) } "write DER file with ASN encoding and provide a password"; ok !$derout->error(), "Check for errors after writing DER file".($derout->error() ? ": ".$derout->error() : ""); lives_ok { $dec2 = $derin->read( Filename => $der_out ) } "re-read written DER file with ASN decoding and password"; ok !$derin->error(), "Check for errors in \$derin after re-reading DER file written by \$derout while providing a password".($derin->error() ? ": ".$derin->error() : ""); $bin2 = $asn->encode($dec2); is md5_hex( $bin2 ), $md5hash, "verify written DER file hash. expecting: \"$md5hash\", actual: \"".md5_hex($bin2)."\""; unlink $der_out; undefl $bin,$bin2,$dec,$dec2; #### read DER/write PEM lives_ok { $dec = $derin->read( Filename => $der_in ) } "read DER file with ASN decoding and OutForm as PEM"; $bin = $asn->encode($dec); ok md5_hex( $bin ) eq $md5hash, "verify DER file hash. expecting: \"$md5hash\", actual: \"".md5_hex($bin)."\""; lives_ok { $derin->write( Filename => $pem_out, Content => $dec ) } "write PEM file with ASN encoding"; ok !$derin->error(), "Check for errors after writing PEM file".($derin->error() ? ": ".$derin->error() : ""); lives_ok { $dec2 = $pem->read( Filename => $pem_out ) } "re-read written DER file with ASN decoding"; ok !$pem->error(), "Check for errors in \$pem after re-reading DER file written by \$derin".($pem->error() ? ": ".$pem->error() : ""); $bin2 = $asn->encode($dec2); ok defined $bin && $bin eq $bin2, "Compare original read to what was written and re-read"; unlink $pem_out; undefl $bin,$bin2,$dec,$dec2; 32-noasn-encode.t100644001750001750 405714723477042 15565 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More tests => 14; use Convert::ASN1; use Convert::PEM; my($str1,$str2) = (pack('H*','3003020104'),pack('H*','300c020a17805cf22a8b3270b48d')); my $desc = qq( TestObject SEQUENCE { int INTEGER } ); #### create object with DER InForm and OutForm to test for proper behavior my $asn = Convert::ASN1->new()->prepare($desc); my $pem = Convert::PEM->new( Name => 'TEST OBJECT', InForm => 'DER', OutForm => 'DER' ); isa_ok $pem, 'Convert::PEM'; my($obj, $obj2, $blob); $blob = $pem->encode( DER => $str1, ); ok $blob, 'encode gave us something'; note($blob); $obj2 = $pem->decode( Content => $blob, ); is $obj2, $str1, 'input matches output'; $blob = $pem->encode( DER => $str1, Password => 'xx', IV => '3EC5575B0B86C70E' ); ok !$pem->error(), 'no error after encode with IV'.($pem->error() ? ": ".$pem->error() : ''); note($blob); ok $blob, 'encode gave us something'; $obj2 = $pem->decode( Content => $blob ); ok !defined $obj2, 'decode fails on encrypted input'; like $pem->errstr, qr/^Decryption failed/, 'errstr of "'.$pem->errstr.'" matches decrypt failed'; $obj2 = $pem->decode( Content => $blob, Password => 'xx' ); is $obj2, $str1, 'input matches output'; $blob = $pem->encode( DER => $str2 ); ok $blob, 'encode gave us something'; note($blob); $obj2 = $pem->decode( Content => $blob ); is $obj2, $str2, 'input matches output'; #### optional DER encoding my $pem = Convert::PEM->new( Name => 'TEST OBJECT', ASN => $desc, InForm => 'DER', OutForm => 'DER' ); $obj = $asn->decode($str1); $blob = $pem->encode( Content => $obj ); ok $blob, 'encode Content gave us something'; $obj2 = $pem->decode( Content => $blob, ); is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'encode Content input matches decode Content output'; $blob = $pem->encode( DER => $str1 ); ok $blob, 'encode DER gave us something'; $obj2 = $pem->decode( Content => $blob, ); is $obj->{TestObject}{int}, $obj2->{TestObject}{int}, 'encode Content input matches decode Content output'; 30-opt-noasn-form.t100644001750001750 1174614723477042 16114 0ustar00timtim000000000000Convert-PEM-0.13/tuse strict; use Test::More; use Test::Exception; use Convert::PEM; use Digest::MD5 qw(md5 md5_hex); sub undefl { @_[0..$#_]=(); } my $pem_in = './t/data/rsakey.pem'; my $der_in = './t/data/rsakey.der'; unless (-e $pem_in && -e $der_in) { plan skip_all => "because the necessary test files do not exist"; exit; } my $pem_out = './t/data/rsakey.t.pem'; my $der_out = './t/data/rsakey.t.der'; my $md5hash = '45f605c6186eaea0730958b0e3da52e4'; #### test optional ASN parameters #### test with DER In and Out forms plan tests => 45; note("Using PEM file '$pem_in'"); note("Using DER file '$der_in'"); my $pem = Convert::PEM->new( Name => "RSA PRIVATE KEY", ); isa_ok $pem, "Convert::PEM"; ok $pem->inform() eq "PEM", "Verify correct InForm of PEM"; ok $pem->outform() eq "PEM", "Verify correct OutForm of PEM"; my $derout = Convert::PEM->new( Name => "RSA PRIVATE KEY", OutForm => "DER", ); isa_ok $derout, "Convert::PEM"; ok $derout->inform() eq "PEM", "Verify correct InForm of PEM"; ok $derout->outform() eq "DER", "Verify correct OutForm of DER"; my $derin = Convert::PEM->new( Name => "RSA PRIVATE KEY", InForm => "DER", ); isa_ok $derin, "Convert::PEM"; ok $derin->inform() eq "DER", "Verify correct InForm of DER"; ok $derin->outform() eq "PEM", "Verify correct OutForm of PEM"; my $der = Convert::PEM->new( Name => "RSA PRIVATE KEY", InForm => "DER", OutForm => "DER", ); isa_ok $der, "Convert::PEM"; ok $der->inform() eq "DER", "Verify correct InForm of DER"; ok $der->outform() eq "DER", "Verify correct OutForm of DER"; my($bin,$bin2,$fh); lives_ok { $bin = $pem->read( Filename => $pem_in ) } "read PEM file without ASN decoding"; ok md5_hex($bin) eq $md5hash, "verify PEM file hash"; lives_ok { $pem->write( Filename => $pem_out, Content => $bin ) } "write PEM file without ASN encoding"; ok !$pem->error(), "Check for errors after writing PEM file: ".($pem->error() ? ": ".$pem->error() : ""); lives_ok { $bin2 = $pem->read( Filename => $pem_out ) } "re-read written PEM file without ASN decoding"; ok !$pem->error(), "Check for errors after re-reading PEM file".($pem->error() ? ": ".$pem->error() : ""); ok $bin eq $bin2, "Compare original read to what was written"; unlink $pem_out; undefl $bin, $bin2; lives_ok { $bin = $derout->read( Filename => $pem_in ) } "read PEM file without ASN decoding and with OutForm set to DER"; ok md5_hex($bin) eq $md5hash, "verify PEM file hash"; lives_ok { $derout->write( Filename => $der_out, Content => $bin ) } "write DER file without ASN encoding"; ok !$derout->error(), "Check for errors after writing PEM file: ".($derout->error() ? ": ".$derout->error() : ""); ok open($fh,'<',$der_out), "Use open to Open file written"; binmode($fh); ok read($fh,$bin2,-s $der_out), "Read file contents into memory"; close($fh); is $bin, $bin2, "Compare original contents ot what was written with \$derout and read back into memory"; undef $bin2; lives_ok { $bin2 = $derin->read( Filename => $der_out ) } "re-read written DER file with \$derin without ASN decoding"; ok !$derin->error(), "Check for errors after re-reading PEM file".($derin->error() ? ": ".$derin->error() : ""); is $bin, $bin2, "Compare original contents to what was written with \$derout and re-read with \$derin"; unlink $der_out; undefl $bin,$bin2; lives_ok { $bin = $derin->read( Filename => $der_in ) } "read DER file without ASN decoding"; ok !$derin->error(), "Check for errors after reading in DER file".($derin->error() ? ": ".$derin->error() : ""); is md5_hex($bin), $md5hash, "verify DER file hash is \"$md5hash\": actual - \"".md5_hex($bin)."\""; lives_ok { $derin->write( Filename => $pem_out, Content => $bin ) } "write PEM file without ASN encoding"; ok !$derin->error(), "Check for errors after writing PEM file: ".($derin->error() ? ": ".$derin->error() : ""); lives_ok { $bin2 = $pem->read( Filename => $pem_out ) } "re-read PEM file written by \$derin with \$pem without ASN decoding"; ok !$derin->error(), "Check for errors after re-reading PEM file".($derin->error() ? ": ".$derin->error() : ""); is $bin, $bin2, "Compare original contents to what was written with \$derout and re-read with \$derin"; unlink $pem_out; undefl $bin,$bin2; lives_ok { $bin = $der->read( Filename => $der_in ) } "read DER file without ASN decoding and with OutForm set to DER"; ok !$der->error(), "Check for errors after reading in DER file: ".$der->error(); is md5_hex($bin), $md5hash, "verify DER file hash is \"$md5hash\": actual - \"".md5_hex($bin)."\""; lives_ok { $der->write( Filename => $der_out, Content => $bin ) } "write DER file without ASN encoding"; ok !$der->error(), "Check for errors after writing DER file: ".($der->error() ? ": ".$der->error() : ""); lives_ok { $bin2 = $der->read( Filename => $der_out ) } "re-read DER file written without ASN decoding"; ok !$der->error(), "Check for errors after re-reading DER file".($der->error() ? ": ".$der->error() : ""); is $bin, $bin2, "Compare original contents to what was written with \$der and re-read with \$der"; unlink $der_out; undefl $bin,$bin2; rsakey-bad.pem100644001750001750 135714723477042 16243 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,D7E8A1186D902144 7qseM7QsE1jdjVM2bjmwaJTjOPGA19/iEAQDHgXLLKwEzHcj1Y704aw7qxWgavy7 SBN8zE2OMHQDZmugfQocO1bGqeZihmlWIZUnk+PUgiyJDKZP4gMq+7y3hfvOi+42 uhJ6EvJe/LrRkbfQX1lb4obZ70VC3xZM95fV4M7395p5mi6Gk3YBjtv5vBaRZvLE PqT6xSUuMHeDQr3E8IUY7pre2cUCR4EEE7vedXcj7NWhLHP/iD3Zn+wouwyPk1Nm YSt5r2b8oMprHLEUg5wMxtjhLizrAxoRdwmUUW2tygNcZcDakzWIvggq4wHYpS2h +1am6NSo4T9o19pklUWUOspOSu4SOEdb6YcyNCDtPea/NwuFswX3I1nKg6NeEalm 7+jk9+vherWz4njGeP4CV+wSLwYQqvD4rZkXiAEZaxdcdscH6wuaDN3Qtw5lKr3/ VTqkvgyc1m9EqFeTSQldKLYZn6VHWZ61UzLWTDEp+KgISrF8jf8ol3x9gIoBrUkg dbvQuKyCrOHqvmXRqPVYm4B63Bzp/PRx6KrWPjOiCJRzMO57wOewza42wJTJTAhL UwsDB5sho3f/AkUKPu8ZL27ZtoVEZ6UUax+5iDWJZZw= -----END RSA PRIVATE KEY----- rsakey-des.pem100644001750001750 135714723477042 16270 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,8EE0256BEB79B13C n4bmBQzIr2fOvsBl3NkeGNPfj28OojQV8lkGX0LbxIgfwUg85h+juiUEkkXxbQ1C bsoJ7nyHU+Fg+WHhnpWZcCg7Xkh8SZJegRaS17DqSLadkKh/2/18S2aAwM4ZaWlm wC6d50Qm7+ZTsIzyk3gsmXTm+2cqNyRcvU/IKZg5qu0NcuBeOVUUFANHxIvBFqUK ltoFPk+B/5xatYEaX73CYgdKHPJNhW8I2imedHR2iHWewebgmYX5dpVSEiP3tHvD MSaNQeasnD0bLmjYd5SXkD8CtGeUYp9ytM7EWgAci3kAWAUdVniA+yCbUywLfBtG fx+76bSX7LbG9AGrDMoO5rDVlLrXC6cxwERqJ2Z/HG5CDamEoPTjrEeteUe4+6my swnwtOJsQgstMWQqPpnYs3XPBz2PLAPCnB4L8FiAzShlekYvMHiCrvhhKZFnRcJU OZFkAeQA0f59+Rc2WcMMGMRWW5p1nvSTVFqbvJHXaolCIJP+yaaawo0yfHIW1QW7 v5mHJFxqMQ6w02eAUrb33W2YtkErAD0idFk9gwGMa/mb+TbBcF7CnBHI9U//Cfd2 uSBwpqtpv/XOFlQQwko7Xuq7Xg5AunD0RdUdUOwe1BM= -----END RSA PRIVATE KEY----- PEM000755001750001750 014723477042 15003 5ustar00timtim000000000000Convert-PEM-0.13/lib/ConvertCBC.pm100644001750001750 1606114723477042 16114 0ustar00timtim000000000000Convert-PEM-0.13/lib/Convert/PEMpackage Convert::PEM::CBC; use strict; our $VERSION = '0.13'; # VERSION use Carp qw( croak ); use Digest::MD5 qw( md5 ); use base qw( Class::ErrorHandler ); use Crypt::PRNG qw( random_bytes ); sub new { my $class = shift; my $cbc = bless { }, $class; $cbc->init(@_); } sub init { my $cbc = shift; my %param = @_; $cbc->{iv} = exists $param{IV} ? $param{IV} : random_bytes(8); croak "init: Cipher is required" unless my $cipher = $param{Cipher}; if (ref($cipher)) { $cbc->{cipher} = $cipher; } else { eval "use $cipher;"; croak "Loading '$cipher' failed: $@" if $@; my $key = $param{Key}; if (!$key && exists $param{Passphrase}) { $key = bytes_to_key($param{Passphrase}, $cbc->{iv}, \&md5, $cipher->keysize); } croak "init: either Key or Passphrase required" unless $key; $cbc->{cipher} = $cipher->new($key); } $cbc; } sub iv { $_[0]->{iv} } sub encrypt { my $cbc = shift; my ($text) = @_; my $cipher = $cbc->{cipher}; ## special stuff for the old SEED package my $seed = ref($cipher) eq "Crypt::SEED"; my $bs = ($seed ? 16 : $cipher->blocksize()) or return $cbc->error("This cipher does not support the blocksize method"); my @blocks = $text =~ /(.{1,$bs})/gs; my $last = pop @blocks if length($blocks[-1]) < $bs; my $iv = $cbc->{iv}; my $buf = ''; for my $block (@blocks) { $buf .= $iv = $seed ? $cipher->encrypt($iv ^ $block,0) : $cipher->encrypt($iv ^ $block); } $last = pack("C*", ($bs) x $bs) unless $last && length $last; if (length $last) { $last .= pack("C*", ($bs-length($last)) x ($bs-length($last))) if length($last) < $bs; $buf .= $iv = $seed ? $cipher->encrypt($iv ^ $last,0) : $cipher->encrypt($iv ^ $last); } $cbc->{iv} = $iv; $buf; } sub decrypt { my $cbc = shift; my ($text) = @_; my $cipher = $cbc->{cipher}; ## special stuff for the old SEED package my $seed = ref($cipher) eq "Crypt::SEED"; my $bs = ($seed ? 16 : $cipher->blocksize()) or return $cbc->error("This cipher does not support the blocksize method"); my @blocks = $text =~ /(.{1,$bs})/gs; my $last = length($blocks[-1]) < $bs ? join '', splice(@blocks, -2) : pop @blocks; my $iv = $cbc->{iv}; my $buf = ''; ## more special stuff for the old SEED package for my $block (@blocks) { $buf .= $iv ^ ($seed ? $cipher->decrypt($block,0) : $cipher->decrypt($block)); $iv = $block; } $last = pack "a$bs", $last; if (length($last)) { my $tmp = $iv ^ ($seed ? $cipher->decrypt($last,0) : $cipher->decrypt($last)); $iv = $last; $last = $tmp; my $cut = ord substr $last, -1; return $cbc->error("Bad key/passphrase") if $cut > $bs; substr($last, -$cut) = ''; $buf .= $last; } $cbc->{iv} = $iv; $buf; } sub bytes_to_key { my ($key, $salt, $md, $ks) = @_; my $ckey = $md->($key . substr($salt,0,8)); while (length($ckey) < $ks) { $ckey .= $md->($ckey, $key, substr($salt,0,8)); } substr $ckey, 0, $ks; } 1; __END__ =head1 NAME Convert::PEM::CBC - Cipher Block Chaining Mode implementation =head1 SYNOPSIS use Convert::PEM::CBC; my $cbc = Convert::PEM::CBC->new( Cipher => 'Crypt::DES_EDE3', Passphrase => 'foo' ); my $plaintext = 'foo bar baz'; $cbc->encrypt($plaintext); =head1 DESCRIPTION I implements the CBC (Cipher Block Chaining) mode for encryption/decryption ciphers; the CBC is designed for compatibility with OpenSSL and may not be compatible with other implementations (such as SSH). =head1 USAGE =head2 $cbc = Convert::PEM::CBC->new(%args) Creates a new I object and initializes it. Returns the new object. I<%args> can contain: =over 4 =item * Cipher Either the name of an encryption cipher class (eg. I), or an object already blessed into such a class. The class must support the I, I, I, and I methods. If the value is a blessed object, it is assumed that the object has already been initialized with a key. This argument is mandatory. =item * Passphrase A passphrase to encrypt/decrypt the content. This is different in implementation from a key (I), because it is assumed that a passphrase comes directly from a user, and must be munged into the correct form for a key. This "munging" is done by repeatedly computing an MD5 hash of the passphrase, the IV, and the existing hash, until the generated key is longer than the keysize for the cipher (I). Because of this "munging", this argument can be any length (even an empty string). If you give the I argument an object, this argument is ignored. If the I argument is a cipher class, either this argument or I must be provided. =item * Key A raw key, to be passed directly to the new cipher object. Because this is passed directly to the cipher itself, the length of the key must be equal to or greater than the keysize for the I. As with the I argument, if you give the I argument an already-constructed cipher object, this argument is ignored. If the I argument is a cipher class, either this argument or I must be provided. =item * IV The initialization vector for CBC mode. This argument is optional; if not provided, a random IV will be generated. Obviously, if you're decrypting data, you should provide this argument, because your IV should match the IV used to encrypt the data. =back =head2 $cbc->encrypt($plaintext) Encrypts the plaintext I<$plaintext> using the underlying cipher implementation in CBC mode, and returns the ciphertext. If any errors occur, returns I, and you should check the I method to find out what went wrong. =head2 $cbc->decrypt($ciphertext) Decrypts the ciphertext I<$ciphertext> using the underlying cipher implementation in CBC mode, and returns the plaintext. If any errors occur, returns I, and you should check the I method to find out what went wrong. =head2 $cbc->iv Returns the current initialization vector. One use for this might be to grab the initial value of the IV if it's created randomly (ie. you haven't provided an I argument to I): my $cbc = Convert::PEM::CBC->new( Cipher => $cipher ); my $iv = $cbc->iv; ## Generated randomly in 'new'. I uses this to write the IV to the PEM file when encrypting, so that it can be known when trying to decrypt the file. =head2 $cbc->errstr Returns the value of the last error that occurred. This should only be considered meaningful when you've received I from one of the functions above; in all other cases its relevance is undefined. =head1 AUTHOR & COPYRIGHTS Please see the Convert::PEM manpage for author, copyright, and license information. =cut rsakey-3des.pem100644001750001750 136414723477042 16351 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,4C831C9C0CC1D0E0 wCa15rzWptaFA2X86YIeNJ19O2xQT25ep3pys6Xj471NLRLYhzYySi1NOTzb1K12 AttmROTw2+7EkH0Y/k5IRch4bmkof6U0+6hlTnhH5Tuq72FYGkNjJhGVv+NcqJ/8 frDPOFs4v3qnlwgjma29CIGozXUn5Xd63Oa6/m571keuRe5+9hGRFJYZYXT5os8g eCyaTBKUXUtD2plkQR42yjNvJglhHNKfpizocz9SMVPNkCVpvKnnoT6kirACjpeM ZwsO/br+EYqJ/7pfAdrMqMImjEq+E26ZFlTv6lELPD7wBt/hUi92ngj1R+D1QP6y UmBl2NV2OTE0s0h5mgcx14OgqNqsMh8gbV76TCfFv+vTpNWek1LASiRHCm/dt1gB A202i23BBnYsxNoqaBzxxYz/9fl5w74exzWuqtHfllX46oLptRvFa6Tr5zVFbM1t +nwzSKb/Bh35CzeVtFc268BnbqPsbZ0hlAGZHiKAL/OfLaeX/TvDoX6m2kjVbW61 vo92IyxP4KcliTpTngERcQ0CpJ6enJnbi49AVkDnQdIOZKHGg+VaHzJ5t+pV8JGC muPNV/z4E72cTh9b1xl0qXdI2Dd6QOiwUhnvPPB8oW0= -----END RSA PRIVATE KEY----- rsakey-des3.pem100644001750001750 136414723477042 16351 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,19C06E97767EEB97 B8KT80sBr065/uJS9oF834xClcIRDInUmPKHZ1oQ+n4J/jWAzzn3Q4oSImFD+MVA JsCfOBvGo+nljJYvfUuQlye4JfjVJJfDDahuL7gj+rITAqeGNx+fHoc+7PIfPmwb yWKp1lRXnZHbYJtb+WrL0JXoicwhtpymJ5vwtB0aj+VbiI169ygQfNCpVjKm3UWc cMEDiAfYOc+vcqgTFQ3J4EX4F/ZYtG7NvNZOwWg369glWi/WU9dprzIxlfSC2ybH 3Rsq/+bLkiV7ZlVXxSqy3goaogHqrui3nu4ciQEIhcMJOb2dX4ncIvxF0dT2RqcH Y7+qSabhLFQdZpYLkSm1m7df+1KqxNOpl60ir2icSqD6DxIgO+RAlfkZNHkJ/5dd 6+7GumIEQ5VBlPry/6pm+FvsjVfeP3sgqnDMJgsfgO3+DunyexpT7dqRbD006Mbw MNK8scephQNrXe3PF1YwuDQMC9bSm78ReGMqgNP1H+jQrLwFuBt58aP2Kq4pfE2B L5BWpDPGEc7Mr+NH9YWTvLoKK9h8402vFi3RD6izLUV01LeFsuVqoODN9X70pZJK 9pCj4RJlzuw/X1smDCz7JD0GMQwn425RwWMKzjeianM= -----END RSA PRIVATE KEY----- rsakey-idea.pem100644001750001750 136014723477042 16411 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: IDEA-CBC,D7E8A1186D902144 7qseM7QsE1jdjVM2bjmwaJTjOPGA19/iEAQDHgXLLKwEzHcj1Y704aw7qxWgavy7 SBN8zE2OMHQDZmugfQocO1bGqeZihmlWIZUnk+PUgiyJDKZP4gMq+7y3hfvOi+42 uhJ6EvJe/LrRkbfQX1lb4obZ70VC3xZM95fV4M7395p5mi6Gk3YBjtv5vBaRZvLE PqT6xSUuMHeDQr3E8IUY7pre2cUCR4EEE7vedXcj7NWhLHP/iD3Zn+wouwyPk1Nm YSt5r2b8oMprHLEUg5wMxtjhLizrAxoRdwmUUW2tygNcZcDakzWIvggq4wHYpS2h +1am6NSo4T9o19pklUWUOspOSu4SOEdb6YcyNCDtPea/NwuFswX3I1nKg6NeEalm 7+jk9+vherWz4njGeP4CV+wSLwYQqvD4rZkXiAEZaxdcdscH6wuaDN3Qtw5lKr3/ VTqkvgyc1m9EqFeTSQldKLYZn6VHWZ61UzLWTDEp+KgISrF8jf8ol3x9gIoBrUkg dbvQuKyCrOHqvmXRqPVYm4B63Bzp/PRx6KrWPjOiCJRzMO57wOewza42wJTJTAhL UwsDB5sho3f/AkUKPu8ZL27ZtoVEZ6UUax+5iDWJZZw= -----END RSA PRIVATE KEY----- rsakey-seed.pem100644001750001750 140014723477042 16422 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: SEED-CBC,D3B7CAE28077F556863FD5A5FFFE3B2C xlCHrHmsMXarlKmuPP18VVF2yU0o6xHwwfZwPZ08uA5SXEnGPgjtMuFsFhiAaM80 37eich9MfpFHv3OXimENBjLaprGMJnnsWNWiMiHP5f/ht+408nJmE0JJE1V1JlJn 2Z2410+HUCEoP8g03ukfVfCZ930Fites7B1mNBvJ1eCm2XloI5XLS5pkgF9tYaft jRktLhP7U30abPMjC/fnqvPER+ZknBWn8BUspRnvbEservEFPC6ZzHK5NtKD5f8o iGAnz6qMm6VidNUxG3ocSyubj2UcyPO3LXtCHHlbQ86yPwjdyloMg0A6HmusuvLt esgzJG7/gnY2wYoq4m/zHNwYtVUmiDKgLhnj5kO01AIa4dLLuWgRRdo26cf6zKSc 230IL5tvWx3/8MOP7DRPmZz63OLMbWN/k4jWdhQS6w29Oe4VKpeS0dPt0nTinfOC 7AgIHBhE1bmxpi1fxaVR43tzyZSihc9cjZDtBgq7SPp76Cy7Ewl9PNUgPeR+kNDf UWRRsRvCOpPrwiupdw0IRE13HHdZ+MOmAL+f/VfgrZCH0SRLPL54yJ6bIQpjIl/F U5kz3kY7GY2DTlROHuePAc9YfXNYSXx7c3Zc5kYTzlg= -----END RSA PRIVATE KEY----- rsakey2-des.pem100644001750001750 56514723477042 16332 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,2074A861486C6DDF 0CoTmi2Ryb+KsOkzgXGmW3wQ4nMnYkg587sXCDkFmubxgJIuNB4tLNzn2r2ViOfR 36UOjDYZpfU6EOhi8p34/rLtg5JdTkYkjeR/P7YztG7Bf7Rldd/Jo3BKrSs7AYbB bvQpXq/sSEjm5y33iDiBpseK+enCPLdoXmCiTuSk55XjWES0NVSXhHLwJuXY+IJV XlgbsY+cgl3UEjyuekqSZfjh2Niit7cvet5IH54UBXnkx0kduQQfNw== -----END RSA PRIVATE KEY----- rsakey2-3des.pem100644001750001750 57214723477042 16413 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,A7CD92C133E248D0 xOAOWqcMrLWo2RO5F6hxv1POdf+KOfNDYoyunvA6dtfZdda43HCPe+1T6rFznQMk Dfmp4nfjWCmhwD7afxWkYN+cI9shgbSXarMruJDJDNQHqk31ICzi9hPPGZZVhyMs uesxSE4JLooDZCGaF5lxMY2Figsp+EMTU4CupG67zLR7lpMLIKf/vubglZnRSS1C 6I9VskR5nH0+QXDlYWVVa277PtDEvzWwRRMXwCPMaHSM2usOCNXrpA== -----END RSA PRIVATE KEY----- rsakey2-idea.pem100644001750001750 56614723477042 16462 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: IDEA-CBC,77379817707114F6 E24dXzCfOCywYBZsNDPfFp0TJ3iRH8vjTEdzyVfswiT6XfA9wuRz1J90d1Gs8ab8 eHx8CSgU1udI2VxX14vXjjjcPbk609BEqB2GpAn78fSpNleIxQrx6aKlEX5sX9zq 72e4epWeiL3A/K2HS8eiZF7mmBnBTO5UiVB3xRmBLVnHMK0W84kbI1Qq7r0FbXs7 hYPOOJ4feE4N4uGZr6dQkZB5iU3gjs6R0mSJfHvf02N/3zKnlvR/Tg== -----END RSA PRIVATE KEY----- rsakey2-seed.pem100644001750001750 61614723477042 16474 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: SEED-CBC,53F634A0B42B1DE91A61C2CAFB93BD76 HTk4RQ5DKibim2dZHPbzUe09CGGrgXHiY/BNd/5iVKrH90wkK9rGLvosJ3Nc+1bO w6Rj2f0Lj1gp87hHRT0rsAcuOe8XEGX84qsiXU39pucV6EhOfpcMsr7+5zq0t7ai bMxGJjnlmY9ZvjATPWvhkFqCiYDEScUc0AT2Wx/6LHrxn6PgOxb+JhwHSFz7eSZ5 sEfGrhrzlfZaRUoL84qlFBR4CF4eUt7ukM3STSMRlmTJ0eozF9UmZcDpVVN5IEQa -----END RSA PRIVATE KEY----- rsakey-aes128.pem100644001750001750 140314723477042 16510 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,71282050E523FE25A5BF6ED8E5F6A0DB tS5PQ1lWjjCkhDpeRqYCeFHUQ/l8eRn4mQTnCnDShBDFqRHGCibkeQ9jXa+bpSbb ZXTBVfPkRTFRQSz/ONPIT4FVxnH9MZfysRhsP9I8jmX5CBxJlSubaSSdB2IWZNPo O71v1LLDyHKnvu40gyfmJ0fB4yyE0jknBgTugwAV7aU/Ic9K5C8flX8t3biXc1DR xQWqiFfyOHXIySbUUgNcci0KG7XmngkOLLlKNqEs8r0kXxCnjEYnlR2x0jU+jDlw /6blefiK72ZtrRi26p/FADmP6CBTgRZdDbtvsH45UK3wjo1/5Lia0+KWmmfH7m2v 2dgJr7Cv6nszzccNmMsK+Vvl1Cl3uaT5VBwrA+os1nNFi4LwQlA9GJq1GPLrHSrF fGsLhdF52EulimeC4CcJT5nei6XR79sqT+yiG3LBDjuNZZpW2Ra8bw6K3yblCCfN /zHt7gedEeG0z3zS+sbT5OU2s9mpSqAf25ao/2c7EL+Nxj+HpM6Bda+cwcCgt9bl +T2mJyCzCIeLsaR4JtcMAkHBEFAVOiq1c/cHR1klXN/+Cw5OcFaPIb/Rg2Qm1/u7 uTwkOFCaEHDkf6HHpmsXmoaHN6MCYSuK1UJSa6v8Y58= -----END RSA PRIVATE KEY----- rsakey-aes192.pem100644001750001750 140314723477042 16511 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-192-CBC,134B238662C8F9D2D72484131C111290 /doUnq+ZDfNJwA00Q0iNIGLQadNO4QQ8zrhWZbdlh11YwnBMef3A329Ov+su/V/X dsXPkDaTpXwci1/s7Bh7JlhtKg9RqcoG4LSNB8DO2O6wFkEwZLxsbKIv7cH+wHge WpLG5+ahIf6ABn3WYe908u1onc6O8TUsG/TMy3nonWkNkekTysFnkYDVsxRivOUM Q9ck5qhgWIrPW0wYjmHzTS/r2bgvfjL2GlhZLWbrdtsrhmCwsyXdoGQQ6bHitHg9 Al2BvDmFz8rZvmkt91RWXqQif7jrQfzAlINgwoLd5OrLP4tGYpKJuEH5xAk+5UJi +kk7c9Zseh30Pc3y8Mpyz6pI3102Iy1KgVZJ8CmcQiYhcIZPodoqzToqPdTRda// Ttz4Wydk0xL++dAhTNpabNTJK9vAFpAjLtIvnRKVIlkxTo6SMfoMQRQ3LbNRdbYP F/bGkW3t8E0f0WCBdgnEwHgmkRhpnHdr1Vi+0jEHNmkpUbM+qr5iaMS9zlhEHfrI Gk52Kou2yUCU66HQ9uV2OtuYT/Ked+ZCgMHk7fvyoUfowQ9nhbLrqcpkqvMQbv8o 7PAcZ8GgLtW0dkn7I+5X63w5NopmTpq5EbYW6PFCSq8= -----END RSA PRIVATE KEY----- rsakey-aes256.pem100644001750001750 140314723477042 16512 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-256-CBC,CED5B654760ADEC8060910ACF4509903 JcPcEBiSkhvHhGXQwpeV7vQyc7+xkfGqA6o7OLhCIHkBDKqqkUDqhV18iX5EURz0 aQpqo9cCYRdX7dN50hAKGEjHn+k1uZaBQCtnE23wERRMRUwodoIovwjSxLzTjN8C 4wSrns8u0RD6zbBbl5ILH4inJ9GLQkXiX6pW85ahGIqeDfO4MziVrIU6NmzTNkGV wvF246AJLCfvMoT7hsw95xQRBYk+//S14ZWd1hEMZvmX1ccsWl1Ul9lYsfonFtN7 3efxAZV/P9uSv+UuAjuv5GLIt9Le9011J5TXCyKmGRGT8iQ7cateqask1gmh3G5v /fAhHc1XRklc3Ve4ZdDlRhuVPCtBNkr+rc4Yd6mL0BjoiAwc0HKzUazgPMy/jwmD pQWL/Az4DGzpKGtSYYuiSsMSCaG+IywuRMFwQByKOEuhLBUcApfXuBQPJyDCywOI KxT3vZ3vDUlqyFHwHKNMRbYRnocfMpJw5dxRE5X41GMAp9PrCdoN+T9sy4EAH36B 9sFK6ATX/yQfM2/NDZnouv5OCAbiq+7d/tqtUpnmA1I12aMCptldqBZHDtc1FUlJ kUpWmcaAFSml0W04stSrCGkjcMXey1bc2X2zPB7OyvQ= -----END RSA PRIVATE KEY----- rsakey2-aes128.pem100644001750001750 62114723477042 16553 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,5C170F7438243763B7A2D61771350418 lSLHUdqwvLhdCyyseQvneM7UoHAhrTp8JcmW+MjDIZbkLS6i1XNtwTTCpBjOUWRA teSfCFd0EHOKDNFBcL5uO0u5FjZJnir7FfLYOD1BWzIwVgG7OhCigdkyyC1D4CWP 1eXPOZzpNntYK8Tz+x43xLmokCNQsEYemxZTacBca8P6iVNnkIkQpO7BYua+mDwE YFzISJOhsFMbMCikZIHt+/E/sq3WvQC0tYo1t0h53Z55FJiP579jKcjljp8ZXpk1 -----END RSA PRIVATE KEY----- rsakey2-aes192.pem100644001750001750 62114723477042 16554 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-192-CBC,EE4CD737ABD7392E94361F2A502CAF57 uei8t3E6eUeAJxreYhFrFJc0roexvAUEGcAOYeIGee2cdnnyyXuMcOo02DM36MRs 2YH9juQ2kwH29uKwZ3//JYOoUOSa/cGZTYBjzCKJiP2+rhqOWwKgl5UdPR8YMTHS WNnjFtCJuGaXXKJ6YiN+cQqHlPNUfL8rEKeNjqfaE3smDiKw0PH4R4O44OA3mEBE 1FhTDaB5LmR8gVTnQgyj3LstodDTaEXyix7Sdr6Fe8IqvPqYQcXEm2Uhz8yui5qq -----END RSA PRIVATE KEY----- rsakey2-aes256.pem100644001750001750 62114723477042 16555 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-256-CBC,052CAB1CD95D9E0FA9E21B7A0F2AAA29 3/Bk4BCH+4FwuNklT5eIN9Hd6+RP+LRK+6ZYTz8Sxo0Qgy8A1nlhjTsSnv8tDq1e VVaomB1MU3s5iK88kOv+IEoi1FqEiHHC452Nd6EkLNAG4C6DcnACOuUDYjxFiuUu bqxtH5W2YpojXLtjbz9N/1n7YSKs6182d+oolcfjtgPry0bhbNXNYYFXxRt1l9hJ KsCCMI4dUqI9xuBJbT0EvITEO61gkEF8C5V0WMBnvpDoCOC8YCqCNSzeETe/NgYn -----END RSA PRIVATE KEY----- rsakey-aes128-b.pem100644001750001750 334614723477042 16737 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,098F6BCD4621D373CADE4E832627B4F6 NyBlaSv1xMy/5+ymF9hwL6ofxZYsZRdcFM91aTutpDQEQmrvzInSj+9vASA1Aotn WZSZF+fyh98n1ZuSkykCg8BOuHkZmM38deQB5LFEJKL40qAYkmB1qb/IKRqL/0dm lUwyT6Izz0WLVJ+6gckuGFG97H5sCCszLwbCD7D2fp7ob6TVnFPkAMbvwEQmsBOo +ZIMedGSPrWNw+PLzclxuqS73WvxEY52QsBu0X7BcAf2/vXYUUVWDY83LbkVZODl 3QBfxiQVnlFsj3kIhukTp68F4874iGGJt56t0biodofvFO4AcLmx2IpYbp6Ia2PN NCAvRwh7CjaJWC0ZUpeu2s05z25hrKznmhwcp2cUGoRw9qTX4Qt4+1eZN3XDQzjB F9RfYtzrQV3mb/7i5Hi/CnaQiDHVzYr3S3Zjlb4+iDVy3GmMgFJxNMIwPy8uiPqA p0zQevO35FgOR5Xiw2Mjtxfnc78wc0OLthydQkzuEQhPSOCMiK4Epd/rrhFThJ2n trObhm+Vu7IC+/du1Ezdb5D4j3z/CHj94bIUxSha3XsG2PIpip+mvBAkRPpty9R9 s7T5is4P7rug9acLZogsGl1CNvgRERKEH0Zntpl2UwwH9P5DnFSJq3pyQCNnfHFV 3J21XJEr5tiP/S7SN8rUytwMxJ1c9Xjgvnt/OvptE4Eqed7PMz3tzXLXfbNnk7+7 2317aN2BZ3+G4wxuQOQpc4Cwz5sefbcoD/IQFXDtem8E1YJFkzJVavth+D5ERAWu 0nvFj+AWl6bhgGig1zERBEn4GnptSqXjcs3lqd9Reo/nTS5KG/lrtjS1JxAY9Zkd kEDukfJ//lo+tla+FvJ2VJdYxFPukoXzovpidZkAu5jy5AA3oeuoUAFGwewqFfCD 5EIZQ1TUorJ8pa/OWZpD1K+rKiPev2REkpuXUWfeZyVb2kmZCyttndNcgQuzJNT3 0fLdxkoQ9mvyPOPVGkVsdv6/0z1REazdTl7FJ3NiApclYALlTORtf8fl/6nnW09a LNyII1guwmA3kjPrFpGgIWQnAuYOJdqx4uLcDPwGeyX5jCN3m0TIlIcak+48DIoz rGNI8HcK3S4LPj23QcVr0Gfu48uOjgmsLaXrNpCgrDVulI+Ed8czZR27yFyvzbw3 RVPStddeM75PmfBEw+vv5Fdbx4FXf9Zl7AoLUNhJzaZj4YnvJM8ykFjRepaxTeI5 s3Djon/z//Vov6eU0n/shTPYWSuqReT4MNy36e5Gref/u8RsOcxo0yHv2dMpEjqP paiwDQxKiNbwxag8Q5a6wwi45y2N6vIXeHLeTaaSp3QTDUu13Z//A4EAtvzLHJ7w SmvNoK3I9yrcv2xeLNUdX1HGHbhnZb1GphfcDKpnITZ29dV4F6rmbRLX73/AY7g8 KzUx2Bw/LRKMMjCzGJ5YWXM2VK20PM6FxT7UKf7R8c9QgAhFf1IDt2n3Jdb4fQTw ONgPpqHK768gMMcj0WQLeBmtrJFKMdS2+uWuMEkAHL8o9x2MEvkIy9cf9iGJPqu3 nJG3kEQz2ClHXTpFqXM2Itep80lmOTtMFzugN8ZYnaXsTjqOVJPzXsvYoNfIazPG -----END RSA PRIVATE KEY----- rsakey-camellia128.pem100644001750001750 141014723477042 17505 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: CAMELLIA-128-CBC,3619262B309A496F1B42FBED5381C764 YTq1Wx2lVqHn2Mwl4bseR9YC9hHJfvY4BYRTkKyc06w1yojjP920p93bfe8saIzg KxBcYusvFjTH/jPA2bw6wRSYWjD3ZqfqVWh39QqLCW4fPYrvpA8XeMyvk4SyYlqs 9h8D21CjRGO4oOyQRQVR0dGKnwNa8dvvAVdkKwwts3pt0niIGAmbGeR9NJnGYd2n jPNKv3GmhMqkcVVAKC3UKN6P4NPindcYPS1nenerW62QyXn2GXXDK4QDgOiQ5jcq 0AliDM4KBa61a+h1Lt4k5h42Bbs4mlFmGp4Y+v/KBybf/Tpr448DeYOtVHZraL8i ETi/Pn8SK6Khq5U/nrpXKi+UrMirg3vc/m6R014JkAYE7YPbkgjfwGHPMYhd2qoU ETaya6mmNXfpcKWY+QGGoYFtu6Cgs27f9OwhT+iVfHrCT4NAN7RSw9lWObioqne0 42byDWmBjzQls8jwxC6fgmWP2/nM1ncVTV6YltmxVEudmHAdAPz0hIzP0BzTCBMJ JtsMVhPRDoFa8a+fZwaP1bTBFS0sKjHOj9StJcJmJgzULK64P9uZc4Gl9ecezhDy YFlneWdOQLrk3j0dOSZE9Tta9FOsurQ300vGOVoPhco= -----END RSA PRIVATE KEY----- rsakey-camellia192.pem100644001750001750 141014723477042 17506 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: CAMELLIA-192-CBC,3F5C8A2CF361867FE8A1D041D448C433 Mop1yn6zWnB1rgOva13j8cH32xNVjzI3xc+zZFUKNQf5laljcNyaissnNhmvgw7D YA8YszBTnolrr4KnQL/ndMIMo+V2DnAHWWaEyc77kISxJ8aAuJYyWRbAB6Cz8t5C w85iDvgX1mopoi3jtyptMmON4lTtLizq0LmAoIGwFO/qcgWz9itzSfRdMQ1+0yV6 h9JLaDFBb3IDZDjgB94fyPvtL/lH6HLozLgfNg6DF/Ld3oOIJ++hGZBaOIRrVrxh AVyNi6MnraBkiq1sbTMrBwu4NSU4IwY5TVbRYAMM0kLRgedWX4XNTawWWQuo56cN zdPhXPrmfwLrmBEz9h9W02KnLIzGTVAm7nODEtvV2Bnz0dtYqcFyH9Pddv1FgJP1 asPNEjZOZIf26ktEpQkhNF3wkiVznQUMJQVQycCy9g7fG1e2BykFfLyxpWn+dIta Bg5yflmdRPhl8KL00y1wez8380WXerZKX6I0Mwctn72yOjueV0KU+daDdbQRgu+a fP5LtjKwHtkvkAviVoBvm1lh60TlEOtTWP90NAP9uORGtd5mQ/dOkLNCYpZ7+NKb oaVcT/I9mvsRi0rMZsk9RszdPi6kOKoVydQvNt0Ilkg= -----END RSA PRIVATE KEY----- rsakey-camellia256.pem100644001750001750 141014723477042 17507 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: CAMELLIA-256-CBC,A16D6AA410454116292D3D76EEC9EAAF mRxKJ//V0eBUs7cZASTc1bdEsFS2BuBmL13cNDp050SSnGvB3a707MMeZQdfQat5 jf4VqmKhXdvZDtMtvPJqij7mFMR78TpaQWEq57fvciu7RiQkdClSh7D4z9fVeS1B 6SEvINnZuTils/bDTkOW1Nc4Y3ApiSZ2iuWCoInRUUgneeCLMB+dQHLKo1yDougn dVDpNDuTGraGPkLVN2WnLlxwgiWaHKOb4FZbNhZhOyCjvFRI9cYXpOJZD6IDW1j2 s8SfGRqexFgUUMeyi8GJDxXYLWx01MMPT7Td+9xVA9QE3DxXM1XSgzsvhPo5b/IV kxyFiUQ9IPn4QrLvjO4ZtMv2zB59Xs7xmBxW28k/BqMelAus1tgAGEDTDcSbBWYp ANnDW+xyUTXA3BjuVB6ybOP3h5a0cfWiY+yjzU71ZxNAlCUwtddE0HPxNGDbvkyU xwkTm8UEOnft/xdsa4JMcJ31cUF/UMMB17PHXNDMFf9bwwtwzc0ptWVLDZSTzOMM OLHF94mdHhO0oYzR7NbKRjiaKeoxjTjEUOxmC5AZ8p5wC1beNOYZOOvRfobNbAZF UmubW/KQyt90JfTtcpNIUvZ9kZkuwAMJaDmaZqi6jQY= -----END RSA PRIVATE KEY----- rsakey2-camellia128.pem100644001750001750 62614723477042 17557 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: CAMELLIA-128-CBC,FDD38BED54F6B627F7057C26728AF96B wj/VomMcf5qiWaSszqCQZ0n/WYACC4bvzsJeJO7AGR72FcTpXLokoabS+P3qBdYW vRyjAefAr2H0DiPSZ2qsqrqKfaymD6DplY6SJdrDTyrsK7BohT1sH+XeeV89H+oK W/6T5GVhrnvczmb9/GmjAVw4zUMtzh26cHXmPq4jISmNhUhaAhC9wqC28rG76E9q VSGoNzAS90yLhv+Erdf5jbjE+LCpNHrf9923gZDAAHNXe88ebuvKkOOnN2Mdch+E -----END RSA PRIVATE KEY----- rsakey2-camellia192.pem100644001750001750 62614723477042 17560 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: CAMELLIA-192-CBC,61DC7BC55B703D70EBDB9F323D1D1D76 kbOpA6DlnawIK/Tv2Dlapkmtr+CjDgAF02CKnNG7GU+lKZk74391bD+4wWc1wq7e K6a162nt11D3b2KJVIHOYoXQdMj7YUJNxCg0XwpFpXgeH/gcaAXBwmvuyeh0EshL k8Ckul/8X/euDLgEXkDBTq4YLyKlS7NbpjjXsPSHAM7coGVoG8dQvLTnu/JirCmx 3DAVVSgYvDQrPCjjcXeK8afjxVsDSUJ4kWZELjUcxwVA6DOYGlmdR47HrJIQ9s4r -----END RSA PRIVATE KEY----- rsakey2-camellia256.pem100644001750001750 62614723477042 17561 0ustar00timtim000000000000Convert-PEM-0.13/t/data-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: CAMELLIA-256-CBC,D56118803AE5E38F8E2493B74E044BF8 hn+Vb77w1b9O9NfN38xKfonObvy0xfyJHurBshIT69sUps6OqSROAvQMy6zRnbSl jZXVqyE7lOlNKx3MlV/jz20t38c7lAXjQhFWBw++0pGuO2MCWvNr9YsnpfBo4LuB tZpao6WTw4qOqIQWeLDYbpqFma4ZQUJNZLOiVy6SjlpJHIuakhXGDhuXceMuNyJb Fy8h71Y5JJF1fGcgoTAO2XTYOvaMihK/9wKYJgPFd/K/RyxgBGOaKbROlvkgwwr/ -----END RSA PRIVATE KEY-----