[not-yet-commons-ssl] 01/08: Imported Upstream version 0.3.9

Tony Mancill tmancill at moszumanska.debian.org
Thu Aug 28 21:03:12 UTC 2014


This is an automated email from the git hooks/post-receive script.

tmancill pushed a commit to branch master
in repository not-yet-commons-ssl.

commit 0a17f4672500f5e093b583ae45b1c9906d88da10
Author: tony mancill <tmancill at debian.org>
Date:   Thu Aug 28 08:12:16 2014 -0700

    Imported Upstream version 0.3.9
---
 LICENSE.txt                                        |  176 ++++
 NOTICE.txt                                         |   10 +
 README.txt                                         |    9 +
 build.xml                                          |  106 ++
 docs/.htaccess                                     |    3 +
 docs/404.html                                      |   51 +
 docs/404.html~                                     |   51 +
 docs/TrustExample.java                             |  114 +++
 docs/TrustExample.java.html                        |  131 +++
 docs/about.html                                    |   73 ++
 docs/download.html                                 |  229 +++++
 docs/download.html~                                |  229 +++++
 docs/index.html                                    |  110 +++
 docs/pbe.html                                      |  204 ++++
 docs/ping.html                                     |   92 ++
 docs/pkcs8.html                                    |  156 +++
 docs/rmi.html                                      |  102 ++
 docs/source.html                                   |   38 +
 docs/ssl.html                                      |  106 ++
 docs/tree.html                                     |  156 +++
 docs/utilities.html                                |   91 ++
 samples/PASSWORD.txt                               |    3 +
 samples/README.txt                                 |    3 +
 samples/createPBESamples.sh                        |  106 ++
 samples/dsa.html                                   |  114 +++
 samples/dsa/openssl_dsa_aes128_cbc.pem             |   23 +
 samples/dsa/openssl_dsa_aes128_cfb.pem             |   23 +
 samples/dsa/openssl_dsa_aes128_ecb.pem             |   23 +
 samples/dsa/openssl_dsa_aes128_ofb.pem             |   23 +
 samples/dsa/openssl_dsa_aes192_cbc.pem             |   23 +
 samples/dsa/openssl_dsa_aes192_cfb.pem             |   23 +
 samples/dsa/openssl_dsa_aes192_ecb.pem             |   23 +
 samples/dsa/openssl_dsa_aes192_ofb.pem             |   23 +
 samples/dsa/openssl_dsa_aes256_cbc.pem             |   23 +
 samples/dsa/openssl_dsa_aes256_cfb.pem             |   23 +
 samples/dsa/openssl_dsa_aes256_ecb.pem             |   23 +
 samples/dsa/openssl_dsa_aes256_ofb.pem             |   23 +
 samples/dsa/openssl_dsa_blowfish_cbc.pem           |   23 +
 samples/dsa/openssl_dsa_blowfish_cfb.pem           |   23 +
 samples/dsa/openssl_dsa_blowfish_ecb.pem           |   23 +
 samples/dsa/openssl_dsa_blowfish_ofb.pem           |   23 +
 samples/dsa/openssl_dsa_des1_cbc.pem               |   23 +
 samples/dsa/openssl_dsa_des1_cfb.pem               |   23 +
 samples/dsa/openssl_dsa_des1_ecb.pem               |   23 +
 samples/dsa/openssl_dsa_des1_ofb.pem               |   23 +
 samples/dsa/openssl_dsa_des2_cbc.pem               |   23 +
 samples/dsa/openssl_dsa_des2_cfb.pem               |   23 +
 samples/dsa/openssl_dsa_des2_ecb.pem               |   23 +
 samples/dsa/openssl_dsa_des2_ofb.pem               |   23 +
 samples/dsa/openssl_dsa_des3_cbc.pem               |   23 +
 samples/dsa/openssl_dsa_des3_cfb.pem               |   23 +
 samples/dsa/openssl_dsa_des3_ecb.pem               |   23 +
 samples/dsa/openssl_dsa_des3_ofb.pem               |   23 +
 samples/dsa/openssl_dsa_rc2_128_cbc.pem            |   23 +
 samples/dsa/openssl_dsa_rc2_128_cfb.pem            |   23 +
 samples/dsa/openssl_dsa_rc2_128_ecb.pem            |   23 +
 samples/dsa/openssl_dsa_rc2_128_ofb.pem            |   23 +
 samples/dsa/openssl_dsa_rc2_40_cbc.pem             |   23 +
 samples/dsa/openssl_dsa_rc2_64_cbc.pem             |   23 +
 samples/dsa/openssl_dsa_unencrypted.der            |  Bin 0 -> 834 bytes
 samples/dsa/openssl_dsa_unencrypted.pem            |   20 +
 samples/dsa/pkcs8_dsa_unencrypted.der              |  Bin 0 -> 593 bytes
 samples/dsa/pkcs8_dsa_unencrypted.pem              |   15 +
 samples/dsa/pkcs8v1_dsa_md2_des1_cbc.der           |  Bin 0 -> 637 bytes
 samples/dsa/pkcs8v1_dsa_md2_des1_cbc.pem           |   16 +
 samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.der         |  Bin 0 -> 637 bytes
 samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.pem         |   16 +
 samples/dsa/pkcs8v1_dsa_md5_des1_cbc.der           |  Bin 0 -> 637 bytes
 samples/dsa/pkcs8v1_dsa_md5_des1_cbc.pem           |   16 +
 samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.der         |  Bin 0 -> 637 bytes
 samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.pem         |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.der          |  Bin 0 -> 637 bytes
 samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.pem          |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.der          |  Bin 0 -> 638 bytes
 samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.pem          |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.der          |  Bin 0 -> 638 bytes
 samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.pem          |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.der       |  Bin 0 -> 638 bytes
 samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.pem       |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.der        |  Bin 0 -> 638 bytes
 samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.pem        |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.der        |  Bin 0 -> 637 bytes
 samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.pem        |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_rc4_128.der           |  Bin 0 -> 631 bytes
 samples/dsa/pkcs8v1_dsa_sha1_rc4_128.pem           |   16 +
 samples/dsa/pkcs8v1_dsa_sha1_rc4_40.der            |  Bin 0 -> 631 bytes
 samples/dsa/pkcs8v1_dsa_sha1_rc4_40.pem            |   16 +
 samples/dsa/pkcs8v2_dsa_aes128_cbc.der             |  Bin 0 -> 691 bytes
 samples/dsa/pkcs8v2_dsa_aes128_cbc.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes128_cfb.der             |  Bin 0 -> 676 bytes
 samples/dsa/pkcs8v2_dsa_aes128_cfb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes128_ecb.der             |  Bin 0 -> 691 bytes
 samples/dsa/pkcs8v2_dsa_aes128_ecb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes128_ofb.der             |  Bin 0 -> 676 bytes
 samples/dsa/pkcs8v2_dsa_aes128_ofb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes192_cbc.der             |  Bin 0 -> 691 bytes
 samples/dsa/pkcs8v2_dsa_aes192_cbc.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes192_cfb.der             |  Bin 0 -> 676 bytes
 samples/dsa/pkcs8v2_dsa_aes192_cfb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes192_ecb.der             |  Bin 0 -> 691 bytes
 samples/dsa/pkcs8v2_dsa_aes192_ecb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes192_ofb.der             |  Bin 0 -> 676 bytes
 samples/dsa/pkcs8v2_dsa_aes192_ofb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes256_cbc.der             |  Bin 0 -> 691 bytes
 samples/dsa/pkcs8v2_dsa_aes256_cbc.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes256_cfb.der             |  Bin 0 -> 676 bytes
 samples/dsa/pkcs8v2_dsa_aes256_cfb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes256_ecb.der             |  Bin 0 -> 691 bytes
 samples/dsa/pkcs8v2_dsa_aes256_ecb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_aes256_ofb.der             |  Bin 0 -> 676 bytes
 samples/dsa/pkcs8v2_dsa_aes256_ofb.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_blowfish_cbc.der           |  Bin 0 -> 675 bytes
 samples/dsa/pkcs8v2_dsa_blowfish_cbc.pem           |   17 +
 samples/dsa/pkcs8v2_dsa_des1_cbc.der               |  Bin 0 -> 671 bytes
 samples/dsa/pkcs8v2_dsa_des1_cbc.pem               |   16 +
 samples/dsa/pkcs8v2_dsa_des1_cfb.der               |  Bin 0 -> 664 bytes
 samples/dsa/pkcs8v2_dsa_des1_cfb.pem               |   16 +
 samples/dsa/pkcs8v2_dsa_des1_ecb.der               |  Bin 0 -> 671 bytes
 samples/dsa/pkcs8v2_dsa_des1_ecb.pem               |   16 +
 samples/dsa/pkcs8v2_dsa_des1_ofb.der               |  Bin 0 -> 664 bytes
 samples/dsa/pkcs8v2_dsa_des1_ofb.pem               |   16 +
 samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.der   |  Bin 0 -> 671 bytes
 samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.pem   |   16 +
 samples/dsa/pkcs8v2_dsa_des3_cbc.der               |  Bin 0 -> 674 bytes
 samples/dsa/pkcs8v2_dsa_des3_cbc.pem               |   17 +
 samples/dsa/pkcs8v2_dsa_rc2_128_cbc.der            |  Bin 0 -> 682 bytes
 samples/dsa/pkcs8v2_dsa_rc2_128_cbc.pem            |   17 +
 samples/dsa/pkcs8v2_dsa_rc2_40_cbc.der             |  Bin 0 -> 683 bytes
 samples/dsa/pkcs8v2_dsa_rc2_40_cbc.pem             |   17 +
 samples/dsa/pkcs8v2_dsa_rc2_64_cbc.der             |  Bin 0 -> 682 bytes
 samples/dsa/pkcs8v2_dsa_rc2_64_cbc.pem             |   17 +
 samples/dsa_result.html                            |   38 +
 samples/pbe.tests                                  |   45 +
 samples/pbe/README.txt                             |   36 +
 samples/pbe/java/aes-128-cbc.base64                |    1 +
 samples/pbe/java/aes-128-cbc.raw                   |    1 +
 samples/pbe/java/aes-128-cfb.base64                |    1 +
 samples/pbe/java/aes-128-cfb.raw                   |    1 +
 samples/pbe/java/aes-128-cfb8.base64               |    1 +
 samples/pbe/java/aes-128-cfb8.raw                  |    1 +
 samples/pbe/java/aes-128-ecb.base64                |    1 +
 samples/pbe/java/aes-128-ecb.raw                   |    1 +
 samples/pbe/java/aes-128-ofb.base64                |    1 +
 samples/pbe/java/aes-128-ofb.raw                   |    1 +
 samples/pbe/java/aes-128.base64                    |    1 +
 samples/pbe/java/aes-128.raw                       |    1 +
 samples/pbe/java/aes-192-cbc.base64                |    1 +
 samples/pbe/java/aes-192-cbc.raw                   |    1 +
 samples/pbe/java/aes-192-cfb.base64                |    1 +
 samples/pbe/java/aes-192-cfb.raw                   |    1 +
 samples/pbe/java/aes-192-cfb8.base64               |    1 +
 samples/pbe/java/aes-192-cfb8.raw                  |    1 +
 samples/pbe/java/aes-192-ecb.base64                |    1 +
 samples/pbe/java/aes-192-ecb.raw                   |    2 +
 samples/pbe/java/aes-192-ofb.base64                |    1 +
 samples/pbe/java/aes-192-ofb.raw                   |    1 +
 samples/pbe/java/aes-192.base64                    |    1 +
 samples/pbe/java/aes-192.raw                       |    1 +
 samples/pbe/java/aes-256-cbc.base64                |    1 +
 samples/pbe/java/aes-256-cbc.raw                   |    1 +
 samples/pbe/java/aes-256-cfb.base64                |    1 +
 samples/pbe/java/aes-256-cfb.raw                   |    1 +
 samples/pbe/java/aes-256-cfb8.base64               |    1 +
 samples/pbe/java/aes-256-cfb8.raw                  |    1 +
 samples/pbe/java/aes-256-ecb.base64                |    1 +
 samples/pbe/java/aes-256-ecb.raw                   |    1 +
 samples/pbe/java/aes-256-ofb.base64                |    1 +
 samples/pbe/java/aes-256-ofb.raw                   |    1 +
 samples/pbe/java/aes-256.base64                    |    1 +
 samples/pbe/java/aes-256.raw                       |    1 +
 samples/pbe/java/aes128-cbc.base64                 |    1 +
 samples/pbe/java/aes128-cbc.raw                    |    1 +
 samples/pbe/java/aes128-cfb.base64                 |    1 +
 samples/pbe/java/aes128-cfb.raw                    |    1 +
 samples/pbe/java/aes128-cfb8.base64                |    1 +
 samples/pbe/java/aes128-cfb8.raw                   |    1 +
 samples/pbe/java/aes128-ecb.base64                 |    1 +
 samples/pbe/java/aes128-ecb.raw                    |    1 +
 samples/pbe/java/aes128-ofb.base64                 |    1 +
 samples/pbe/java/aes128-ofb.raw                    |    1 +
 samples/pbe/java/aes128.base64                     |    1 +
 samples/pbe/java/aes128.raw                        |    1 +
 samples/pbe/java/aes192-cbc.base64                 |    1 +
 samples/pbe/java/aes192-cbc.raw                    |  Bin 0 -> 32 bytes
 samples/pbe/java/aes192-cfb.base64                 |    1 +
 samples/pbe/java/aes192-cfb.raw                    |    2 +
 samples/pbe/java/aes192-cfb8.base64                |    1 +
 samples/pbe/java/aes192-cfb8.raw                   |    1 +
 samples/pbe/java/aes192-ecb.base64                 |    1 +
 samples/pbe/java/aes192-ecb.raw                    |    1 +
 samples/pbe/java/aes192-ofb.base64                 |    1 +
 samples/pbe/java/aes192-ofb.raw                    |    1 +
 samples/pbe/java/aes192.base64                     |    1 +
 samples/pbe/java/aes192.raw                        |    1 +
 samples/pbe/java/aes256-cbc.base64                 |    1 +
 samples/pbe/java/aes256-cbc.raw                    |    1 +
 samples/pbe/java/aes256-cfb.base64                 |    1 +
 samples/pbe/java/aes256-cfb.raw                    |    2 +
 samples/pbe/java/aes256-cfb8.base64                |    1 +
 samples/pbe/java/aes256-cfb8.raw                   |    1 +
 samples/pbe/java/aes256-ecb.base64                 |    1 +
 samples/pbe/java/aes256-ecb.raw                    |    1 +
 samples/pbe/java/aes256-ofb.base64                 |    1 +
 samples/pbe/java/aes256-ofb.raw                    |    1 +
 samples/pbe/java/aes256.base64                     |    1 +
 samples/pbe/java/aes256.raw                        |    1 +
 samples/pbe/java/bf-cbc.base64                     |    1 +
 samples/pbe/java/bf-cbc.raw                        |    1 +
 samples/pbe/java/bf-cfb.base64                     |    1 +
 samples/pbe/java/bf-cfb.raw                        |    1 +
 samples/pbe/java/bf-cfb8.base64                    |    1 +
 samples/pbe/java/bf-cfb8.raw                       |    1 +
 samples/pbe/java/bf-ecb.base64                     |    1 +
 samples/pbe/java/bf-ecb.raw                        |    1 +
 samples/pbe/java/bf-ofb.base64                     |    1 +
 samples/pbe/java/bf-ofb.raw                        |    1 +
 samples/pbe/java/bf.base64                         |    1 +
 samples/pbe/java/bf.raw                            |    1 +
 samples/pbe/java/blowfish-cbc.base64               |    1 +
 samples/pbe/java/blowfish-cbc.raw                  |    1 +
 samples/pbe/java/blowfish-cfb.base64               |    1 +
 samples/pbe/java/blowfish-cfb.raw                  |    1 +
 samples/pbe/java/blowfish-cfb8.base64              |    1 +
 samples/pbe/java/blowfish-cfb8.raw                 |    1 +
 samples/pbe/java/blowfish-ecb.base64               |    1 +
 samples/pbe/java/blowfish-ecb.raw                  |    1 +
 samples/pbe/java/blowfish-ofb.base64               |    1 +
 samples/pbe/java/blowfish-ofb.raw                  |    2 +
 samples/pbe/java/blowfish.base64                   |    1 +
 samples/pbe/java/blowfish.raw                      |    1 +
 samples/pbe/java/camellia-128-cbc.base64           |    1 +
 samples/pbe/java/camellia-128-cbc.raw              |    1 +
 samples/pbe/java/camellia-128-cfb.base64           |    1 +
 samples/pbe/java/camellia-128-cfb.raw              |  Bin 0 -> 28 bytes
 samples/pbe/java/camellia-128-cfb8.base64          |    1 +
 samples/pbe/java/camellia-128-cfb8.raw             |    1 +
 samples/pbe/java/camellia-128-ecb.base64           |    1 +
 samples/pbe/java/camellia-128-ecb.raw              |    1 +
 samples/pbe/java/camellia-128-ofb.base64           |    1 +
 samples/pbe/java/camellia-128-ofb.raw              |    1 +
 samples/pbe/java/camellia-128.base64               |    1 +
 samples/pbe/java/camellia-128.raw                  |    1 +
 samples/pbe/java/camellia-192-cbc.base64           |    1 +
 samples/pbe/java/camellia-192-cbc.raw              |    1 +
 samples/pbe/java/camellia-192-cfb.base64           |    1 +
 samples/pbe/java/camellia-192-cfb.raw              |    2 +
 samples/pbe/java/camellia-192-cfb8.base64          |    1 +
 samples/pbe/java/camellia-192-cfb8.raw             |    1 +
 samples/pbe/java/camellia-192-ecb.base64           |    1 +
 samples/pbe/java/camellia-192-ecb.raw              |    1 +
 samples/pbe/java/camellia-192-ofb.base64           |    1 +
 samples/pbe/java/camellia-192-ofb.raw              |    1 +
 samples/pbe/java/camellia-192.base64               |    1 +
 samples/pbe/java/camellia-192.raw                  |    1 +
 samples/pbe/java/camellia-256-cbc.base64           |    1 +
 samples/pbe/java/camellia-256-cbc.raw              |    1 +
 samples/pbe/java/camellia-256-cfb.base64           |    1 +
 samples/pbe/java/camellia-256-cfb.raw              |    1 +
 samples/pbe/java/camellia-256-cfb8.base64          |    1 +
 samples/pbe/java/camellia-256-cfb8.raw             |    1 +
 samples/pbe/java/camellia-256-ecb.base64           |    1 +
 samples/pbe/java/camellia-256-ecb.raw              |    1 +
 samples/pbe/java/camellia-256-ofb.base64           |    1 +
 samples/pbe/java/camellia-256-ofb.raw              |    1 +
 samples/pbe/java/camellia-256.base64               |    1 +
 samples/pbe/java/camellia-256.raw                  |    1 +
 samples/pbe/java/camellia128-cbc.base64            |    1 +
 samples/pbe/java/camellia128-cbc.raw               |    1 +
 samples/pbe/java/camellia128-cfb.base64            |    1 +
 samples/pbe/java/camellia128-cfb.raw               |    1 +
 samples/pbe/java/camellia128-cfb8.base64           |    1 +
 samples/pbe/java/camellia128-cfb8.raw              |    1 +
 samples/pbe/java/camellia128-ecb.base64            |    1 +
 samples/pbe/java/camellia128-ecb.raw               |    1 +
 samples/pbe/java/camellia128-ofb.base64            |    1 +
 samples/pbe/java/camellia128-ofb.raw               |    1 +
 samples/pbe/java/camellia128.base64                |    1 +
 samples/pbe/java/camellia128.raw                   |    1 +
 samples/pbe/java/camellia192-cbc.base64            |    1 +
 samples/pbe/java/camellia192-cbc.raw               |    1 +
 samples/pbe/java/camellia192-cfb.base64            |    1 +
 samples/pbe/java/camellia192-cfb.raw               |    1 +
 samples/pbe/java/camellia192-cfb8.base64           |    1 +
 samples/pbe/java/camellia192-cfb8.raw              |    1 +
 samples/pbe/java/camellia192-ecb.base64            |    1 +
 samples/pbe/java/camellia192-ecb.raw               |    1 +
 samples/pbe/java/camellia192-ofb.base64            |    1 +
 samples/pbe/java/camellia192-ofb.raw               |    1 +
 samples/pbe/java/camellia192.base64                |    1 +
 samples/pbe/java/camellia192.raw                   |    1 +
 samples/pbe/java/camellia256-cbc.base64            |    1 +
 samples/pbe/java/camellia256-cbc.raw               |    1 +
 samples/pbe/java/camellia256-cfb.base64            |    1 +
 samples/pbe/java/camellia256-cfb.raw               |    1 +
 samples/pbe/java/camellia256-cfb8.base64           |    1 +
 samples/pbe/java/camellia256-cfb8.raw              |    1 +
 samples/pbe/java/camellia256-ecb.base64            |    1 +
 samples/pbe/java/camellia256-ecb.raw               |    1 +
 samples/pbe/java/camellia256-ofb.base64            |    1 +
 samples/pbe/java/camellia256-ofb.raw               |    1 +
 samples/pbe/java/camellia256.base64                |    1 +
 samples/pbe/java/camellia256.raw                   |    1 +
 samples/pbe/java/cast5-cbc.base64                  |    1 +
 samples/pbe/java/cast5-cbc.raw                     |    1 +
 samples/pbe/java/cast5-cfb.base64                  |    1 +
 samples/pbe/java/cast5-cfb.raw                     |    1 +
 samples/pbe/java/cast5-cfb8.base64                 |    1 +
 samples/pbe/java/cast5-cfb8.raw                    |    1 +
 samples/pbe/java/cast5-ecb.base64                  |    1 +
 samples/pbe/java/cast5-ecb.raw                     |    1 +
 samples/pbe/java/cast5-ofb.base64                  |    1 +
 samples/pbe/java/cast5-ofb.raw                     |    1 +
 samples/pbe/java/cast5.base64                      |    1 +
 samples/pbe/java/cast5.raw                         |    2 +
 samples/pbe/java/cast6-cbc.base64                  |    1 +
 samples/pbe/java/cast6-cbc.raw                     |    1 +
 samples/pbe/java/cast6-cfb.base64                  |    1 +
 samples/pbe/java/cast6-cfb.raw                     |    1 +
 samples/pbe/java/cast6-cfb8.base64                 |    1 +
 samples/pbe/java/cast6-cfb8.raw                    |    1 +
 samples/pbe/java/cast6-ecb.base64                  |    1 +
 samples/pbe/java/cast6-ecb.raw                     |    1 +
 samples/pbe/java/cast6-ofb.base64                  |    1 +
 samples/pbe/java/cast6-ofb.raw                     |    1 +
 samples/pbe/java/cast6.base64                      |    1 +
 samples/pbe/java/cast6.raw                         |    1 +
 samples/pbe/java/des-cbc.base64                    |    1 +
 samples/pbe/java/des-cbc.raw                       |    1 +
 samples/pbe/java/des-cfb.base64                    |    1 +
 samples/pbe/java/des-cfb.raw                       |    1 +
 samples/pbe/java/des-cfb8.base64                   |    1 +
 samples/pbe/java/des-cfb8.raw                      |    1 +
 samples/pbe/java/des-ecb.base64                    |    1 +
 samples/pbe/java/des-ecb.raw                       |    1 +
 samples/pbe/java/des-ede-cbc.base64                |    1 +
 samples/pbe/java/des-ede-cbc.raw                   |    1 +
 samples/pbe/java/des-ede-cfb.base64                |    1 +
 samples/pbe/java/des-ede-cfb.raw                   |  Bin 0 -> 28 bytes
 samples/pbe/java/des-ede-cfb8.base64               |    1 +
 samples/pbe/java/des-ede-cfb8.raw                  |    1 +
 samples/pbe/java/des-ede-ecb.base64                |    1 +
 samples/pbe/java/des-ede-ecb.raw                   |    1 +
 samples/pbe/java/des-ede-ofb.base64                |    1 +
 samples/pbe/java/des-ede-ofb.raw                   |    1 +
 samples/pbe/java/des-ede.base64                    |    1 +
 samples/pbe/java/des-ede.raw                       |  Bin 0 -> 32 bytes
 samples/pbe/java/des-ede3-cbc.base64               |    1 +
 samples/pbe/java/des-ede3-cbc.raw                  |    1 +
 samples/pbe/java/des-ede3-cfb.base64               |    1 +
 samples/pbe/java/des-ede3-cfb.raw                  |    1 +
 samples/pbe/java/des-ede3-cfb8.base64              |    1 +
 samples/pbe/java/des-ede3-cfb8.raw                 |    1 +
 samples/pbe/java/des-ede3-ecb.base64               |    1 +
 samples/pbe/java/des-ede3-ecb.raw                  |    1 +
 samples/pbe/java/des-ede3-ofb.base64               |    1 +
 samples/pbe/java/des-ede3-ofb.raw                  |    1 +
 samples/pbe/java/des-ede3.base64                   |    1 +
 samples/pbe/java/des-ede3.raw                      |  Bin 0 -> 32 bytes
 samples/pbe/java/des-ofb.base64                    |    1 +
 samples/pbe/java/des-ofb.raw                       |    1 +
 samples/pbe/java/des.base64                        |    1 +
 samples/pbe/java/des.raw                           |    1 +
 samples/pbe/java/des2-cbc.base64                   |    1 +
 samples/pbe/java/des2-cbc.raw                      |    1 +
 samples/pbe/java/des2-cfb.base64                   |    1 +
 samples/pbe/java/des2-cfb.raw                      |    1 +
 samples/pbe/java/des2-cfb8.base64                  |    1 +
 samples/pbe/java/des2-cfb8.raw                     |    1 +
 samples/pbe/java/des2-ecb.base64                   |    1 +
 samples/pbe/java/des2-ecb.raw                      |  Bin 0 -> 32 bytes
 samples/pbe/java/des2-ofb.base64                   |    1 +
 samples/pbe/java/des2-ofb.raw                      |    1 +
 samples/pbe/java/des2.base64                       |    1 +
 samples/pbe/java/des2.raw                          |    1 +
 samples/pbe/java/des3-cbc.base64                   |    1 +
 samples/pbe/java/des3-cbc.raw                      |    1 +
 samples/pbe/java/des3-cfb.base64                   |    1 +
 samples/pbe/java/des3-cfb.raw                      |    1 +
 samples/pbe/java/des3-cfb8.base64                  |    1 +
 samples/pbe/java/des3-cfb8.raw                     |    1 +
 samples/pbe/java/des3-ecb.base64                   |    1 +
 samples/pbe/java/des3-ecb.raw                      |    1 +
 samples/pbe/java/des3-ofb.base64                   |    1 +
 samples/pbe/java/des3-ofb.raw                      |    1 +
 samples/pbe/java/des3.base64                       |    1 +
 samples/pbe/java/des3.raw                          |    1 +
 samples/pbe/java/gost-cbc.base64                   |    1 +
 samples/pbe/java/gost-cbc.raw                      |    1 +
 samples/pbe/java/gost-cfb.base64                   |    1 +
 samples/pbe/java/gost-cfb.raw                      |    1 +
 samples/pbe/java/gost-cfb8.base64                  |    1 +
 samples/pbe/java/gost-cfb8.raw                     |    1 +
 samples/pbe/java/gost-ecb.base64                   |    1 +
 samples/pbe/java/gost-ecb.raw                      |    1 +
 samples/pbe/java/gost-ofb.base64                   |    1 +
 samples/pbe/java/gost-ofb.raw                      |    1 +
 samples/pbe/java/gost.base64                       |    1 +
 samples/pbe/java/gost.raw                          |    2 +
 samples/pbe/java/gost28147-cbc.base64              |    1 +
 samples/pbe/java/gost28147-cbc.raw                 |    1 +
 samples/pbe/java/gost28147-cfb.base64              |    1 +
 samples/pbe/java/gost28147-cfb.raw                 |    1 +
 samples/pbe/java/gost28147-cfb8.base64             |    1 +
 samples/pbe/java/gost28147-cfb8.raw                |    1 +
 samples/pbe/java/gost28147-ecb.base64              |    1 +
 samples/pbe/java/gost28147-ecb.raw                 |    1 +
 samples/pbe/java/gost28147-ofb.base64              |    1 +
 samples/pbe/java/gost28147-ofb.raw                 |    1 +
 samples/pbe/java/gost28147.base64                  |    1 +
 samples/pbe/java/gost28147.raw                     |  Bin 0 -> 32 bytes
 samples/pbe/java/idea-cbc.base64                   |    1 +
 samples/pbe/java/idea-cbc.raw                      |    1 +
 samples/pbe/java/idea-cfb.base64                   |    1 +
 samples/pbe/java/idea-cfb.raw                      |    2 +
 samples/pbe/java/idea-cfb8.base64                  |    1 +
 samples/pbe/java/idea-cfb8.raw                     |    1 +
 samples/pbe/java/idea-ecb.base64                   |    1 +
 samples/pbe/java/idea-ecb.raw                      |    2 +
 samples/pbe/java/idea-ofb.base64                   |    1 +
 samples/pbe/java/idea-ofb.raw                      |    1 +
 samples/pbe/java/idea.base64                       |    1 +
 samples/pbe/java/idea.raw                          |    1 +
 samples/pbe/java/rc2-40-cbc.base64                 |    1 +
 samples/pbe/java/rc2-40-cbc.raw                    |    1 +
 samples/pbe/java/rc2-40-cfb.base64                 |    1 +
 samples/pbe/java/rc2-40-cfb.raw                    |    1 +
 samples/pbe/java/rc2-40-cfb8.base64                |    1 +
 samples/pbe/java/rc2-40-cfb8.raw                   |    1 +
 samples/pbe/java/rc2-40-ecb.base64                 |    1 +
 samples/pbe/java/rc2-40-ecb.raw                    |    1 +
 samples/pbe/java/rc2-40-ofb.base64                 |    1 +
 samples/pbe/java/rc2-40-ofb.raw                    |    1 +
 samples/pbe/java/rc2-40.base64                     |    1 +
 samples/pbe/java/rc2-40.raw                        |    1 +
 samples/pbe/java/rc2-64-cbc.base64                 |    1 +
 samples/pbe/java/rc2-64-cbc.raw                    |    1 +
 samples/pbe/java/rc2-64-cfb.base64                 |    1 +
 samples/pbe/java/rc2-64-cfb.raw                    |    1 +
 samples/pbe/java/rc2-64-cfb8.base64                |    1 +
 samples/pbe/java/rc2-64-cfb8.raw                   |  Bin 0 -> 28 bytes
 samples/pbe/java/rc2-64-ecb.base64                 |    1 +
 samples/pbe/java/rc2-64-ecb.raw                    |    1 +
 samples/pbe/java/rc2-64-ofb.base64                 |    1 +
 samples/pbe/java/rc2-64-ofb.raw                    |    1 +
 samples/pbe/java/rc2-64.base64                     |    1 +
 samples/pbe/java/rc2-64.raw                        |    1 +
 samples/pbe/java/rc2-cbc.base64                    |    1 +
 samples/pbe/java/rc2-cbc.raw                       |  Bin 0 -> 32 bytes
 samples/pbe/java/rc2-cfb.base64                    |    1 +
 samples/pbe/java/rc2-cfb.raw                       |    1 +
 samples/pbe/java/rc2-cfb8.base64                   |    1 +
 samples/pbe/java/rc2-cfb8.raw                      |    1 +
 samples/pbe/java/rc2-ecb.base64                    |    1 +
 samples/pbe/java/rc2-ecb.raw                       |    1 +
 samples/pbe/java/rc2-ofb.base64                    |    1 +
 samples/pbe/java/rc2-ofb.raw                       |    1 +
 samples/pbe/java/rc2.base64                        |    1 +
 samples/pbe/java/rc2.raw                           |    1 +
 samples/pbe/java/rc4-40-cbc.base64                 |    1 +
 samples/pbe/java/rc4-40-cbc.raw                    |    1 +
 samples/pbe/java/rc4-40-cfb.base64                 |    1 +
 samples/pbe/java/rc4-40-cfb.raw                    |    1 +
 samples/pbe/java/rc4-40-cfb1.base64                |    1 +
 samples/pbe/java/rc4-40-cfb1.raw                   |    1 +
 samples/pbe/java/rc4-40-cfb8.base64                |    1 +
 samples/pbe/java/rc4-40-cfb8.raw                   |    1 +
 samples/pbe/java/rc4-40-ecb.base64                 |    1 +
 samples/pbe/java/rc4-40-ecb.raw                    |    1 +
 samples/pbe/java/rc4-40-ofb.base64                 |    1 +
 samples/pbe/java/rc4-40-ofb.raw                    |    1 +
 samples/pbe/java/rc4-40.base64                     |    1 +
 samples/pbe/java/rc4-40.raw                        |    1 +
 samples/pbe/java/rc4-cbc.base64                    |    1 +
 samples/pbe/java/rc4-cbc.raw                       |    1 +
 samples/pbe/java/rc4-cfb.base64                    |    1 +
 samples/pbe/java/rc4-cfb.raw                       |    1 +
 samples/pbe/java/rc4-cfb1.base64                   |    1 +
 samples/pbe/java/rc4-cfb1.raw                      |    1 +
 samples/pbe/java/rc4-cfb8.base64                   |    1 +
 samples/pbe/java/rc4-cfb8.raw                      |    1 +
 samples/pbe/java/rc4-ecb.base64                    |    1 +
 samples/pbe/java/rc4-ecb.raw                       |    1 +
 samples/pbe/java/rc4-ofb.base64                    |    1 +
 samples/pbe/java/rc4-ofb.raw                       |    1 +
 samples/pbe/java/rc4.base64                        |    1 +
 samples/pbe/java/rc4.raw                           |  Bin 0 -> 28 bytes
 samples/pbe/java/rc5-cbc.base64                    |    1 +
 samples/pbe/java/rc5-cbc.raw                       |  Bin 0 -> 32 bytes
 samples/pbe/java/rc5-cfb.base64                    |    1 +
 samples/pbe/java/rc5-cfb.raw                       |    1 +
 samples/pbe/java/rc5-cfb8.base64                   |    1 +
 samples/pbe/java/rc5-cfb8.raw                      |    1 +
 samples/pbe/java/rc5-ecb.base64                    |    1 +
 samples/pbe/java/rc5-ecb.raw                       |    1 +
 samples/pbe/java/rc5-ofb.base64                    |    1 +
 samples/pbe/java/rc5-ofb.raw                       |    1 +
 samples/pbe/java/rc5.base64                        |    1 +
 samples/pbe/java/rc5.raw                           |    2 +
 samples/pbe/java/rc6-cbc.base64                    |    1 +
 samples/pbe/java/rc6-cbc.raw                       |    1 +
 samples/pbe/java/rc6-cfb.base64                    |    1 +
 samples/pbe/java/rc6-cfb.raw                       |    1 +
 samples/pbe/java/rc6-cfb8.base64                   |    1 +
 samples/pbe/java/rc6-cfb8.raw                      |    1 +
 samples/pbe/java/rc6-ecb.base64                    |    1 +
 samples/pbe/java/rc6-ecb.raw                       |    1 +
 samples/pbe/java/rc6-ofb.base64                    |    1 +
 samples/pbe/java/rc6-ofb.raw                       |    1 +
 samples/pbe/java/rc6.base64                        |    1 +
 samples/pbe/java/rc6.raw                           |    1 +
 samples/pbe/java/rijndael-cbc.base64               |    1 +
 samples/pbe/java/rijndael-cbc.raw                  |    1 +
 samples/pbe/java/rijndael-cfb.base64               |    1 +
 samples/pbe/java/rijndael-cfb.raw                  |    1 +
 samples/pbe/java/rijndael-cfb8.base64              |    1 +
 samples/pbe/java/rijndael-cfb8.raw                 |    1 +
 samples/pbe/java/rijndael-ecb.base64               |    1 +
 samples/pbe/java/rijndael-ecb.raw                  |    1 +
 samples/pbe/java/rijndael-ofb.base64               |    1 +
 samples/pbe/java/rijndael-ofb.raw                  |  Bin 0 -> 28 bytes
 samples/pbe/java/rijndael.base64                   |    1 +
 samples/pbe/java/rijndael.raw                      |    1 +
 samples/pbe/java/seed-cbc.base64                   |    1 +
 samples/pbe/java/seed-cbc.raw                      |    1 +
 samples/pbe/java/seed-cfb.base64                   |    1 +
 samples/pbe/java/seed-cfb.raw                      |    1 +
 samples/pbe/java/seed-cfb8.base64                  |    1 +
 samples/pbe/java/seed-cfb8.raw                     |    1 +
 samples/pbe/java/seed-ecb.base64                   |    1 +
 samples/pbe/java/seed-ecb.raw                      |    1 +
 samples/pbe/java/seed-ofb.base64                   |    1 +
 samples/pbe/java/seed-ofb.raw                      |  Bin 0 -> 28 bytes
 samples/pbe/java/seed.base64                       |    1 +
 samples/pbe/java/seed.raw                          |    1 +
 samples/pbe/java/serpent-cbc.base64                |    1 +
 samples/pbe/java/serpent-cbc.raw                   |    1 +
 samples/pbe/java/serpent-cfb.base64                |    1 +
 samples/pbe/java/serpent-cfb.raw                   |  Bin 0 -> 28 bytes
 samples/pbe/java/serpent-cfb8.base64               |    1 +
 samples/pbe/java/serpent-cfb8.raw                  |    1 +
 samples/pbe/java/serpent-ecb.base64                |    1 +
 samples/pbe/java/serpent-ecb.raw                   |    1 +
 samples/pbe/java/serpent-ofb.base64                |    1 +
 samples/pbe/java/serpent-ofb.raw                   |    1 +
 samples/pbe/java/serpent.base64                    |    1 +
 samples/pbe/java/serpent.raw                       |    2 +
 samples/pbe/java/skipjack-cbc.base64               |    1 +
 samples/pbe/java/skipjack-cbc.raw                  |    1 +
 samples/pbe/java/skipjack-cfb.base64               |    1 +
 samples/pbe/java/skipjack-cfb.raw                  |    1 +
 samples/pbe/java/skipjack-cfb8.base64              |    1 +
 samples/pbe/java/skipjack-cfb8.raw                 |    1 +
 samples/pbe/java/skipjack-ecb.base64               |    1 +
 samples/pbe/java/skipjack-ecb.raw                  |    1 +
 samples/pbe/java/skipjack-ofb.base64               |    1 +
 samples/pbe/java/skipjack-ofb.raw                  |    1 +
 samples/pbe/java/skipjack.base64                   |    1 +
 samples/pbe/java/skipjack.raw                      |    1 +
 samples/pbe/java/tea-cbc.base64                    |    1 +
 samples/pbe/java/tea-cbc.raw                       |    1 +
 samples/pbe/java/tea-cfb.base64                    |    1 +
 samples/pbe/java/tea-cfb.raw                       |  Bin 0 -> 28 bytes
 samples/pbe/java/tea-cfb8.base64                   |    1 +
 samples/pbe/java/tea-cfb8.raw                      |  Bin 0 -> 28 bytes
 samples/pbe/java/tea-ecb.base64                    |    1 +
 samples/pbe/java/tea-ecb.raw                       |    1 +
 samples/pbe/java/tea-ofb.base64                    |    1 +
 samples/pbe/java/tea-ofb.raw                       |    1 +
 samples/pbe/java/tea.base64                        |    1 +
 samples/pbe/java/tea.raw                           |    1 +
 samples/pbe/java/twofish-cbc.base64                |    1 +
 samples/pbe/java/twofish-cbc.raw                   |    2 +
 samples/pbe/java/twofish-cfb.base64                |    1 +
 samples/pbe/java/twofish-cfb.raw                   |    1 +
 samples/pbe/java/twofish-cfb8.base64               |    1 +
 samples/pbe/java/twofish-cfb8.raw                  |  Bin 0 -> 28 bytes
 samples/pbe/java/twofish-ecb.base64                |    1 +
 samples/pbe/java/twofish-ecb.raw                   |    1 +
 samples/pbe/java/twofish-ofb.base64                |    1 +
 samples/pbe/java/twofish-ofb.raw                   |    1 +
 samples/pbe/java/twofish.base64                    |    1 +
 samples/pbe/java/twofish.raw                       |    1 +
 samples/pbe/java/xtea-cbc.base64                   |    1 +
 samples/pbe/java/xtea-cbc.raw                      |    1 +
 samples/pbe/java/xtea-cfb.base64                   |    1 +
 samples/pbe/java/xtea-cfb.raw                      |    1 +
 samples/pbe/java/xtea-cfb8.base64                  |    1 +
 samples/pbe/java/xtea-cfb8.raw                     |  Bin 0 -> 28 bytes
 samples/pbe/java/xtea-ecb.base64                   |    1 +
 samples/pbe/java/xtea-ecb.raw                      |    1 +
 samples/pbe/java/xtea-ofb.base64                   |    1 +
 samples/pbe/java/xtea-ofb.raw                      |    1 +
 samples/pbe/java/xtea.base64                       |    1 +
 samples/pbe/java/xtea.raw                          |    1 +
 samples/pbe/openssl/README.txt                     |    5 +
 samples/pbe/openssl/aes-128-cbc.base64             |    1 +
 samples/pbe/openssl/aes-128-cbc.raw                |  Bin 0 -> 32 bytes
 samples/pbe/openssl/aes-128-cfb.base64             |    1 +
 samples/pbe/openssl/aes-128-cfb.raw                |    1 +
 samples/pbe/openssl/aes-128-cfb1.base64            |    1 +
 samples/pbe/openssl/aes-128-cfb1.raw               |  Bin 0 -> 28 bytes
 samples/pbe/openssl/aes-128-cfb8.base64            |    1 +
 samples/pbe/openssl/aes-128-cfb8.raw               |    2 +
 samples/pbe/openssl/aes-128-ecb.base64             |    1 +
 samples/pbe/openssl/aes-128-ecb.raw                |    1 +
 samples/pbe/openssl/aes-128-ofb.base64             |    1 +
 samples/pbe/openssl/aes-128-ofb.raw                |    1 +
 samples/pbe/openssl/aes-192-cbc.base64             |    1 +
 samples/pbe/openssl/aes-192-cbc.raw                |    1 +
 samples/pbe/openssl/aes-192-cfb.base64             |    1 +
 samples/pbe/openssl/aes-192-cfb.raw                |    1 +
 samples/pbe/openssl/aes-192-cfb1.base64            |    1 +
 samples/pbe/openssl/aes-192-cfb1.raw               |  Bin 0 -> 28 bytes
 samples/pbe/openssl/aes-192-cfb8.base64            |    1 +
 samples/pbe/openssl/aes-192-cfb8.raw               |    1 +
 samples/pbe/openssl/aes-192-ecb.base64             |    1 +
 samples/pbe/openssl/aes-192-ecb.raw                |    1 +
 samples/pbe/openssl/aes-192-ofb.base64             |    1 +
 samples/pbe/openssl/aes-192-ofb.raw                |    1 +
 samples/pbe/openssl/aes-256-cbc.base64             |    1 +
 samples/pbe/openssl/aes-256-cbc.raw                |    1 +
 samples/pbe/openssl/aes-256-cfb.base64             |    1 +
 samples/pbe/openssl/aes-256-cfb.raw                |    1 +
 samples/pbe/openssl/aes-256-cfb1.base64            |    1 +
 samples/pbe/openssl/aes-256-cfb1.raw               |  Bin 0 -> 28 bytes
 samples/pbe/openssl/aes-256-cfb8.base64            |    1 +
 samples/pbe/openssl/aes-256-cfb8.raw               |    1 +
 samples/pbe/openssl/aes-256-ecb.base64             |    1 +
 samples/pbe/openssl/aes-256-ecb.raw                |  Bin 0 -> 32 bytes
 samples/pbe/openssl/aes-256-ofb.base64             |    1 +
 samples/pbe/openssl/aes-256-ofb.raw                |    1 +
 samples/pbe/openssl/aes128.base64                  |    1 +
 samples/pbe/openssl/aes128.raw                     |  Bin 0 -> 32 bytes
 samples/pbe/openssl/aes192.base64                  |    1 +
 samples/pbe/openssl/aes192.raw                     |    3 +
 samples/pbe/openssl/aes256.base64                  |    1 +
 samples/pbe/openssl/aes256.raw                     |  Bin 0 -> 32 bytes
 samples/pbe/openssl/bf-cbc.base64                  |    1 +
 samples/pbe/openssl/bf-cbc.raw                     |    1 +
 samples/pbe/openssl/bf-cfb.base64                  |    1 +
 samples/pbe/openssl/bf-cfb.raw                     |  Bin 0 -> 28 bytes
 samples/pbe/openssl/bf-ecb.base64                  |    1 +
 samples/pbe/openssl/bf-ecb.raw                     |    1 +
 samples/pbe/openssl/bf-ofb.base64                  |    1 +
 samples/pbe/openssl/bf-ofb.raw                     |    1 +
 samples/pbe/openssl/bf.base64                      |    1 +
 samples/pbe/openssl/bf.raw                         |    1 +
 samples/pbe/openssl/blowfish.base64                |    1 +
 samples/pbe/openssl/blowfish.raw                   |    1 +
 samples/pbe/openssl/camellia-128-cbc.base64        |    1 +
 samples/pbe/openssl/camellia-128-cbc.raw           |    1 +
 samples/pbe/openssl/camellia-128-cfb.base64        |    1 +
 samples/pbe/openssl/camellia-128-cfb.raw           |    1 +
 samples/pbe/openssl/camellia-128-cfb1.base64       |    1 +
 samples/pbe/openssl/camellia-128-cfb1.raw          |  Bin 0 -> 28 bytes
 samples/pbe/openssl/camellia-128-cfb8.base64       |    1 +
 samples/pbe/openssl/camellia-128-cfb8.raw          |    1 +
 samples/pbe/openssl/camellia-128-ecb.base64        |    1 +
 samples/pbe/openssl/camellia-128-ecb.raw           |    1 +
 samples/pbe/openssl/camellia-128-ofb.base64        |    1 +
 samples/pbe/openssl/camellia-128-ofb.raw           |    1 +
 samples/pbe/openssl/camellia-192-cbc.base64        |    1 +
 samples/pbe/openssl/camellia-192-cbc.raw           |    1 +
 samples/pbe/openssl/camellia-192-cfb.base64        |    1 +
 samples/pbe/openssl/camellia-192-cfb.raw           |    1 +
 samples/pbe/openssl/camellia-192-cfb1.base64       |    1 +
 samples/pbe/openssl/camellia-192-cfb1.raw          |  Bin 0 -> 28 bytes
 samples/pbe/openssl/camellia-192-cfb8.base64       |    1 +
 samples/pbe/openssl/camellia-192-cfb8.raw          |    1 +
 samples/pbe/openssl/camellia-192-ecb.base64        |    1 +
 samples/pbe/openssl/camellia-192-ecb.raw           |    1 +
 samples/pbe/openssl/camellia-192-ofb.base64        |    1 +
 samples/pbe/openssl/camellia-192-ofb.raw           |  Bin 0 -> 28 bytes
 samples/pbe/openssl/camellia-256-cbc.base64        |    1 +
 samples/pbe/openssl/camellia-256-cbc.raw           |    1 +
 samples/pbe/openssl/camellia-256-cfb.base64        |    1 +
 samples/pbe/openssl/camellia-256-cfb.raw           |    2 +
 samples/pbe/openssl/camellia-256-cfb1.base64       |    1 +
 samples/pbe/openssl/camellia-256-cfb1.raw          |  Bin 0 -> 28 bytes
 samples/pbe/openssl/camellia-256-cfb8.base64       |    1 +
 samples/pbe/openssl/camellia-256-cfb8.raw          |    1 +
 samples/pbe/openssl/camellia-256-ecb.base64        |    1 +
 samples/pbe/openssl/camellia-256-ecb.raw           |    1 +
 samples/pbe/openssl/camellia-256-ofb.base64        |    1 +
 samples/pbe/openssl/camellia-256-ofb.raw           |    1 +
 samples/pbe/openssl/camellia128.base64             |    1 +
 samples/pbe/openssl/camellia128.raw                |    1 +
 samples/pbe/openssl/camellia192.base64             |    1 +
 samples/pbe/openssl/camellia192.raw                |    1 +
 samples/pbe/openssl/camellia256.base64             |    1 +
 samples/pbe/openssl/camellia256.raw                |  Bin 0 -> 32 bytes
 samples/pbe/openssl/cast-cbc.base64                |    1 +
 samples/pbe/openssl/cast-cbc.raw                   |  Bin 0 -> 32 bytes
 samples/pbe/openssl/cast.base64                    |    1 +
 samples/pbe/openssl/cast.raw                       |    1 +
 samples/pbe/openssl/cast5-cbc.base64               |    1 +
 samples/pbe/openssl/cast5-cbc.raw                  |    2 +
 samples/pbe/openssl/cast5-cfb.base64               |    1 +
 samples/pbe/openssl/cast5-cfb.raw                  |    1 +
 samples/pbe/openssl/cast5-ecb.base64               |    1 +
 samples/pbe/openssl/cast5-ecb.raw                  |    1 +
 samples/pbe/openssl/cast5-ofb.base64               |    1 +
 samples/pbe/openssl/cast5-ofb.raw                  |    2 +
 samples/pbe/openssl/des-cbc.base64                 |    1 +
 samples/pbe/openssl/des-cbc.raw                    |    1 +
 samples/pbe/openssl/des-cfb.base64                 |    1 +
 samples/pbe/openssl/des-cfb.raw                    |    1 +
 samples/pbe/openssl/des-cfb1.base64                |    1 +
 samples/pbe/openssl/des-cfb1.raw                   |  Bin 0 -> 28 bytes
 samples/pbe/openssl/des-cfb8.base64                |    1 +
 samples/pbe/openssl/des-cfb8.raw                   |    1 +
 samples/pbe/openssl/des-ecb.base64                 |    1 +
 samples/pbe/openssl/des-ecb.raw                    |  Bin 0 -> 32 bytes
 samples/pbe/openssl/des-ede-cbc.base64             |    1 +
 samples/pbe/openssl/des-ede-cbc.raw                |    1 +
 samples/pbe/openssl/des-ede-cfb.base64             |    1 +
 samples/pbe/openssl/des-ede-cfb.raw                |    1 +
 samples/pbe/openssl/des-ede-ofb.base64             |    1 +
 samples/pbe/openssl/des-ede-ofb.raw                |    1 +
 samples/pbe/openssl/des-ede.base64                 |    1 +
 samples/pbe/openssl/des-ede.raw                    |    1 +
 samples/pbe/openssl/des-ede3-cbc.base64            |    1 +
 samples/pbe/openssl/des-ede3-cbc.raw               |    2 +
 samples/pbe/openssl/des-ede3-cfb.base64            |    1 +
 samples/pbe/openssl/des-ede3-cfb.raw               |    1 +
 samples/pbe/openssl/des-ede3-ofb.base64            |    1 +
 samples/pbe/openssl/des-ede3-ofb.raw               |    1 +
 samples/pbe/openssl/des-ede3.base64                |    1 +
 samples/pbe/openssl/des-ede3.raw                   |    1 +
 samples/pbe/openssl/des-ofb.base64                 |    1 +
 samples/pbe/openssl/des-ofb.raw                    |    1 +
 samples/pbe/openssl/des.base64                     |    1 +
 samples/pbe/openssl/des.raw                        |    1 +
 samples/pbe/openssl/des3.base64                    |    1 +
 samples/pbe/openssl/des3.raw                       |    1 +
 samples/pbe/openssl/idea-cbc.base64                |    1 +
 samples/pbe/openssl/idea-cbc.raw                   |    1 +
 samples/pbe/openssl/idea-cfb.base64                |    1 +
 samples/pbe/openssl/idea-cfb.raw                   |    1 +
 samples/pbe/openssl/idea-ecb.base64                |    1 +
 samples/pbe/openssl/idea-ecb.raw                   |    1 +
 samples/pbe/openssl/idea-ofb.base64                |    1 +
 samples/pbe/openssl/idea-ofb.raw                   |    1 +
 samples/pbe/openssl/idea.base64                    |    1 +
 samples/pbe/openssl/idea.raw                       |    1 +
 samples/pbe/openssl/rc2-40-cbc.base64              |    1 +
 samples/pbe/openssl/rc2-40-cbc.raw                 |    1 +
 samples/pbe/openssl/rc2-64-cbc.base64              |    1 +
 samples/pbe/openssl/rc2-64-cbc.raw                 |    1 +
 samples/pbe/openssl/rc2-cbc.base64                 |    1 +
 samples/pbe/openssl/rc2-cbc.raw                    |    1 +
 samples/pbe/openssl/rc2-cfb.base64                 |    1 +
 samples/pbe/openssl/rc2-cfb.raw                    |    1 +
 samples/pbe/openssl/rc2-ecb.base64                 |    1 +
 samples/pbe/openssl/rc2-ecb.raw                    |    1 +
 samples/pbe/openssl/rc2-ofb.base64                 |    1 +
 samples/pbe/openssl/rc2-ofb.raw                    |    1 +
 samples/pbe/openssl/rc2.base64                     |    1 +
 samples/pbe/openssl/rc2.raw                        |    1 +
 samples/pbe/openssl/rc4-40.base64                  |    1 +
 samples/pbe/openssl/rc4-40.raw                     |    1 +
 samples/pbe/openssl/rc4.base64                     |    1 +
 samples/pbe/openssl/rc4.raw                        |    1 +
 samples/pbe/openssl/rc5-cbc.base64                 |    1 +
 samples/pbe/openssl/rc5-cbc.raw                    |    1 +
 samples/pbe/openssl/rc5-cfb.base64                 |    1 +
 samples/pbe/openssl/rc5-cfb.raw                    |    1 +
 samples/pbe/openssl/rc5-ecb.base64                 |    1 +
 samples/pbe/openssl/rc5-ecb.raw                    |    1 +
 samples/pbe/openssl/rc5-ofb.base64                 |    1 +
 samples/pbe/openssl/rc5-ofb.raw                    |    1 +
 samples/pbe/openssl/rc5.base64                     |    1 +
 samples/pbe/openssl/rc5.raw                        |    1 +
 samples/pkcs12/pkcs12_client_cert.p12              |  Bin 0 -> 4070 bytes
 samples/pkcs12/pkcs12_client_cert.pem              |   94 ++
 samples/rsa.html                                   |  114 +++
 samples/rsa/openssl_rsa_aes128_cbc.pem             |   30 +
 samples/rsa/openssl_rsa_aes128_cfb.pem             |   30 +
 samples/rsa/openssl_rsa_aes128_ecb.pem             |   30 +
 samples/rsa/openssl_rsa_aes128_ofb.pem             |   30 +
 samples/rsa/openssl_rsa_aes192_cbc.pem             |   30 +
 samples/rsa/openssl_rsa_aes192_cfb.pem             |   30 +
 samples/rsa/openssl_rsa_aes192_ecb.pem             |   30 +
 samples/rsa/openssl_rsa_aes192_ofb.pem             |   30 +
 samples/rsa/openssl_rsa_aes256_cbc.pem             |   30 +
 samples/rsa/openssl_rsa_aes256_cfb.pem             |   30 +
 samples/rsa/openssl_rsa_aes256_ecb.pem             |   30 +
 samples/rsa/openssl_rsa_aes256_ofb.pem             |   30 +
 samples/rsa/openssl_rsa_blowfish_cbc.pem           |   30 +
 samples/rsa/openssl_rsa_blowfish_cfb.pem           |   30 +
 samples/rsa/openssl_rsa_blowfish_ecb.pem           |   30 +
 samples/rsa/openssl_rsa_blowfish_ofb.pem           |   30 +
 samples/rsa/openssl_rsa_des1_cbc.pem               |   30 +
 samples/rsa/openssl_rsa_des1_cfb.pem               |   30 +
 samples/rsa/openssl_rsa_des1_ecb.pem               |   30 +
 samples/rsa/openssl_rsa_des1_ofb.pem               |   30 +
 samples/rsa/openssl_rsa_des2_cbc.pem               |   30 +
 samples/rsa/openssl_rsa_des2_cfb.pem               |   30 +
 samples/rsa/openssl_rsa_des2_ecb.pem               |   30 +
 samples/rsa/openssl_rsa_des2_ofb.pem               |   30 +
 samples/rsa/openssl_rsa_des3_cbc.pem               |   30 +
 samples/rsa/openssl_rsa_des3_cfb.pem               |   30 +
 samples/rsa/openssl_rsa_des3_ecb.pem               |   30 +
 samples/rsa/openssl_rsa_des3_ofb.pem               |   30 +
 samples/rsa/openssl_rsa_rc2_128_cbc.pem            |   30 +
 samples/rsa/openssl_rsa_rc2_128_cfb.pem            |   30 +
 samples/rsa/openssl_rsa_rc2_128_ecb.pem            |   30 +
 samples/rsa/openssl_rsa_rc2_128_ofb.pem            |   30 +
 samples/rsa/openssl_rsa_rc2_40.pem                 |   30 +
 samples/rsa/openssl_rsa_rc2_64.pem                 |   30 +
 samples/rsa/openssl_rsa_unencrypted.der            |  Bin 0 -> 1192 bytes
 samples/rsa/openssl_rsa_unencrypted.pem            |   27 +
 samples/rsa/pkcs8_rsa_unencrypted.der              |  Bin 0 -> 1218 bytes
 samples/rsa/pkcs8_rsa_unencrypted.pem              |   28 +
 samples/rsa/pkcs8v1_rsa_md2_des1.der               |  Bin 0 -> 1261 bytes
 samples/rsa/pkcs8v1_rsa_md2_des1.pem               |   29 +
 samples/rsa/pkcs8v1_rsa_md2_rc2_64.der             |  Bin 0 -> 1261 bytes
 samples/rsa/pkcs8v1_rsa_md2_rc2_64.pem             |   29 +
 samples/rsa/pkcs8v1_rsa_md5_des1.der               |  Bin 0 -> 1261 bytes
 samples/rsa/pkcs8v1_rsa_md5_des1.pem               |   29 +
 samples/rsa/pkcs8v1_rsa_md5_rc2_64.der             |  Bin 0 -> 1261 bytes
 samples/rsa/pkcs8v1_rsa_md5_rc2_64.pem             |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_des1.der              |  Bin 0 -> 1261 bytes
 samples/rsa/pkcs8v1_rsa_sha1_des1.pem              |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_des2.der              |  Bin 0 -> 1262 bytes
 samples/rsa/pkcs8v1_rsa_sha1_des2.pem              |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_des3.der              |  Bin 0 -> 1262 bytes
 samples/rsa/pkcs8v1_rsa_sha1_des3.pem              |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_rc2_128.der           |  Bin 0 -> 1262 bytes
 samples/rsa/pkcs8v1_rsa_sha1_rc2_128.pem           |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_rc2_40.der            |  Bin 0 -> 1262 bytes
 samples/rsa/pkcs8v1_rsa_sha1_rc2_40.pem            |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_rc2_64.der            |  Bin 0 -> 1261 bytes
 samples/rsa/pkcs8v1_rsa_sha1_rc2_64.pem            |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_rc4_128.der           |  Bin 0 -> 1256 bytes
 samples/rsa/pkcs8v1_rsa_sha1_rc4_128.pem           |   29 +
 samples/rsa/pkcs8v1_rsa_sha1_rc4_40.der            |  Bin 0 -> 1256 bytes
 samples/rsa/pkcs8v1_rsa_sha1_rc4_40.pem            |   29 +
 samples/rsa/pkcs8v2_rsa_aes128_cbc.der             |  Bin 0 -> 1315 bytes
 samples/rsa/pkcs8v2_rsa_aes128_cbc.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes128_cfb.der             |  Bin 0 -> 1301 bytes
 samples/rsa/pkcs8v2_rsa_aes128_cfb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes128_ecb.der             |  Bin 0 -> 1315 bytes
 samples/rsa/pkcs8v2_rsa_aes128_ecb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes128_ofb.der             |  Bin 0 -> 1301 bytes
 samples/rsa/pkcs8v2_rsa_aes128_ofb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes192_cbc.der             |  Bin 0 -> 1315 bytes
 samples/rsa/pkcs8v2_rsa_aes192_cbc.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes192_cfb.der             |  Bin 0 -> 1301 bytes
 samples/rsa/pkcs8v2_rsa_aes192_cfb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes192_ecb.der             |  Bin 0 -> 1315 bytes
 samples/rsa/pkcs8v2_rsa_aes192_ecb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes192_ofb.der             |  Bin 0 -> 1301 bytes
 samples/rsa/pkcs8v2_rsa_aes192_ofb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes256_cbc.der             |  Bin 0 -> 1315 bytes
 samples/rsa/pkcs8v2_rsa_aes256_cbc.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes256_cfb.der             |  Bin 0 -> 1301 bytes
 samples/rsa/pkcs8v2_rsa_aes256_cfb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes256_ecb.der             |  Bin 0 -> 1315 bytes
 samples/rsa/pkcs8v2_rsa_aes256_ecb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_aes256_ofb.der             |  Bin 0 -> 1301 bytes
 samples/rsa/pkcs8v2_rsa_aes256_ofb.pem             |   30 +
 samples/rsa/pkcs8v2_rsa_blowfish_cbc.der           |  Bin 0 -> 1299 bytes
 samples/rsa/pkcs8v2_rsa_blowfish_cbc.pem           |   30 +
 samples/rsa/pkcs8v2_rsa_des1_cbc.der               |  Bin 0 -> 1295 bytes
 samples/rsa/pkcs8v2_rsa_des1_cbc.pem               |   29 +
 samples/rsa/pkcs8v2_rsa_des1_cfb.der               |  Bin 0 -> 1289 bytes
 samples/rsa/pkcs8v2_rsa_des1_cfb.pem               |   29 +
 samples/rsa/pkcs8v2_rsa_des1_ecb.der               |  Bin 0 -> 1295 bytes
 samples/rsa/pkcs8v2_rsa_des1_ecb.pem               |   29 +
 samples/rsa/pkcs8v2_rsa_des1_ofb.der               |  Bin 0 -> 1289 bytes
 samples/rsa/pkcs8v2_rsa_des1_ofb.pem               |   29 +
 samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.der   |  Bin 0 -> 1295 bytes
 samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.pem   |   29 +
 samples/rsa/pkcs8v2_rsa_des3.der                   |  Bin 0 -> 1298 bytes
 samples/rsa/pkcs8v2_rsa_des3.pem                   |   30 +
 samples/rsa/pkcs8v2_rsa_rc2_128.der                |  Bin 0 -> 1306 bytes
 samples/rsa/pkcs8v2_rsa_rc2_128.pem                |   30 +
 samples/rsa/pkcs8v2_rsa_rc2_40.der                 |  Bin 0 -> 1307 bytes
 samples/rsa/pkcs8v2_rsa_rc2_40.pem                 |   30 +
 samples/rsa/pkcs8v2_rsa_rc2_64.der                 |  Bin 0 -> 1306 bytes
 samples/rsa/pkcs8v2_rsa_rc2_64.pem                 |   30 +
 samples/rsa_result.html                            |   38 +
 samples/x509/certificate.der                       |  Bin 0 -> 1092 bytes
 samples/x509/certificate.pem                       |   85 ++
 samples/x509/certificate_chain.pem                 |   79 ++
 samples/x509/certificate_root_ca.der               |  Bin 0 -> 1156 bytes
 samples/x509/certificate_root_ca.pem               |   87 ++
 samples/x509/oscp.pem                              |   22 +
 samples/x509/two-crls.pem                          |   46 +
 samples/x509/x509_foo.pem                          |   85 ++
 samples/x509/x509_foo_bar.pem                      |   88 ++
 samples/x509/x509_foo_bar_hanako.pem               |   88 ++
 samples/x509/x509_hanako.pem                       |   85 ++
 samples/x509/x509_no_cns_foo.pem                   |   87 ++
 samples/x509/x509_three_cns_foo_bar_hanako.pem     |   86 ++
 samples/x509/x509_wild_co_jp.pem                   |   85 ++
 samples/x509/x509_wild_foo.pem                     |   85 ++
 samples/x509/x509_wild_foo_bar_hanako.pem          |   88 ++
 .../contrib/ssl/AuthSSLProtocolSocketFactory.java  |  196 ++++
 .../contrib/ssl/EasySSLProtocolSocketFactory.java  |  102 ++
 .../ssl/StrictSSLProtocolSocketFactory.java        |  131 +++
 .../contrib/ssl/TrustSSLProtocolSocketFactory.java |  199 ++++
 src/java/org/apache/commons/ssl/ASN1Structure.java |  112 +++
 src/java/org/apache/commons/ssl/ASN1Util.java      |  211 ++++
 src/java/org/apache/commons/ssl/Base64.java        |  535 ++++++++++
 .../org/apache/commons/ssl/Base64InputStream.java  |  120 +++
 src/java/org/apache/commons/ssl/CRLUtil.java       |   75 ++
 src/java/org/apache/commons/ssl/Certificates.java  |  591 +++++++++++
 .../org/apache/commons/ssl/ComboInputStream.java   |   96 ++
 src/java/org/apache/commons/ssl/DerivedKey.java    |   49 +
 src/java/org/apache/commons/ssl/HostPort.java      |   55 ++
 .../org/apache/commons/ssl/HostnameVerifier.java   |  481 +++++++++
 .../org/apache/commons/ssl/HttpSecureProtocol.java |   93 ++
 src/java/org/apache/commons/ssl/Java13.java        |  290 ++++++
 .../commons/ssl/Java13KeyManagerWrapper.java       |   82 ++
 .../commons/ssl/Java13TrustManagerWrapper.java     |   99 ++
 src/java/org/apache/commons/ssl/Java14.java        |  258 +++++
 .../commons/ssl/Java14KeyManagerWrapper.java       |   82 ++
 .../commons/ssl/Java14TrustManagerWrapper.java     |  128 +++
 src/java/org/apache/commons/ssl/JavaImpl.java      |  245 +++++
 src/java/org/apache/commons/ssl/KeyMaterial.java   |  201 ++++
 .../org/apache/commons/ssl/KeyStoreBuilder.java    |  625 ++++++++++++
 src/java/org/apache/commons/ssl/LDAPSocket.java    |   83 ++
 src/java/org/apache/commons/ssl/LogHelper.java     |   87 ++
 src/java/org/apache/commons/ssl/LogWrapper.java    |  295 ++++++
 src/java/org/apache/commons/ssl/OpenSSL.java       |  720 ++++++++++++++
 src/java/org/apache/commons/ssl/OpenSSLTest.java   |   92 ++
 src/java/org/apache/commons/ssl/PBETestCreate.java |   79 ++
 src/java/org/apache/commons/ssl/PEMItem.java       |  106 ++
 src/java/org/apache/commons/ssl/PEMUtil.java       |  238 +++++
 src/java/org/apache/commons/ssl/PKCS8Key.java      | 1034 ++++++++++++++++++++
 src/java/org/apache/commons/ssl/Ping.java          |  464 +++++++++
 .../commons/ssl/ProbablyBadPasswordException.java  |   51 +
 .../commons/ssl/ProbablyNotPKCS8Exception.java     |   50 +
 .../apache/commons/ssl/RMISocketFactoryImpl.java   |  578 +++++++++++
 src/java/org/apache/commons/ssl/SSL.java           |  739 ++++++++++++++
 src/java/org/apache/commons/ssl/SSLClient.java     |  233 +++++
 src/java/org/apache/commons/ssl/SSLEchoServer.java |  142 +++
 .../org/apache/commons/ssl/SSLProxyServer.java     |  193 ++++
 src/java/org/apache/commons/ssl/SSLServer.java     |  295 ++++++
 .../apache/commons/ssl/SSLServerSocketWrapper.java |  182 ++++
 .../org/apache/commons/ssl/SSLSocketWrapper.java   |  251 +++++
 .../org/apache/commons/ssl/SSLWrapperFactory.java  |  109 +++
 .../org/apache/commons/ssl/TomcatServerXML.java    |  231 +++++
 src/java/org/apache/commons/ssl/TrustChain.java    |  206 ++++
 src/java/org/apache/commons/ssl/TrustMaterial.java |  272 +++++
 src/java/org/apache/commons/ssl/Util.java          |  403 ++++++++
 src/java/org/apache/commons/ssl/Version.java       |  197 ++++
 .../commons/ssl/X509CertificateChainBuilder.java   |  181 ++++
 .../org/apache/commons/ssl/asn1/ASN1Choice.java    |   13 +
 .../org/apache/commons/ssl/asn1/ASN1Encodable.java |   74 ++
 .../commons/ssl/asn1/ASN1EncodableVector.java      |   10 +
 .../org/apache/commons/ssl/asn1/ASN1Generator.java |   13 +
 .../apache/commons/ssl/asn1/ASN1InputStream.java   |  420 ++++++++
 src/java/org/apache/commons/ssl/asn1/ASN1Null.java |   30 +
 .../org/apache/commons/ssl/asn1/ASN1Object.java    |   34 +
 .../apache/commons/ssl/asn1/ASN1ObjectParser.java  |   55 ++
 .../apache/commons/ssl/asn1/ASN1OctetString.java   |  137 +++
 .../commons/ssl/asn1/ASN1OctetStringParser.java    |    8 +
 .../apache/commons/ssl/asn1/ASN1OutputStream.java  |   26 +
 .../org/apache/commons/ssl/asn1/ASN1Sequence.java  |  183 ++++
 .../commons/ssl/asn1/ASN1SequenceParser.java       |    9 +
 src/java/org/apache/commons/ssl/asn1/ASN1Set.java  |  281 ++++++
 .../org/apache/commons/ssl/asn1/ASN1SetParser.java |    9 +
 .../apache/commons/ssl/asn1/ASN1StreamParser.java  |  193 ++++
 .../apache/commons/ssl/asn1/ASN1TaggedObject.java  |  177 ++++
 .../commons/ssl/asn1/ASN1TaggedObjectParser.java   |   11 +
 .../ssl/asn1/BERConstructedOctetString.java        |  137 +++
 .../commons/ssl/asn1/BERConstructedSequence.java   |   29 +
 .../org/apache/commons/ssl/asn1/BERGenerator.java  |   82 ++
 .../apache/commons/ssl/asn1/BERInputStream.java    |  179 ++++
 src/java/org/apache/commons/ssl/asn1/BERNull.java  |   22 +
 .../commons/ssl/asn1/BEROctetStringGenerator.java  |   86 ++
 .../commons/ssl/asn1/BEROctetStringParser.java     |   36 +
 .../apache/commons/ssl/asn1/BEROutputStream.java   |   26 +
 .../org/apache/commons/ssl/asn1/BERSequence.java   |   44 +
 .../commons/ssl/asn1/BERSequenceGenerator.java     |   36 +
 .../apache/commons/ssl/asn1/BERSequenceParser.java |   21 +
 src/java/org/apache/commons/ssl/asn1/BERSet.java   |   51 +
 .../org/apache/commons/ssl/asn1/BERSetParser.java  |   21 +
 .../apache/commons/ssl/asn1/BERTaggedObject.java   |   94 ++
 .../commons/ssl/asn1/BERTaggedObjectParser.java    |  118 +++
 .../commons/ssl/asn1/ConstructedOctetStream.java   |   92 ++
 .../commons/ssl/asn1/DERApplicationSpecific.java   |  143 +++
 .../org/apache/commons/ssl/asn1/DERBMPString.java  |  104 ++
 .../org/apache/commons/ssl/asn1/DERBitString.java  |  245 +++++
 .../org/apache/commons/ssl/asn1/DERBoolean.java    |   96 ++
 .../commons/ssl/asn1/DERConstructedSequence.java   |   46 +
 .../apache/commons/ssl/asn1/DERConstructedSet.java |   63 ++
 .../org/apache/commons/ssl/asn1/DEREncodable.java  |    5 +
 .../commons/ssl/asn1/DEREncodableVector.java       |   31 +
 .../org/apache/commons/ssl/asn1/DEREnumerated.java |   96 ++
 .../apache/commons/ssl/asn1/DERGeneralString.java  |   75 ++
 .../commons/ssl/asn1/DERGeneralizedTime.java       |  242 +++++
 .../org/apache/commons/ssl/asn1/DERGenerator.java  |  108 ++
 .../org/apache/commons/ssl/asn1/DERIA5String.java  |  142 +++
 .../apache/commons/ssl/asn1/DERInputStream.java    |  237 +++++
 .../org/apache/commons/ssl/asn1/DERInteger.java    |  114 +++
 src/java/org/apache/commons/ssl/asn1/DERNull.java  |   20 +
 .../apache/commons/ssl/asn1/DERNumericString.java  |  148 +++
 .../org/apache/commons/ssl/asn1/DERObject.java     |   18 +
 .../commons/ssl/asn1/DERObjectIdentifier.java      |  245 +++++
 .../apache/commons/ssl/asn1/DEROctetString.java    |   23 +
 .../apache/commons/ssl/asn1/DEROutputStream.java   |   73 ++
 .../commons/ssl/asn1/DERPrintableString.java       |  172 ++++
 .../org/apache/commons/ssl/asn1/DERSequence.java   |   62 ++
 .../commons/ssl/asn1/DERSequenceGenerator.java     |   39 +
 src/java/org/apache/commons/ssl/asn1/DERSet.java   |   76 ++
 .../org/apache/commons/ssl/asn1/DERString.java     |    6 +
 .../org/apache/commons/ssl/asn1/DERT61String.java  |  103 ++
 .../apache/commons/ssl/asn1/DERTaggedObject.java   |   74 ++
 src/java/org/apache/commons/ssl/asn1/DERTags.java  |   35 +
 .../org/apache/commons/ssl/asn1/DERUTCTime.java    |  214 ++++
 .../org/apache/commons/ssl/asn1/DERUTF8String.java |   83 ++
 .../commons/ssl/asn1/DERUniversalString.java       |  100 ++
 .../org/apache/commons/ssl/asn1/DERUnknownTag.java |   71 ++
 .../apache/commons/ssl/asn1/DERVisibleString.java  |  103 ++
 .../ssl/asn1/DefiniteLengthInputStream.java        |   83 ++
 .../ssl/asn1/IndefiniteLengthInputStream.java      |   98 ++
 .../commons/ssl/asn1/LimitedInputStream.java       |   23 +
 .../org/apache/commons/ssl/asn1/OIDTokenizer.java  |   42 +
 src/java/org/apache/commons/ssl/asn1/Strings.java  |  195 ++++
 src/java/org/apache/commons/ssl/rmi/DateRMI.java   |   69 ++
 .../org/apache/commons/ssl/rmi/IntegerRMI.java     |   69 ++
 .../org/apache/commons/ssl/rmi/RemoteDate.java     |   46 +
 .../org/apache/commons/ssl/rmi/RemoteInteger.java  |   45 +
 src/java/org/apache/commons/ssl/rmi/Test.java      |  200 ++++
 src/java/org/apache/commons/ssl/util/Hex.java      |   83 ++
 .../apache/commons/ssl/util/PublicKeyDeriver.java  |   82 ++
 version.txt                                        |    3 +
 1031 files changed, 27782 insertions(+)

diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..2bb9ad2
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,176 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..2807f75
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,10 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+The PKCS12 key derivation function was developed by BouncyCastle
+(bouncycastle.org).  (Look for the "pkcs12()" method inside PKCS8.java).
+
+Some of this software was originally developed by
+Credit Union Central of British Columbia (http://www.cucbc.com/).
+The CUCBC code was licensed to the Apache Software Foundation on
+August 23rd, 2006.
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..2497e38
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,9 @@
+Jakarta Commons SSL 
+===========================
+Welcome to the SSL component of the Jakarta Commons
+project.
+
+This is not a real Jakarta Project yet.  I'm just 
+trying to copy their directory structure while I work
+on this proposal.
+
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..a5854e2
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,106 @@
+<!--
+    $ ant -p
+    Buildfile: build.xml
+
+    Main targets:
+
+    clean     Deletes class files and other generated files.
+    jar       Jars compiled java class files.
+    javac     Compiles java source code.
+    javadocs  Generates javadocs.
+
+    Default target: jar
+-->
+<project name="commons-ssl" default="jar" basedir=".">
+
+  <property name="httpclient-jar" value="commons-httpclient-3.0.jar"/>
+  <property name="log4j-jar" value="log4j-1.2.13.jar"/>
+  <property name="src" location="./src/java"/>
+  <property name="build" location="./build"/>
+  <property name="lib" location="./lib"/>
+  <property name="classes" value="${build}/classes"/>
+  <property name="jar-file" value="${ant.project.name}.jar"/>
+  <property name="javadocs" value="${build}/javadocs"/>
+  <property name="rmic.includes" value="**/*RMI.class"/>
+
+  <path id="compile-classpath">
+    <pathelement location="${classes}"/>
+    <pathelement location="${lib}/${httpclient-jar}"/>
+    <pathelement location="${lib}/${log4j-jar}"/>
+  </path>
+
+  <target name="init">
+    <tstamp>
+      <format property="date" pattern="zzz:yyyy-MM-dd/HH:mm:ss" locale="en"/>
+    </tstamp>
+    <mkdir dir="${build}"/>
+  </target>
+
+  <target name="javac" depends="init" description="Compiles java source code.">
+    <mkdir dir="${classes}"/>
+    <javac
+      includeAntRuntime="false"
+      destdir="${classes}"
+      debug="true"
+      optimize="false"
+      srcdir="${src}"
+      excludes="${javac.exclude}"
+    >
+      <classpath refid="compile-classpath"/>
+    </javac>
+    <copy todir="${classes}">
+      <fileset dir="${src}" excludes="**/*.java"/>
+    </copy>
+  </target>
+
+  <target name="rmic" depends="javac" description="Rmics java class files named "*RMI.class".">                   
+    <rmic
+      base="${classes}"
+      includes="${rmic.includes}"
+      classpathref="compile-classpath"
+    />
+  </target>
+
+  <target name="jar" depends="rmic" description="Jars compiled java class files.">
+    <jar
+      basedir="${classes}"
+      destfile="${build}/${jar-file}"
+      index="true"
+      duplicate="fail"
+    >
+      <manifest>
+        <attribute name="Built-By" value="cucbc.com"/>
+        <attribute name="Created-By" value="cucbc.com"/>
+        <attribute name="Main-Class" value="org.apache.commons.ssl.Ping"/>
+      </manifest>
+     </jar>
+  </target>
+
+  <!-- Alias for "javadocs". -->
+  <target name="javadoc" depends="javadocs"/>
+
+  <target name="javadocs" depends="init" description="Generates javadocs.">
+    <mkdir dir="${javadocs}"/>
+      <javadoc
+        sourcepath="${src}"
+        destdir="${javadocs}"
+        packagenames="*"
+        classpathref="compile-classpath"
+        access="private"
+        source="yes"
+        linksource="yes"
+      >
+        <link href="http://java.sun.com/j2se/1.5.0/docs/api/"/>
+        <link href="http://java.sun.com/j2ee/1.4/docs/api/"/>
+        <link href="http://jakarta.apache.org/commons/httpclient/apidocs/"/>
+      </javadoc>
+  </target>
+
+  <target name="clean" description="Deletes class files and other generated files.">
+    <delete dir="${build}"/>
+  </target>
+
+  <target name="all" depends="clean,jar"/>
+
+
+</project>
diff --git a/docs/.htaccess b/docs/.htaccess
new file mode 100644
index 0000000..6f20845
--- /dev/null
+++ b/docs/.htaccess
@@ -0,0 +1,3 @@
+AddType text/html .html
+AddHandler server-parsed .html
+ErrorDocument 404 /commons-ssl/404.html 
diff --git a/docs/404.html b/docs/404.html
new file mode 100644
index 0000000..92d9bad
--- /dev/null
+++ b/docs/404.html
@@ -0,0 +1,51 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - 404 Page Not Found</title>
+<style type="text/css">
+dl, h1, h2, h3, h4 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+td.v { text-align: center; }
+dt { padding: 8px 0 8px 5px; }
+dd { padding-left: 15px; }
+li { padding-bottom: 6px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="/commons-ssl/index.html">main</a> |
+<a href="/commons-ssl/ssl.html">ssl</a> |
+<a href="/commons-ssl/pkcs8.html">pkcs8</a> |
+<a href="/commons-ssl/pbe.html">pbe</a> |
+<a href="/commons-ssl/rmi.html">rmi</a> |
+<a href="/commons-ssl/utilities.html">utilities</a> |
+<a href="/commons-ssl/source.html">source</a> |
+<a href="/commons-ssl/javadocs/">javadocs</a> |
+<a href="/commons-ssl/download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>404 - Page Not Found</h2>
+<p>The path you requested is not available.</p>
+<table cellpadding="6" cellspacing="0" border="0" style="margin-top: 9px;">
+<tr><th colspan="3">Current Version (November 14th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.zip">not-yet-commons-ssl-0.3.9.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 8063831d05fc6204a7c0c23a0f86b086</td></tr>
+<tr><td>Binary only:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.jar">not-yet-commons-ssl-0.3.9.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 34996468b477e3a6c81d7feec213288b</td></tr>
+<tr><th colspan="3">Previous Version (July 4th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.zip">not-yet-commons-ssl-0.3.8.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 6c709837f9fef310a69f8659f1697c81</td></tr>
+<tr><td>Binary only:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.jar">not-yet-commons-ssl-0.3.8.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 34996468b477e3a6c81d7feec213288b</td></tr>
+</table>
+<br/><b>Warning:</b>
+ <span style="color: red; font-weight: bold;">not-yet-commons-ssl-0.3.9 should be considered to be of "Alpha" quality!
+This code probably contains bugs.  This code may have security issues.</span>
+<p>Future versions will definitely break the current API in a non-reverse compatible way.  After commons-ssl-0.5.0, though, we
+plan on always being reverse compatible with ourselves.
+<hr/>
+
+</body>
+</html>
diff --git a/docs/404.html~ b/docs/404.html~
new file mode 100644
index 0000000..e6e28ab
--- /dev/null
+++ b/docs/404.html~
@@ -0,0 +1,51 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - 404 Page Not Found</title>
+<style type="text/css">
+dl, h1, h2, h3, h4 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+td.v { text-align: center; }
+dt { padding: 8px 0 8px 5px; }
+dd { padding-left: 15px; }
+li { padding-bottom: 6px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="/commons-ssl/index.html">main</a> |
+<a href="/commons-ssl/ssl.html">ssl</a> |
+<a href="/commons-ssl/pkcs8.html">pkcs8</a> |
+<a href="/commons-ssl/pbe.html">pbe</a> |
+<a href="/commons-ssl/rmi.html">rmi</a> |
+<a href="/commons-ssl/utilities.html">utilities</a> |
+<a href="/commons-ssl/source.html">source</a> |
+<a href="/commons-ssl/javadocs/">javadocs</a> |
+<a href="/commons-ssl/download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>404 - Page Not Found</h2>
+<p>The path you requested is not available.</p>
+<table cellpadding="6" cellspacing="0" border="0" style="margin-top: 9px;">
+<tr><th colspan="3">Current Version (November 14th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.zip">not-yet-commons-ssl-0.3.9.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 6c709837f9fef310a69f8659f1697c81</td></tr>
+<tr><td>Binary only:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.jar">not-yet-commons-ssl-0.3.9.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 34996468b477e3a6c81d7feec213288b</td></tr>
+<tr><th colspan="3">Previous Version (July 4th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.zip">not-yet-commons-ssl-0.3.8.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 6c709837f9fef310a69f8659f1697c81</td></tr>
+<tr><td>Binary only:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.jar">not-yet-commons-ssl-0.3.8.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 34996468b477e3a6c81d7feec213288b</td></tr>
+</table>
+<br/><b>Warning:</b>
+ <span style="color: red; font-weight: bold;">not-yet-commons-ssl-0.3.9 should be considered to be of "Alpha" quality!
+This code probably contains bugs.  This code may have security issues.</span>
+<p>Future versions will definitely break the current API in a non-reverse compatible way.  After commons-ssl-0.5.0, though, we
+plan on always being reverse compatible with ourselves.
+<hr/>
+
+</body>
+</html>
diff --git a/docs/TrustExample.java b/docs/TrustExample.java
new file mode 100644
index 0000000..c4561de
--- /dev/null
+++ b/docs/TrustExample.java
@@ -0,0 +1,114 @@
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.ssl.HttpSecureProtocol;
+import org.apache.commons.ssl.TrustMaterial;
+
+import javax.net.ssl.SSLHandshakeException;
+import java.net.URL;
+
+/**
+ *
+ * Example of trusting certs to answer a question Sudip Shrestha posed on the
+ * httpclient-user at jakarta.apache.org mailing list, Fri 5/5/2006.
+ *
+ * @author Julius Davies
+ * @since May 5, 2006
+ */
+public class TrustExample {
+
+/*
+Microsoft IE trusts usertrust.com CA certs by default, but Java doesn't, so we need
+to tell Java to.
+
+Cert is good until 2019 !
+
+openssl x509 -in cert.pem -noout -text
+=======================================
+
+Serial Number:
+    44:be:0c:8b:50:00:24:b4:11:d3:36:2a:fe:65:0a:fd
+Signature Algorithm: sha1WithRSAEncryption
+Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+Validity
+    Not Before: Jul  9 18:10:42 1999 GMT
+    Not After : Jul  9 18:19:22 2019 GMT
+Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
+
+X509v3 extensions:
+    X509v3 Key Usage:
+        Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
+    X509v3 Basic Constraints: critical
+        CA:TRUE
+    X509v3 Subject Key Identifier:
+        A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
+    X509v3 CRL Distribution Points:
+        URI:http://crl.usertrust.com/UTN-USERFirst-Hardware.crl
+
+    X509v3 Extended Key Usage:
+        TLS Web Server Authentication, IPSec End System, IPSec Tunnel, IPSec User
+
+*/
+    private static byte[] pemCert = (
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB\n" +
+            "lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug\n" +
+            "Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho\n" +
+            "dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt\n" +
+            "SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG\n" +
+            "A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe\n" +
+            "MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v\n" +
+            "d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh\n" +
+            "cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn\n" +
+            "0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ\n" +
+            "M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a\n" +
+            "MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd\n" +
+            "oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI\n" +
+            "DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy\n" +
+            "oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD\n" +
+            "VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0\n" +
+            "dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy\n" +
+            "bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF\n" +
+            "BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM\n" +
+            "//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli\n" +
+            "CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE\n" +
+            "CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t\n" +
+            "3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS\n" +
+            "KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==\n" +
+            "-----END CERTIFICATE-----\n" ).getBytes();
+
+    public static void main( String[] args ) throws Exception
+    {
+        HttpSecureProtocol f = new HttpSecureProtocol();
+
+        // might as well trust the usual suspects:
+        f.addTrustMaterial(TrustMaterial.CACERTS);
+
+        // here's where we start trusting usertrust.com's CA:
+        f.addTrustMaterial(new TrustMaterial( pemCert ));
+
+        Protocol trustHttps = new Protocol("https", f, 443);
+        Protocol.registerProtocol("https", trustHttps);
+
+        HttpClient client = new HttpClient();
+        GetMethod httpget = new GetMethod("https://www.usertrust.com/");
+        client.executeMethod(httpget);
+        String s = httpget.getStatusLine().toString();
+        System.out.println( "HTTPClient: " + s );
+
+        // Notice that Java still can't access it.  Only HTTPClient knows
+        // to trust the cert!
+        URL u = new URL( "https://www.usertrust.com/" );
+        try
+        {
+            // This will throw an SSLHandshakeException
+            u.openStream();
+        }
+        catch ( SSLHandshakeException she )
+        {
+            System.out.println( "Java:       " + she );
+        }
+    }
+
+}
diff --git a/docs/TrustExample.java.html b/docs/TrustExample.java.html
new file mode 100644
index 0000000..ec2752d
--- /dev/null
+++ b/docs/TrustExample.java.html
@@ -0,0 +1,131 @@
+<HTML>
+<HEAD>
+<TITLE>/home/julius/dev/commons-ssl/src/java/TrustExample.java</TITLE>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+<META NAME="KEYWORDS" CONTENT="IntelliJ_IDEA_Html">
+</HEAD>
+<BODY BGCOLOR="#ffffff">
+<TABLE CELLSPACING=0 CELLPADDING=5 COLS=1 WIDTH="100%" BGCOLOR="#C0C0C0" >
+<TR><TD><CENTER>
+<FONT FACE="Arial, Helvetica" COLOR="#000000">
+/home/julius/dev/commons-ssl/src/java/TrustExample.java</FONT>
+</center></TD></TR></TABLE>
+<PRE>
+
+<FONT COLOR=0 STYLE="font-style:normal">1    </FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">2    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> org.apache.commons.httpclient.HttpClient; 
+<FONT COLOR=0 STYLE="font-style:normal">3    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> org.apache.commons.httpclient.methods.GetMethod; 
+<FONT COLOR=0 STYLE="font-style:normal">4    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> org.apache.commons.httpclient.protocol.Protocol; 
+<FONT COLOR=0 STYLE="font-style:normal">5    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> org.apache.commons.ssl.HttpSecureProtocol; 
+<FONT COLOR=0 STYLE="font-style:normal">6    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> org.apache.commons.ssl.TrustMaterial; 
+<FONT COLOR=0 STYLE="font-style:normal">7    </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">8    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> javax.net.ssl.SSLHandshakeException; 
+<FONT COLOR=0 STYLE="font-style:normal">9    </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>import</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> java.net.URL; 
+<FONT COLOR=0 STYLE="font-style:normal">10   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">11   </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>/** 
+<FONT COLOR=0 STYLE="font-style:normal">12   </FONT> * 
+<FONT COLOR=0 STYLE="font-style:normal">13   </FONT> * Example of trusting certs to answer a question Sudip Shrestha posed on the 
+<FONT COLOR=0 STYLE="font-style:normal">14   </FONT> * httpclient-user at jakarta.apache.org mailing list, Fri 5/5/2006. 
+<FONT COLOR=0 STYLE="font-style:normal">15   </FONT> * 
+<FONT COLOR=0 STYLE="font-style:normal">16   </FONT> * </I></FONT><FONT style="font-family:monospaced;" COLOR="#008000"><B>@author</B></FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I> Julius Davies 
+<FONT COLOR=0 STYLE="font-style:normal">17   </FONT> * </I></FONT><FONT style="font-family:monospaced;" COLOR="#008000"><B>@since</B></FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I> May 5, 2006 
+<FONT COLOR=0 STYLE="font-style:normal">18   </FONT> */</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">19   </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>public</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>class</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> TrustExample { 
+<FONT COLOR=0 STYLE="font-style:normal">20   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">21   </FONT></FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>/* 
+<FONT COLOR=0 STYLE="font-style:normal">22   </FONT>Microsoft IE trusts usertrust.com CA certs by default, but Java doesn't, so we need 
+<FONT COLOR=0 STYLE="font-style:normal">23   </FONT>to tell Java to. 
+<FONT COLOR=0 STYLE="font-style:normal">24   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">25   </FONT>Cert is good until 2019 ! 
+<FONT COLOR=0 STYLE="font-style:normal">26   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">27   </FONT>openssl x509 -in cert.pem -noout -text 
+<FONT COLOR=0 STYLE="font-style:normal">28   </FONT>======================================= 
+<FONT COLOR=0 STYLE="font-style:normal">29   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">30   </FONT>Serial Number: 
+<FONT COLOR=0 STYLE="font-style:normal">31   </FONT>    44:be:0c:8b:50:00:24:b4:11:d3:36:2a:fe:65:0a:fd 
+<FONT COLOR=0 STYLE="font-style:normal">32   </FONT>Signature Algorithm: sha1WithRSAEncryption 
+<FONT COLOR=0 STYLE="font-style:normal">33   </FONT>Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware 
+<FONT COLOR=0 STYLE="font-style:normal">34   </FONT>Validity 
+<FONT COLOR=0 STYLE="font-style:normal">35   </FONT>    Not Before: Jul  9 18:10:42 1999 GMT 
+<FONT COLOR=0 STYLE="font-style:normal">36   </FONT>    Not After : Jul  9 18:19:22 2019 GMT 
+<FONT COLOR=0 STYLE="font-style:normal">37   </FONT>Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware 
+<FONT COLOR=0 STYLE="font-style:normal">38   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">39   </FONT>X509v3 extensions: 
+<FONT COLOR=0 STYLE="font-style:normal">40   </FONT>    X509v3 Key Usage: 
+<FONT COLOR=0 STYLE="font-style:normal">41   </FONT>        Digital Signature, Non Repudiation, Certificate Sign, CRL Sign 
+<FONT COLOR=0 STYLE="font-style:normal">42   </FONT>    X509v3 Basic Constraints: critical 
+<FONT COLOR=0 STYLE="font-style:normal">43   </FONT>        CA:TRUE 
+<FONT COLOR=0 STYLE="font-style:normal">44   </FONT>    X509v3 Subject Key Identifier: 
+<FONT COLOR=0 STYLE="font-style:normal">45   </FONT>        A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45 
+<FONT COLOR=0 STYLE="font-style:normal">46   </FONT>    X509v3 CRL Distribution Points: 
+<FONT COLOR=0 STYLE="font-style:normal">47   </FONT>        URI:http://crl.usertrust.com/UTN-USERFirst-Hardware.crl 
+<FONT COLOR=0 STYLE="font-style:normal">48   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">49   </FONT>    X509v3 Extended Key Usage: 
+<FONT COLOR=0 STYLE="font-style:normal">50   </FONT>        TLS Web Server Authentication, IPSec End System, IPSec Tunnel, IPSec User 
+<FONT COLOR=0 STYLE="font-style:normal">51   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">52   </FONT>*/</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">53   </FONT>    </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>private</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>static</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>byte</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000">[] pemCert = ( 
+<FONT COLOR=0 STYLE="font-style:normal">54   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"-----BEGIN CERTIFICATE-----</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">55   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">56   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">57   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">58   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">59   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">60   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">61   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">62   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">63   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">64   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">65   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">66   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">67   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">68   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">69   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">70   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">71   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">72   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">73   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">74   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">75   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">76   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">77   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">78   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + 
+<FONT COLOR=0 STYLE="font-style:normal">79   </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"-----END CERTIFICATE-----</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>\n</B></FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> ).getBytes(); 
+<FONT COLOR=0 STYLE="font-style:normal">80   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">81   </FONT>    </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>public</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>static</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>void</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> main( String[] args ) </FONT>< [...]
+<FONT COLOR=0 STYLE="font-style:normal">82   </FONT>    { 
+<FONT COLOR=0 STYLE="font-style:normal">83   </FONT>        HttpSecureProtocol f = </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>new</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> HttpSecureProtocol(); 
+<FONT COLOR=0 STYLE="font-style:normal">84   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">85   </FONT>        </FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>// might as well trust the usual suspects:</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">86   </FONT>        f.addTrustMaterial(TrustMaterial.CACERTS); 
+<FONT COLOR=0 STYLE="font-style:normal">87   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">88   </FONT>        </FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>// here's where we start trusting usertrust.com's CA:</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">89   </FONT>        f.addTrustMaterial(</FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>new</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> TrustMaterial( pemCert )); 
+<FONT COLOR=0 STYLE="font-style:normal">90   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">91   </FONT>        Protocol trustHttps = </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>new</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> Protocol(</FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"https"</FONT><FONT style="font-family:monospaced;" COLOR="#000000">, f, </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">443</FONT><FONT style="font-family:monospaced;" COLOR="#000000">); 
+<FONT COLOR=0 STYLE="font-style:normal">92   </FONT>        Protocol.registerProtocol(</FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"https"</FONT><FONT style="font-family:monospaced;" COLOR="#000000">, trustHttps); 
+<FONT COLOR=0 STYLE="font-style:normal">93   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">94   </FONT>        HttpClient client = </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>new</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> HttpClient(); 
+<FONT COLOR=0 STYLE="font-style:normal">95   </FONT>        GetMethod httpget = </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>new</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> GetMethod(</FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"https://www.usertrust.com/"</FONT><FONT style="font-family:monospaced;" COLOR="#000000">); 
+<FONT COLOR=0 STYLE="font-style:normal">96   </FONT>        client.executeMethod(httpget); 
+<FONT COLOR=0 STYLE="font-style:normal">97   </FONT>        String s = httpget.getStatusLine().toString(); 
+<FONT COLOR=0 STYLE="font-style:normal">98   </FONT>        System.out.println( </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"HTTPClient: "</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + s ); 
+<FONT COLOR=0 STYLE="font-style:normal">99   </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">100  </FONT>        </FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>// Notice that Java still can't access it.  Only HTTPClient knows</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">101  </FONT>        </FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>// to trust the cert!</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">102  </FONT>        URL u = </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>new</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> URL( </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"https://www.usertrust.com/"</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> ); 
+<FONT COLOR=0 STYLE="font-style:normal">103  </FONT>        </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>try</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">104  </FONT>        { 
+<FONT COLOR=0 STYLE="font-style:normal">105  </FONT>            </FONT><FONT style="font-family:monospaced;" COLOR="#008000"><I>// This will throw an SSLHandshakeException</I></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> 
+<FONT COLOR=0 STYLE="font-style:normal">106  </FONT>            u.openStream(); 
+<FONT COLOR=0 STYLE="font-style:normal">107  </FONT>        } 
+<FONT COLOR=0 STYLE="font-style:normal">108  </FONT>        </FONT><FONT style="font-family:monospaced;" COLOR="#000080"><B>catch</B></FONT><FONT style="font-family:monospaced;" COLOR="#000000"> ( SSLHandshakeException she ) 
+<FONT COLOR=0 STYLE="font-style:normal">109  </FONT>        { 
+<FONT COLOR=0 STYLE="font-style:normal">110  </FONT>            System.out.println( </FONT><FONT style="font-family:monospaced;" COLOR="#0000ff">"Java:       "</FONT><FONT style="font-family:monospaced;" COLOR="#000000"> + she ); 
+<FONT COLOR=0 STYLE="font-style:normal">111  </FONT>        } 
+<FONT COLOR=0 STYLE="font-style:normal">112  </FONT>    } 
+<FONT COLOR=0 STYLE="font-style:normal">113  </FONT> 
+<FONT COLOR=0 STYLE="font-style:normal">114  </FONT>} 
+<FONT COLOR=0 STYLE="font-style:normal">115  </FONT></FONT></PRE>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/docs/about.html b/docs/about.html
new file mode 100644
index 0000000..3b61f22
--- /dev/null
+++ b/docs/about.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Author" content="Julius Davies">
+<title>About Not-Yet-Commons-SSL</title>
+<style type="text/css">
+dl, h1, h2, h3, h4 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl, a.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+.nav a.hl { color: white; }
+dt { padding: 8px 0 8px 5px; }
+li { padding-bottom: 6px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html" class="hl">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>About Not-Yet-Commons-SSL</h2>
+
+<h4 style="margin-top: 1em;">5 Design Goals:</h4>
+<ol>
+<li  style="margin-top: 6px;"><b>Make SSL and Java Easier.</b>  Ever wanted to work with self-signed
+certificates in your Java application in a secure fashion?  Ever wanted to use more than one client
+certificte in a single running JVM?  You can edit your <code>$JAVA_HOME/jre/lib/security/cacerts</code>
+file, and you can invoke Java with <code>-Djavax.net.ssl.keyStore=/path/to/keystore</code>.  Both of
+these approaches are great at first, but they don't scale well.  Do you really want to pollute every
+SSL socket in your JVM (HTTP, LDAP, JDBC, RMI, etc...) with those system-wide changes?  Commons-SSL let's you
+control the SSL options you need in an natural way for each SSLSocketFactory, and those options
+won't bleed into the rest of your system.</li>
+<li  style="margin-top: 6px;"><b>Improve Security.</b>
+<a href="http://en.wikipedia.org/wiki/Certificate_revocation_list">CRL</a> checking turned on by default.
+We hope to add support for
+<a href="http://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol">OCSP</a> soon!
+It's obnoxious to have to download CRL files around 500KB each from Thawte and Verisign every 24 hours.
+OCSP improves on that.</li>
+<li  style="margin-top: 6px;"><b>Improve Flexibility.</b>  Checking hostnames, expirations, CRL's, and many
+other options can be enabled/disabled for each SSLSocketFactory created.</li>
+<li style="margin-top: 6px;"><b>Support more file formats, and support these formats more robustly.</b>
+<ul>
+<li>commons-ssl supports over <a href="samples/rsa_result.html">50 formats</a> of PKCS8 and OpenSSL Encrypted Private Keys in PEM or DER</li>
+<li>X.509 Certificates can be PEM or DER encoded.  Can also come in PKCS7 chains.  (To be fair, Java always supported this.)</li>
+<li>PKCS12 files can be in <a href="samples/pkcs12/pkcs12_client_cert.pem">PEM</a> (as created by <code>openssl pkcs12</code>).</li>
+<li>Parsing of Base64-PEM is more tolerant of extra whitespace or comments, especially outside the Base64 sections:
+<pre style="padding-left: 100px;">any comments or whitespace up here are ignored
+
+-----BEGIN TYPE-----
+[...base64....]
+-----END TYPE-----
+
+any comments or whitespace down here are also ignored</pre></li></ul></li>
+<li><b>Automatically detect type of KeyMaterial or TrustMaterial.</b>  Consumer does not need to know
+whether keystore is PKCS12 or JKS.  They just need to know the password to decrypt the private key.</li>
+</ol>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/download.html b/docs/download.html
new file mode 100644
index 0000000..9eb706b
--- /dev/null
+++ b/docs/download.html
@@ -0,0 +1,229 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - Downloads, Features, Future Directions</title>
+<style type="text/css">
+dl, h1, h2, h3, h4 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+td.v { text-align: center; }
+dt { padding: 8px 0 8px 5px; }
+dd { padding-left: 15px; }
+li { padding-bottom: 6px; }
+tr.released td, tr.released th { background-color: yellow; font-weight: bold; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<span class="hl" href="download.html">download</span>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Download Not-Yet-Commons-SSL!</em></h2>
+<p>Not-Yet-Commons-SSL currently has NO affiliation with the <a href="http://apache.org/">Apache Software Foundation</a> (apache.org), but we're hoping
+to start <a href="http://incubator.apache.org/incubation/Incubation_Policy.html">Incubation</a> one day.
+<table cellpadding="6" cellspacing="0" border="0" style="margin-top: 9px;">
+<tr><th colspan="3">Current Version (November 14th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.zip">not-yet-commons-ssl-0.3.9.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 8063831d05fc6204a7c0c23a0f86b086</td></tr>
+<tr><td>Binary only:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.jar">not-yet-commons-ssl-0.3.9.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: </td></tr>
+<tr><th colspan="3">Previous Version (July 4th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.zip">not-yet-commons-ssl-0.3.8.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 6c709837f9fef310a69f8659f1697c81</td></tr>
+<tr><td>Binary only:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.jar">not-yet-commons-ssl-0.3.8.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 34996468b477e3a6c81d7feec213288b</td></tr>
+</table>
+<br/><b>Warning:</b>
+ <span style="color: red; font-weight: bold;">not-yet-commons-ssl-0.3.9 should be considered to be of "Alpha" quality!
+This code probably contains bugs.  This code may have security issues.</span>
+<p>Future versions will definitely break the current API in a non-reverse compatible way.  After commons-ssl-0.5.0, though, we
+plan on always being reverse compatible with ourselves.
+<hr/>
+<h3>Features as of not-yet-commons-ssl-0.3.9:</h3>
+<dl>
+<dt>1. <a href="pbe.html">PBE</a> is now Compatible with <code>openssl enc -K [key] -iv [IV]</code>.</dt>
+<dd>People were asking for this.  See the PBE page for more details.</dd>
+<dt>2. DES2 with PBE was broken.</dt>
+<dd>Fixed.</dd>
+<dt>3. directory.apache.org didn't write the ASN.1 code.  BouncyCastle did.</dt>
+<dd>Now using latest ASN.1 parsing code from BC, and attributing it properly.</dd>
+<dt>4. The "ping" utility has a few more options.</dt>
+<dd>For those who need more than just a "HEAD /" request.  You can also set the HTTP host header,
+independant of the target host/ip.</dd>
+</dl>
+<br/>
+<h3>Features as of not-yet-commons-ssl-0.3.8:</h3>
+<dl>
+<dt>1. useDefaultJavaCiphers() actually works now.</dt>
+<dd>When you want to allow 40 bit, 56 bit, and MD5 based SSL ciphers, use this.  It was 99% functional in 0.3.7, but there was a
+rare situation where setting ciphers was causing SSL handshake errors.</dd>
+<dt>2. <a href="pbe.html">PBE</a> (password-based-encryption) improved.</dt>
+<dd>PBE now has its own <a href="pbe.html">HTML page</a>.  Support for all of OpenSSL's PBE ciphers implemented and tested, including
+IDEA and RC5.  (DES-X might work, but couldn't find a JCE provider that supported it).  Threw in support for some
+additional BouncyCastle ciphers even though OpenSSL doesn't support them (cast6, gost28147, rc6, seed, serpent,
+skipjack, tea, twofish, xtea).  Around <a href="samples/pbe/">650 test files</a> created to make sure PBE is working properly.
+</dd>
+<dt>3. PBE API changed on <a href="javadocs/org/apache/commons/ssl/OpenSSL.html#encrypt(java.lang.String,%20char[],%20java.io.InputStream)">OpenSSL.encrypt()</a> and <a href="javadocs/org/apache/commons/ssl/OpenSSL.html#decrypt(java.lang.String,%20char[],%20java.io.InputStream)">OpenSSL.decrypt()</a>.</dt>
+<dd>The password is now char[] instead of byte[] (sorry!).  Encrypt/decrypt on byte[] introduced.  Encrypt/decrypt on InputStream
+is still available, and is properly streamed so that even extremely large files can be encrypted/decrypted.</dd>
+</dl>
+<br/>
+<h3>Features as of not-yet-commons-ssl-0.3.7:</h3>
+<dl>
+<dt>1. useStrongCiphers() used by default.</dt>
+<dd>40 bit and 56 bit ciphers are now disabled by default.  To turn them back on call useDefaultJavaCiphers().</dd>
+<dt>2. addAllowedName() adds some flexibility to the CN verification.</dt>
+<dd>
+Here's a code example using "cucbc.com" to connect, but anticipating "www.cucbc.com" in the server's certificate:
+<pre>
+SSLClient client = new SSLClient();
+client.addAllowedName( "www.cucbc.com" );
+Socket s = client.createSocket( "cucbc.com", 443 );
+</pre>
+This technique is also useful if you don't want to use DNS, and want to
+connect using the IP address.
+</dd>
+<dt>3. SSLServer can re-use a Tomcat-8443 private key if running from inside Tomcat.</dt>
+<dd>
+<pre>
+SSLClient server = new SSLServer();
+server.useTomcatSSLMaterial();
+</pre>
+</dd>
+<dt>4. RMI-SSL support improved.</dt>
+<dd>Attempts to re-use the Tomcat-8443 private key for all RMI SSL Server sockets.
+Anonymous server-sockets (port 0) will always be set to port 31099.  Analyzes the
+server certificate CN field and tries to set "java.rmi.server.hostname" to something
+compatible with that.  Probably the only free implementation around that does a good
+job on the hostname verification!
+</dd>
+<dt>5. KeyMaterial constructor blows up earlier.</dt>
+<dd>If a JKS or PKCS12 file is provided that isn't going to work (e.g. no private keys),
+the KeyMaterial constructor throws an exception right away.</dd>
+<dt>6. getSSLContext() now available to help inter-op with Java 5 SSL-NIO libraries.</dt>
+<dd>Oleg has been working hard on SSL-NIO for the Apache httpcomponents library.  Go
+check it out!</dd>
+<dt>7. Fixed bug where SSLClient couldn't be used with javax.net.ssl.HttpsURLConnection
+on Java 1.4.x</dt>
+<dd>I was wrapping the SSLSocket, but Java 1.4.x guards against that inside HttpsURLConnection
+and throws this exciting exception:
+<pre>
+java.lang.RuntimeException: Export restriction: this JSSE implementation is non-pluggable.
+  at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.checkCreate(DashoA6275)
+  at sun.net.www.protocol.https.HttpsClient.afterConnect(DashoA6275)
+  at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(DashoA6275)
+  at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:560)
+  at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(DashoA6275)
+</pre>
+Silly Java - I'm still using <em>your</em> JSSE implementation, I'm just wrapping it!
+</dd>
+</dl>
+<br/>
+<h3>Features as of not-yet-commons-ssl-0.3.4:</h3>
+<dl>
+<dt>1.  <code>"javax.net.ssl.keyStore"</code> and <code>"javax.net.ssl.trustStore"</code></dt>
+<dd>SSLClient and SSLServer now set their default TrustMaterial and KeyMaterial from these
+ system properties if they are present.</dd>
+<dt>2.  <code>ssl.setCheckCRL( true/false )</code> <em>Note: <a href="http://en.wikipedia.org/wiki/Certificate_revocation_list">CRL</a> is an abbreviation for "Certificate Revocation List"</em></dt>
+<dd>Set to <code>true</code> by default.  If you're using SSLClient, then the remote
+server's certificate chain is checked.  If you're using SSLServer, CRL checking is ignored <em>unless</em>
+client certificates are presented.  Commons-SSL tries to perform the CRL check against each certificate in
+the chain, but we're not sure if we always know the entire chain.
+<p><em>Implementation note:</em>
+To reduce memory consumption all CRL's are saved to disk using
+<code>File.createTempFile()</code> and <code>File.deleteOnExit()</code>.
+CRL's are re-downloaded every 24 hours.  To reduce disk IO
+the "pass/fail" result of a CRL check for a given X.509 Certificate is cached using the 20 byte SHA1 hash of the
+certificate as the key.  The cached "pass" result is discarded every 24 hours.  The cached "fail" result is retained 
+until the JVM restarts.
+</p>
+</dd>
+<dt>3.  <code>ssl.setCheckExpiry( true/false )</code></dt>
+<dd>Certificate expiry checking can be turned off.  Turned on by default.  For Java 1.4 and newer we're
+intercepting the CertificateException thrown by the TrustManager.  But we still implemented our own
+expiry checking because Java 1.3 doesn't check expiry.  We check every certificate in
+the chain, but we're not sure if we always know the entire chain.</dd>
+<dt>4.  <code>ssl.setCheckHostname( true/false )</code></dt>
+<dd>Certificate hostname checking improved.  Turned on by default for SSLClient, but turned off by
+default for SSLServer.  If turned on for SSLServer, only applied to client certificates by checking
+against a reverse DNS lookup of the client's IP address.  Turning on for SSLServer will probably be
+quite rare.  We imagine that applications (such as Tomcat) will pass the client chain back up into
+the business layer where people can code in any kind of validation logic they like.  But we put
+it in anyway to keep things consistent.
+<p>Support added for certificates with wildcards in the CN field 
+(e.g. <a href="https://www.credential.com/">*.credential.com</a>). 
+Java already had this, to be fair.  We broke it
+by accident!
+<pre style="font-style: 90%; padding: 0 30px;">
+s: CN=*.credential.com, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/cps (c)05,
+   OU=businessprofile.geotrust.com/get.jsp?GT27402892, O=*.credential.com, C=CA
+i: CN=Equifax Secure Global eBusiness CA-1, O=Equifax Secure Inc., C=US
+</pre>
+</p>
+</dd>
+<dt>5.  PKCS8 support.</dt>
+<dd>Support for OpenSSL "Traditional" and PKCS8 encrypted private keys added.
+Private keys can be RSA or DSA.  See our <a href="pkcs8.html">pkcs8 page</a> for more details.</dt>
+<dt>6.  New Utility: "<code>KeyStoreBuilder</code>"</dt>
+<dd>Command line utility converts an OpenSSL pair (private key + certificate) into a Java Keystore ("JKS")
+file.  To see the command-line options, visit our <a href="utilities.html">utilities page</a>, or just run:
+<pre style="font-style: 90%; padding: 0 30px;">
+java -cp commons-ssl-0.3.4.jar org.apache.commons.ssl.KeyStoreBuilder
+</pre></dd>
+</dl>
+
+<hr/>
+<h3><a name="roadmap">Road Map For Future Versions</a></h3>
+<p>0.3.10 - 0.3.11 are just some feature ideas.  They might not be feasible.  <b style="background-color: yellow;">0.3.9 is the current version.</b></p>
+<table cellspacing="0" cellpadding="4" border="1">
+<tr><th>Version</th><th>Release Date?</th><th>Description</th></tr>
+<tr><td class="v">0.3.4</td><td class="v">Nov 2006</td><td>90% feature complete.  Probably contains some bugs.</td></tr>
+<tr><td class="v">0.3.5</td><td class="v">Dec 2006</td><td>PKCS8Key constructor is public now.  Whoops.  Hostname verification
+knows about more than just CN's now - also checks subjectAlts in the server's certificate.</td></tr>
+<tr><td class="v">0.3.6</td><td class="v">Jan 2007</td><td>Fixed Java 1.4 bug with HttpsURLConnection.</td></tr>
+<tr><td class="v">0.3.7</td><td class="v">Feb 2007</td><td>40 bit and 56 bit ciphers disabled by default.  RMI-SSL improved.  getSSLContext() added.  Various other improvements.</td></tr>
+<tr class="v"><td class="v">0.3.8</td><td class="v">Nov 2007</td><td>PBE (password-based-encryption) formally introduced and improved.  40 bit and 56 bit ciphers still disabled by default, but working better when re-enabled.</td></tr>
+<tr class="released"><td class="v">0.3.9</td><td class="v">May 2008</td><td>Some PBE fixes.  Using latest ASN.1 code from BouncyCastle.</td></tr>
+<tr class="unreleased"><td class="v">0.3.10</td><td class="v">May 2008</td><td>
+<p>
+Socket monitoring.  Make it easier for long-running server applications to warn
+about impending certificate expiries.
+</p>
+<p>
+<a href="http://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol">OCSP</a> - Online Certificate Status Protocol
+</p>
+<p>
+NotQuiteSoEasySSLProtocolSocketFactory will trust any server The First Time, and store that server's cert on disk for future accesses.
+</p>
+</td></tr>
+<tr><td class="v">0.3.11</td><td class="v">Jun 2008</td><td><code>TrustMaterial.setAutoReload( true / false )</code>, and <code>KeyMaterial.setAutoReload( true / false )</code>,
+but only if no password, or "changeit" was provided.  (Question:  should this "reload" tear down all open sockets?).
+</td></tr>
+<tr><td class="v">0.4.0</td><td class="v">Jul 2008</td><td>Non-public code (protected, private, etc) moved into a separate "impl" package where possible.</td></tr>
+<tr><td class="v">0.5.0</td><td class="v">Aug 2008</td><td>API froven.  All future versions must be reverse-compatible with 0.5.0 (except for any parts of 0.5.0 later found to be insecure).</td></tr>
+<tr><td class="v">0.7.0</td><td class="v">Nov 2008</td><td>JavaDocs written for all public methods and classes.</td></tr>
+<tr><td class="v">0.7.5</td><td class="v">Mar 2009</td><td>JUnit tests written for all classes.</td></tr>
+<tr><td class="v">0.9.0</td><td class="v">May 2009</td><td>First BETA release.  JUnit tests passing on all targetted platforms:
+<ol>
+<li>Intel/AMD: (Sun, IBM, BEA) x (Linux, Mac, Windows) x (1.3, 1.4, 5, 6, 7)</li>
+<li>All of the above with and without BouncyCastle.</li>
+<li>PowerPC:  Mac OS X 10.4, 10.5</li>
+<li>Linux: Latest GCJ, Kaffe, and Blackdown releases.  BouncyCastle added if necessary to get tests to pass.</li>
+<li>Anyone got an IBM mainframe we can test on?</li>
+</td></tr>
+<tr><td class="v">0.9.1 - 0.9.9</td><td class="v">Aug 2009</td><td>Bug fixes.</td></tr>
+<tr><td class="v">1.0.0</td><td class="v">Jan 2010</td><td>Development mostly stops.</td></tr>
+</table>
+<p>The problem we're solving with Commons-SSL
+is quite small, so I don't see any reason to ever go beyond 1.0.0, except for fixing bugs.</p>
+</body>
+</html>
diff --git a/docs/download.html~ b/docs/download.html~
new file mode 100644
index 0000000..9eb706b
--- /dev/null
+++ b/docs/download.html~
@@ -0,0 +1,229 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - Downloads, Features, Future Directions</title>
+<style type="text/css">
+dl, h1, h2, h3, h4 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+td.v { text-align: center; }
+dt { padding: 8px 0 8px 5px; }
+dd { padding-left: 15px; }
+li { padding-bottom: 6px; }
+tr.released td, tr.released th { background-color: yellow; font-weight: bold; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<span class="hl" href="download.html">download</span>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Download Not-Yet-Commons-SSL!</em></h2>
+<p>Not-Yet-Commons-SSL currently has NO affiliation with the <a href="http://apache.org/">Apache Software Foundation</a> (apache.org), but we're hoping
+to start <a href="http://incubator.apache.org/incubation/Incubation_Policy.html">Incubation</a> one day.
+<table cellpadding="6" cellspacing="0" border="0" style="margin-top: 9px;">
+<tr><th colspan="3">Current Version (November 14th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.zip">not-yet-commons-ssl-0.3.9.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 8063831d05fc6204a7c0c23a0f86b086</td></tr>
+<tr><td>Binary only:</td><td><a href="/commons-ssl/not-yet-commons-ssl-0.3.9.jar">not-yet-commons-ssl-0.3.9.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: </td></tr>
+<tr><th colspan="3">Previous Version (July 4th, 2007):</th></tr>
+<tr><td>Full source:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.zip">not-yet-commons-ssl-0.3.8.zip</a></td><td>2.3MB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 6c709837f9fef310a69f8659f1697c81</td></tr>
+<tr><td>Binary only:</td><td><a href="/not-yet-commons-ssl-0.3.8/not-yet-commons-ssl-0.3.8.jar">not-yet-commons-ssl-0.3.8.jar</a></td><td>189KB</td><td><span style="color: red;">Alpha</span></td><td>MD5: 34996468b477e3a6c81d7feec213288b</td></tr>
+</table>
+<br/><b>Warning:</b>
+ <span style="color: red; font-weight: bold;">not-yet-commons-ssl-0.3.9 should be considered to be of "Alpha" quality!
+This code probably contains bugs.  This code may have security issues.</span>
+<p>Future versions will definitely break the current API in a non-reverse compatible way.  After commons-ssl-0.5.0, though, we
+plan on always being reverse compatible with ourselves.
+<hr/>
+<h3>Features as of not-yet-commons-ssl-0.3.9:</h3>
+<dl>
+<dt>1. <a href="pbe.html">PBE</a> is now Compatible with <code>openssl enc -K [key] -iv [IV]</code>.</dt>
+<dd>People were asking for this.  See the PBE page for more details.</dd>
+<dt>2. DES2 with PBE was broken.</dt>
+<dd>Fixed.</dd>
+<dt>3. directory.apache.org didn't write the ASN.1 code.  BouncyCastle did.</dt>
+<dd>Now using latest ASN.1 parsing code from BC, and attributing it properly.</dd>
+<dt>4. The "ping" utility has a few more options.</dt>
+<dd>For those who need more than just a "HEAD /" request.  You can also set the HTTP host header,
+independant of the target host/ip.</dd>
+</dl>
+<br/>
+<h3>Features as of not-yet-commons-ssl-0.3.8:</h3>
+<dl>
+<dt>1. useDefaultJavaCiphers() actually works now.</dt>
+<dd>When you want to allow 40 bit, 56 bit, and MD5 based SSL ciphers, use this.  It was 99% functional in 0.3.7, but there was a
+rare situation where setting ciphers was causing SSL handshake errors.</dd>
+<dt>2. <a href="pbe.html">PBE</a> (password-based-encryption) improved.</dt>
+<dd>PBE now has its own <a href="pbe.html">HTML page</a>.  Support for all of OpenSSL's PBE ciphers implemented and tested, including
+IDEA and RC5.  (DES-X might work, but couldn't find a JCE provider that supported it).  Threw in support for some
+additional BouncyCastle ciphers even though OpenSSL doesn't support them (cast6, gost28147, rc6, seed, serpent,
+skipjack, tea, twofish, xtea).  Around <a href="samples/pbe/">650 test files</a> created to make sure PBE is working properly.
+</dd>
+<dt>3. PBE API changed on <a href="javadocs/org/apache/commons/ssl/OpenSSL.html#encrypt(java.lang.String,%20char[],%20java.io.InputStream)">OpenSSL.encrypt()</a> and <a href="javadocs/org/apache/commons/ssl/OpenSSL.html#decrypt(java.lang.String,%20char[],%20java.io.InputStream)">OpenSSL.decrypt()</a>.</dt>
+<dd>The password is now char[] instead of byte[] (sorry!).  Encrypt/decrypt on byte[] introduced.  Encrypt/decrypt on InputStream
+is still available, and is properly streamed so that even extremely large files can be encrypted/decrypted.</dd>
+</dl>
+<br/>
+<h3>Features as of not-yet-commons-ssl-0.3.7:</h3>
+<dl>
+<dt>1. useStrongCiphers() used by default.</dt>
+<dd>40 bit and 56 bit ciphers are now disabled by default.  To turn them back on call useDefaultJavaCiphers().</dd>
+<dt>2. addAllowedName() adds some flexibility to the CN verification.</dt>
+<dd>
+Here's a code example using "cucbc.com" to connect, but anticipating "www.cucbc.com" in the server's certificate:
+<pre>
+SSLClient client = new SSLClient();
+client.addAllowedName( "www.cucbc.com" );
+Socket s = client.createSocket( "cucbc.com", 443 );
+</pre>
+This technique is also useful if you don't want to use DNS, and want to
+connect using the IP address.
+</dd>
+<dt>3. SSLServer can re-use a Tomcat-8443 private key if running from inside Tomcat.</dt>
+<dd>
+<pre>
+SSLClient server = new SSLServer();
+server.useTomcatSSLMaterial();
+</pre>
+</dd>
+<dt>4. RMI-SSL support improved.</dt>
+<dd>Attempts to re-use the Tomcat-8443 private key for all RMI SSL Server sockets.
+Anonymous server-sockets (port 0) will always be set to port 31099.  Analyzes the
+server certificate CN field and tries to set "java.rmi.server.hostname" to something
+compatible with that.  Probably the only free implementation around that does a good
+job on the hostname verification!
+</dd>
+<dt>5. KeyMaterial constructor blows up earlier.</dt>
+<dd>If a JKS or PKCS12 file is provided that isn't going to work (e.g. no private keys),
+the KeyMaterial constructor throws an exception right away.</dd>
+<dt>6. getSSLContext() now available to help inter-op with Java 5 SSL-NIO libraries.</dt>
+<dd>Oleg has been working hard on SSL-NIO for the Apache httpcomponents library.  Go
+check it out!</dd>
+<dt>7. Fixed bug where SSLClient couldn't be used with javax.net.ssl.HttpsURLConnection
+on Java 1.4.x</dt>
+<dd>I was wrapping the SSLSocket, but Java 1.4.x guards against that inside HttpsURLConnection
+and throws this exciting exception:
+<pre>
+java.lang.RuntimeException: Export restriction: this JSSE implementation is non-pluggable.
+  at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.checkCreate(DashoA6275)
+  at sun.net.www.protocol.https.HttpsClient.afterConnect(DashoA6275)
+  at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(DashoA6275)
+  at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:560)
+  at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(DashoA6275)
+</pre>
+Silly Java - I'm still using <em>your</em> JSSE implementation, I'm just wrapping it!
+</dd>
+</dl>
+<br/>
+<h3>Features as of not-yet-commons-ssl-0.3.4:</h3>
+<dl>
+<dt>1.  <code>"javax.net.ssl.keyStore"</code> and <code>"javax.net.ssl.trustStore"</code></dt>
+<dd>SSLClient and SSLServer now set their default TrustMaterial and KeyMaterial from these
+ system properties if they are present.</dd>
+<dt>2.  <code>ssl.setCheckCRL( true/false )</code> <em>Note: <a href="http://en.wikipedia.org/wiki/Certificate_revocation_list">CRL</a> is an abbreviation for "Certificate Revocation List"</em></dt>
+<dd>Set to <code>true</code> by default.  If you're using SSLClient, then the remote
+server's certificate chain is checked.  If you're using SSLServer, CRL checking is ignored <em>unless</em>
+client certificates are presented.  Commons-SSL tries to perform the CRL check against each certificate in
+the chain, but we're not sure if we always know the entire chain.
+<p><em>Implementation note:</em>
+To reduce memory consumption all CRL's are saved to disk using
+<code>File.createTempFile()</code> and <code>File.deleteOnExit()</code>.
+CRL's are re-downloaded every 24 hours.  To reduce disk IO
+the "pass/fail" result of a CRL check for a given X.509 Certificate is cached using the 20 byte SHA1 hash of the
+certificate as the key.  The cached "pass" result is discarded every 24 hours.  The cached "fail" result is retained 
+until the JVM restarts.
+</p>
+</dd>
+<dt>3.  <code>ssl.setCheckExpiry( true/false )</code></dt>
+<dd>Certificate expiry checking can be turned off.  Turned on by default.  For Java 1.4 and newer we're
+intercepting the CertificateException thrown by the TrustManager.  But we still implemented our own
+expiry checking because Java 1.3 doesn't check expiry.  We check every certificate in
+the chain, but we're not sure if we always know the entire chain.</dd>
+<dt>4.  <code>ssl.setCheckHostname( true/false )</code></dt>
+<dd>Certificate hostname checking improved.  Turned on by default for SSLClient, but turned off by
+default for SSLServer.  If turned on for SSLServer, only applied to client certificates by checking
+against a reverse DNS lookup of the client's IP address.  Turning on for SSLServer will probably be
+quite rare.  We imagine that applications (such as Tomcat) will pass the client chain back up into
+the business layer where people can code in any kind of validation logic they like.  But we put
+it in anyway to keep things consistent.
+<p>Support added for certificates with wildcards in the CN field 
+(e.g. <a href="https://www.credential.com/">*.credential.com</a>). 
+Java already had this, to be fair.  We broke it
+by accident!
+<pre style="font-style: 90%; padding: 0 30px;">
+s: CN=*.credential.com, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/cps (c)05,
+   OU=businessprofile.geotrust.com/get.jsp?GT27402892, O=*.credential.com, C=CA
+i: CN=Equifax Secure Global eBusiness CA-1, O=Equifax Secure Inc., C=US
+</pre>
+</p>
+</dd>
+<dt>5.  PKCS8 support.</dt>
+<dd>Support for OpenSSL "Traditional" and PKCS8 encrypted private keys added.
+Private keys can be RSA or DSA.  See our <a href="pkcs8.html">pkcs8 page</a> for more details.</dt>
+<dt>6.  New Utility: "<code>KeyStoreBuilder</code>"</dt>
+<dd>Command line utility converts an OpenSSL pair (private key + certificate) into a Java Keystore ("JKS")
+file.  To see the command-line options, visit our <a href="utilities.html">utilities page</a>, or just run:
+<pre style="font-style: 90%; padding: 0 30px;">
+java -cp commons-ssl-0.3.4.jar org.apache.commons.ssl.KeyStoreBuilder
+</pre></dd>
+</dl>
+
+<hr/>
+<h3><a name="roadmap">Road Map For Future Versions</a></h3>
+<p>0.3.10 - 0.3.11 are just some feature ideas.  They might not be feasible.  <b style="background-color: yellow;">0.3.9 is the current version.</b></p>
+<table cellspacing="0" cellpadding="4" border="1">
+<tr><th>Version</th><th>Release Date?</th><th>Description</th></tr>
+<tr><td class="v">0.3.4</td><td class="v">Nov 2006</td><td>90% feature complete.  Probably contains some bugs.</td></tr>
+<tr><td class="v">0.3.5</td><td class="v">Dec 2006</td><td>PKCS8Key constructor is public now.  Whoops.  Hostname verification
+knows about more than just CN's now - also checks subjectAlts in the server's certificate.</td></tr>
+<tr><td class="v">0.3.6</td><td class="v">Jan 2007</td><td>Fixed Java 1.4 bug with HttpsURLConnection.</td></tr>
+<tr><td class="v">0.3.7</td><td class="v">Feb 2007</td><td>40 bit and 56 bit ciphers disabled by default.  RMI-SSL improved.  getSSLContext() added.  Various other improvements.</td></tr>
+<tr class="v"><td class="v">0.3.8</td><td class="v">Nov 2007</td><td>PBE (password-based-encryption) formally introduced and improved.  40 bit and 56 bit ciphers still disabled by default, but working better when re-enabled.</td></tr>
+<tr class="released"><td class="v">0.3.9</td><td class="v">May 2008</td><td>Some PBE fixes.  Using latest ASN.1 code from BouncyCastle.</td></tr>
+<tr class="unreleased"><td class="v">0.3.10</td><td class="v">May 2008</td><td>
+<p>
+Socket monitoring.  Make it easier for long-running server applications to warn
+about impending certificate expiries.
+</p>
+<p>
+<a href="http://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol">OCSP</a> - Online Certificate Status Protocol
+</p>
+<p>
+NotQuiteSoEasySSLProtocolSocketFactory will trust any server The First Time, and store that server's cert on disk for future accesses.
+</p>
+</td></tr>
+<tr><td class="v">0.3.11</td><td class="v">Jun 2008</td><td><code>TrustMaterial.setAutoReload( true / false )</code>, and <code>KeyMaterial.setAutoReload( true / false )</code>,
+but only if no password, or "changeit" was provided.  (Question:  should this "reload" tear down all open sockets?).
+</td></tr>
+<tr><td class="v">0.4.0</td><td class="v">Jul 2008</td><td>Non-public code (protected, private, etc) moved into a separate "impl" package where possible.</td></tr>
+<tr><td class="v">0.5.0</td><td class="v">Aug 2008</td><td>API froven.  All future versions must be reverse-compatible with 0.5.0 (except for any parts of 0.5.0 later found to be insecure).</td></tr>
+<tr><td class="v">0.7.0</td><td class="v">Nov 2008</td><td>JavaDocs written for all public methods and classes.</td></tr>
+<tr><td class="v">0.7.5</td><td class="v">Mar 2009</td><td>JUnit tests written for all classes.</td></tr>
+<tr><td class="v">0.9.0</td><td class="v">May 2009</td><td>First BETA release.  JUnit tests passing on all targetted platforms:
+<ol>
+<li>Intel/AMD: (Sun, IBM, BEA) x (Linux, Mac, Windows) x (1.3, 1.4, 5, 6, 7)</li>
+<li>All of the above with and without BouncyCastle.</li>
+<li>PowerPC:  Mac OS X 10.4, 10.5</li>
+<li>Linux: Latest GCJ, Kaffe, and Blackdown releases.  BouncyCastle added if necessary to get tests to pass.</li>
+<li>Anyone got an IBM mainframe we can test on?</li>
+</td></tr>
+<tr><td class="v">0.9.1 - 0.9.9</td><td class="v">Aug 2009</td><td>Bug fixes.</td></tr>
+<tr><td class="v">1.0.0</td><td class="v">Jan 2010</td><td>Development mostly stops.</td></tr>
+</table>
+<p>The problem we're solving with Commons-SSL
+is quite small, so I don't see any reason to ever go beyond 1.0.0, except for fixing bugs.</p>
+</body>
+</html>
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..eafed68
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Author" content="Julius Davies">
+<title>Java and SSL/TLS Made Easier - Not-Yet-Commons-SSL</title>
+<meta name="description" content="Java library for controlling aspects of SSL.  Also helps interop between Java and OpenSSL."/>
+<meta name="keywords" content="Java, SSL, TLS, OpenSSL, HTTPS, Certificates, X.509, X509, Secure Socket Layer, Transport Layer Security, Client Auth, Client Certificate, Client Cert, Client Certificates, Server Cert, Server Certificate, Server Certificates"/>
+<style type="text/css">
+dl, h1, h2, h3, h4 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+dt { padding: 8px 0 8px 5px; }
+li { padding-bottom: 6px; }
+th { text-align: right; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<span class="hl">main</span> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Not-Yet-Commons-SSL</h2>
+<p><a href="download.html">not-yet-commons-ssl-0.3.9</a> released! (November 14th, 2007)</p>
+<p>Requires Java 1.3.x or higher.
+<br/>Some features require Java 1.4.x or higher.   (<a href="rmi.html">RMI-SSL</a>, for example).</p>
+<p>Please see our <a href="ssl.html">ssl page</a> for code examples on how to use this library.</a></p>
+
+<h3>Resources:</h3>
+<table border="0" cellpadding="5" cellspacing="5">
+<tr>
+    <th>Design Goals:</th>
+    <td><a href="about.html">about.html</a></td>
+</tr>
+<tr>
+    <th>Code Examples:</th>
+    <td><a href="ssl.html">SSL/TLS</a>  |  <a href="pkcs8.html">PKCS #8</a>  |  <a href="pbe.html">PBE</a></td>
+</tr>
+<tr>
+    <th>Join Mailing List:</th>
+    <td><a href="http://lists.juliusdavies.ca/listinfo.cgi/not-yet-commons-ssl-juliusdavies.ca/">http://lists.juliusdavies.ca/listinfo.cgi/not-yet-commons-ssl-juliusdavies.ca/</a></td>
+</tr>
+<tr>
+    <th>Mailing List Archives:</th>
+    <td><a href="http://lists.juliusdavies.ca/pipermail/not-yet-commons-ssl-juliusdavies.ca/">http://lists.juliusdavies.ca/pipermail/not-yet-commons-ssl-juliusdavies.ca/</a></td>
+</tr>    
+<tr>
+    <th>Downloads:</th>
+    <td><a href="download.html">http://juliusdavies.ca/commons-ssl/download.html</a></td>
+</tr>
+<tr>
+    <th>Checkout From Subversion:</th>
+    <td><code>svn co <a style="text-decoration: none;" href="http://juliusdavies.ca/svn/not-yet-commons-ssl/trunk">http://juliusdavies.ca/svn/not-yet-commons-ssl/trunk</a> not-yet-commons-ssl</code></td>
+</tr>
+<tr>
+    <th>Browse Subversion (via viewvc):</th>
+    <td><a href="http://juliusdavies.ca/svn/viewvc.cgi">http://juliusdavies.ca/svn/not-yet-commons-ssl/viewvc.cgi</a></td>
+</tr>
+<tr>
+    <th>License (Apache 2.0):</th>
+    <td><a href="../LICENSE.txt">LICENSE.txt</a></td>
+</tr>
+</table>
+<hr/>
+<h4>About</h4>
+<p>We're calling this library "Not-Yet-Commons-SSL" since we have the intention of one day
+becoming an official Apache project.  Not-Yet-Commons-SSL was originally developed by
+<a href="https://www.cucbc.com">Credit Union Central of British Columbia</a>.
+The webpages, releases, and code here on <a href="http://juliusdavies.ca/">juliusdavies.ca</a> have no relationship to
+the Apache Software Foundation, but all code is licensed under <a href="LICENSE.txt">ASL 2.0</a>.
+</p>
+<p>The <a href="http://juliusdavies.ca/svn/viewvc.cgi/trunk/src/java/org/apache/commons/ssl/asn1/">ASN.1 parsing code</a>
+comes directly from BouncyCastle (<a href="http://bouncycastle.org/">bouncycastle.org</a>).  Our only modification to this
+code was an accidental "reformat" to bring it inline with our code style.  Also, in two places, we switched the BC code
+to use <em>our</em> Hex.java
+for encoding/decoding instead of their own.
+The PKCS12 key derivation function (for some PKCS8 version 1.5 encrypted keys) also comes from BouncyCastle.
+Presumably they  got it from RSA's PKCS12 specification
+(<a href="ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf">ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf</a>).
+BouncyCastle maintains copyright over all the code used, but allows us to reuse and redistribute
+(the BouncyCastle license is compatible with ASL 2.0).  We are very thankful for their excellent code.
+</p>
+
+<p>Not-Yet-Commons-SSL would never have happened without Oleg Kalnichevski's excellent
+"<a href="http://svn.apache.org/viewvc/jakarta/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/">contrib</a>"
+example in the <a href="http://jakarta.apache.org/httpcomponents/">HttpComponents</a> SVN repository.
+His
+<a href="http://svn.apache.org/viewvc/jakarta/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java?view=markup">AuthSSLProtocolSocketFactory.java</a>
+and
+<a href="http://svn.apache.org/viewvc/jakarta/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/AuthSSLX509TrustManager.java?view=markup">AuthSSLX509TrustManager.java</a>
+examples
+were the seeds for all of this.  Evil Comrade Oleg's Javadocs on those classes were also extremely helpful.  We
+only one day hope that we can write Javadocs like that (hopefully by <a href="download.html#roadmap">0.7.0</a>!).
+</p>
+</body>
+</html>
diff --git a/docs/pbe.html b/docs/pbe.html
new file mode 100644
index 0000000..eab326a
--- /dev/null
+++ b/docs/pbe.html
@@ -0,0 +1,204 @@
+<html>
+<head>
+<title>OpenSSL's "enc" in Java (PBE / Password Based Encryption)</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+li.top { margin-top: 10px; }
+li { margin-top: 6px; width: 750px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+i { color: purple; }
+i.special { color: red; }
+dt { font-weight: bold; }
+dd { margin-top: 1em; margin-bottom: 1em; }
+sup a { text-decoration: none; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<span class="hl" href="pbe.html">pbe</span> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>OpenSSL's "enc" in Java (PBE / Password Based Encryption)</h2>
+<p>Not-Yet-Commons-SSL has an implementation of PBE ("password based encryption") that is 100%
+compatible with OpenSSL's command-line "enc" utility.  PBE is a form of symmetric encryption where
+the same key or password is used to encrypt and decrypt the file.
+</p>
+<p>
+We are also compatible with <code>openssl enc -K [key] -iv [IV]</code>, where the key and IV are provided explicitly,
+instead of being derived from a password.  Look for encrypt()/decrypt() methods that take
+<a href="http://juliusdavies.ca/commons-ssl/javadocs/org/apache/commons/ssl/OpenSSL.html#encrypt(java.lang.String,%20byte[],%20byte[],%20byte[])">byte[] key, byte[] iv</a>
+instead of char[] password.  
+
+</p>
+<p>Please visit the <a href="#Quick-FAQ">Quick-FAQ</a> if you are having problems.</p>
+
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>PBE code example (DES-3):</b></u><sup><a href="#fn">*</a></sup>
+
+char[] password = {'c','h','a','n','g','e','i','t'};
+byte[] data = "Hello World!".getBytes();
+
+<em style="color: green;">// Encrypt!</em>
+byte[] encrypted = OpenSSL.encrypt("des3", password, data);
+System.out.println("ENCRYPTED: [" + new String(encrypted) + "]");
+
+<em style="color: green;">// Decrypt results of previous!</em>
+data = OpenSSL.decrypt("des3", password, encrypted);
+System.out.println("DECRYPTED: [" + new String(data) + "]");
+
+
+OUTPUT:
+=======================
+ENCRYPTED: [U2FsdGVkX19qplb9qVDVVEYxH8wjJDGpMS+F4/2pS2c=]
+DECRYPTED: [Hello World!]
+
+<sup><a name="fn">*</a></sup> <span style="font-size: 85%;">- This code example is <a href="#nqr">not quite right</a>.</span>
+</pre>
+<br clear="all"/>
+<p>Some notes:
+<ul>
+    <li>The OpenSSL.encrypt() and OpenSSL.decrypt() methods have InputStream and byte[] versions.  For large
+    files you're going to have to use the InputStream versions.</li>
+    <li>OpenSSL.encrypt() produces base64 output by default.  Use
+<a href="http://juliusdavies.ca/commons-ssl/javadocs/org/apache/commons/ssl/OpenSSL.html#encrypt(java.lang.String,%20char[],%20byte[],%20boolean)">OpenSSL.encrypt(alg, pwd, data, false)</a>
+    to turn that off.</li>
+    <li>OpenSSL.decrypt() auto-detects whether input is base64 or raw binary, so you don't need to worry about it
+    when decrypting.  The base64 "true/false" parameter is only applicable when encrypting.</li>
+    <li>We also have methods that are compatible with "<code>openssl enc -K [key] -iv [IV]</code>" where key and iv
+    are explicitly provided, rather than being derived from a password.  The [key] and [IV] should be specified
+    in either raw binary, or hexidecimal (4 bits per character).  This isn't really PBE anymore, but it's a
+    common use case.</li>
+</ul>
+</p>
+
+<p>Here's a list of supported OpenSSL ciphers.  The <i>purple ones</i> require the <a href="http://www.bouncycastle.org/latest_releases.html">BouncyCastle JCE</a>.
+The <i class="special">red ones (desx, desx-cbc)</i> probably require RSA's <a href="http://www.rsa.com/node.aspx?id=1204">BSAFE JCE</a>,
+and have not been tested.
+</p>
+<pre>
+aes-128-cbc               aes-128-cfb               <!-- aes-128-cfb1 -->
+aes-128-cfb8              aes-128-ecb               aes-128-ofb
+aes-192-cbc               aes-192-cfb               <!-- aes-192-cfb1 -->
+aes-192-cfb8              aes-192-ecb               aes-192-ofb
+aes-256-cbc               aes-256-cfb               <!-- aes-256-cfb1 -->
+aes-256-cfb8              aes-256-ecb               aes-256-ofb
+aes128                    aes192                    aes256
+bf                        bf-cbc                    bf-cfb
+bf-ecb                    bf-ofb                    blowfish
+<i>camellia-128-cbc</i>          <i>camellia-128-cfb</i>          <!-- <i>camellia-128-cfb1</i> -->
+<i>camellia-128-cfb8</i>         <i>camellia-128-ecb</i>          <i>camellia-128-ofb</i>
+<i>camellia-192-cbc</i>          <i>camellia-192-cfb</i>          <!-- <i>camellia-192-cfb1</i> -->
+<i>camellia-192-cfb8</i>         <i>camellia-192-ecb</i>          <i>camellia-192-ofb</i>
+<i>camellia-256-cbc</i>          <i>camellia-256-cfb</i>          <!-- <i>camellia-256-cfb1</i> -->
+<i>camellia-256-cfb8</i>         <i>camellia-256-ecb</i>          <i>camellia-256-ofb</i>
+<i>camellia128</i>               <i>camellia192</i>               <i>camellia256</i>
+<i>cast</i>                      <i>cast-cbc</i>                  <i>cast5-cbc</i>
+<i>cast5-cfb</i>                 <i>cast5-ecb</i>                 <i>cast5-ofb</i>
+des                       des-cbc                   des-cfb
+<!-- des-cfb1 -->                          des-cfb8                  des-ecb
+des-ede                   des-ede-cbc               des-ede-cfb
+des-ede-ofb               des-ede3                  des-ede3-cbc
+des-ede3-cfb              des-ede3-ofb              des-ofb
+des3                      <i class="special">desx</i>                      <i class="special">desx-cbc</i>
+<i>idea</i>                      <i>idea-cbc</i>                  <i>idea-cfb</i>
+<i>idea-ecb</i>                  <i>idea-ofb</i>                  rc2
+rc2-40-cbc                rc2-64-cbc                rc2-cbc
+rc2-cfb                   rc2-ecb                   rc2-ofb
+rc4                       rc4-40                    <i>rc5</i>
+<i>rc5-cbc</i>                   <i>rc5-cfb</i>                   <i>rc5-ecb</i>
+<i>rc5-ofb</i>
+</pre>
+
+<p>Here are some additional ciphers supported by BouncyCastle, but not by OpenSSL:</p>
+<pre>
+<i>cast6</i>
+<i>gost</i> (aka: <i>gost28147</i>)
+<i>rc6</i>
+<i>seed</i>
+<i>serpent</i>
+<i>skipjack</i>
+<i>tea</i>
+<i>twofish</i>
+<i>xtea</i>
+</pre>
+
+<hr/>
+<h3><a name="Quick-FAQ">Quick FAQ about PBE and Java</a></h3>
+<hr/>
+<dl>
+<dt>Why do I keep getting "java.security.InvalidKeyException: Illegal key size"?</dt>
+<dd>
+Don't forget to install your JVM's Unlimited Strength
+Jurisdiction Policy Files if you want AES-192 and AES-256 to work.  (Same is true
+for Camillia-192, Camellia-256, and GOST28147).
+
+Visit <a href="http://java.sun.com/javase/downloads/">http://java.sun.com/javase/downloads/</a>
+and scroll to the bottom:
+<blockquote>
+Other Downloads
+<br/>Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6
+</blockquote>
+You can use DES-3 (168 bit keys) without
+installing the extra policy files.
+</dd>
+<dt>Why do the encrypted files always start with "Salted__" ("U2FsdGVkX1" in base64)?
+Isn't giving away information like this insecure?</dt>
+<dd>
+The encrypted files must always start with "Salted__" to interoperate with OpenSSL.
+OpenSSL expects this.  The 8 bytes that spell "Salted__" are always immediately followed
+by another random 8 bytes of salt.  The encrypted stream starts at the 17th byte.
+This way, even if you use the same password to encrypt 2 different files, the actual
+secret keys used to encrypt these 2 files are very different.
+<br/>
+<br/>
+It is possible to omit the salt, but this is highly discouraged:
+
+<pre style="padding: 10px; float: left;">
+boolean useBase64 = true;
+boolean useSalt = false; <em style="color: green;">// Omitting the salt is bad for security!</em>
+byte[] result = <a href="http://juliusdavies.ca/commons-ssl/javadocs/org/apache/commons/ssl/OpenSSL.html#encrypt(java.lang.String,%20char[],%20byte[],%20boolean,%20boolean)">OpenSSL.encrypt(alg, pwd, data, useBase64, useSalt);</a>
+</pre>
+<br clear="all"/>
+</dd>
+<dt><a name="nqr">Why</a> is code example above "not quite right"?</dt>
+<dd>It relies on the platform's default character set.  Here is the proper version (forcing UTF-8):
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>PBE example (DES-3):</b></u>
+
+char[] password = {'c','h','a','n','g','e','i','t'};
+byte[] data = "Hello World!".getBytes("UTF-8");
+
+<em style="color: green;">// Encrypt!</em>
+byte[] encrypted = OpenSSL.encrypt("des3", password, data);
+System.out.println("ENCRYPTED: [" + new String(encrypted, "UTF-8") + "]");
+
+<em style="color: green;">// Decrypt results of previous!</em>
+data = OpenSSL.decrypt("des3", password, encrypted);
+System.out.println("DECRYPTED: [" + new String(data, "UTF-8") + "]");
+
+OUTPUT:
+======================
+ENCRYPTED: [U2FsdGVkX19qplb9qVDVVEYxH8wjJDGpMS+F4/2pS2c=]
+DECRYPTED: [Hello World!]
+</pre>
+</dd>
+</dl>
+</body>
+</html>
diff --git a/docs/ping.html b/docs/ping.html
new file mode 100644
index 0000000..9be48fd
--- /dev/null
+++ b/docs/ping.html
@@ -0,0 +1,92 @@
+<html>
+<head>
+<title>Commons-SSL - Utilities</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<span class="hl" href="utilities.html">utilities</span> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Ping</h2>
+
+<p>"org.apache.commons.ssl.Ping" contains a main method to help you diagnose SSL issues.
+It's modeled on OpenSSL's very handy "s_client" utility.  We've been very careful to
+make sure "org.apache.commons.ssl.Ping" can execute without any additional jar files
+on the classpath (except if using Java 1.3 - then you'll need jsse.jar).</p>
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>"Ping" Utility Attempts "HEAD / HTTP/1.1" Request</b></u>
+This utility is very handy because it can get you the server's public
+certificate even if your client certificate is bad (so even though the SSL
+handshake fails).  And unlike "openssl s_client", this utility can bind
+against any IP address available.
+
+$Name: commons-ssl-0_3_8 $ compiled=[EST:2007-02-22/10:12:26.000]
+Usage:  java -jar not-yet-commons-ssl-0.3.7.jar [options]
+Options:   (*=required)
+*  -t  --target           [hostname[:port]]             default port=443
+   -b  --bind             [hostname[:port]]             default port=0 "ANY"
+   -r  --proxy            [hostname[:port]]             default port=80
+   -tm --trust-cert       [path to trust material]  *.{pem, der, crt, jks}
+   -km --client-cert      [path to client's private key]  *.{jks, pkcs12, pkcs8}
+   -cc --cert-chain       [path to client's cert chain if using pkcs8/OpenSSL key]
+   -p  --password         [client cert password]
+
+Example:
+
+java -jar commons-ssl.jar -t cucbc.com:443 -c ./client.pfx -p `cat ./pass.txt`</pre><br clear="all"/>
+
+<p style="margin-top: 8px;"><b>TODO:</b><br/>Apparently Java 6.0 includes support for grabbing passwords from
+standard-in without echoing the typed characters.  Would be nice to use that feature when it's
+available, instead of requiring the password to be specified as a command-line argument.</p>
+
+<hr/>
+<h2>KeyStoreBuilder</em></h2>
+<p><code>java -cp commons-ssl-0.3.7.jar org.apache.commons.ssl.KeyStoreBuilder</code></p>
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>KeyStoreBuilder converts PKCS12 and PKCS8 to Java "Keystore", and vice versa.</b></u>
+
+KeyStoreBuilder:  creates '[alias].jks' (Java Key Store)
+    -topk8 mode:  creates '[alias].pem' (x509 chain + unencrypted pkcs8)
+[alias] will be set to the first CN value of the X509 certificate.
+-------------------------------------------------------------------
+Usage1: [password] [file:pkcs12]
+Usage2: [password] [file:private-key] [file:certificate-chain]
+Usage3: -topk8 [password] [file:jks]
+-------------------------------------------------------------------
+[private-key] can be openssl format, or pkcs8.
+[password] decrypts [private-key], and also encrypts outputted JKS file.
+All files can be PEM or DER.
+</pre><br clear="all"/>
+
+<br/><b>Warning:</b>
+ <span style="color: red; font-weight: bold;">-topk8 outputs the private key UNENCRYPTED!
+Cut and paste the private key into a separate file, and then use "openssl rsa" or "openssl dsa"
+to encrypt it with a password.</span>
+<br/> 
+<br/> 
+
+
+</body>
+</html>
diff --git a/docs/pkcs8.html b/docs/pkcs8.html
new file mode 100644
index 0000000..40b799f
--- /dev/null
+++ b/docs/pkcs8.html
@@ -0,0 +1,156 @@
+<html>
+<head>
+<title>Decrypting PKCS #8 and OpenSSL Private Keys with Java</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<span class="hl" href="pkcs8.html">pkcs8</span> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>PKCS #8 / OpenSSL Encrypted Keys</em></h2>
+<br/>
+<h3>Java 1.3 Compatible! (with <a href="http://java.sun.com/products/jce/index-122.html">jce1_2_2.jar</a>) (or <a href="http://bouncycastle.org/latest_releases.html">bcprov-jdk13.jar</a>)</h3>
+<p>Commons-SSL includes support for extracting private keys from PKCS #8 files.
+We also support the OpenSSL formats ("traditional SSLeay").  The private keys can be in PEM (base64)
+or DER (raw ASN.1 - a binary format).
+</p>
+<p>The code works with Java 1.3 (+JCE), 1.4, 5.0, 6.0, but not all of the ciphers and hashes are available
+until Java 5.0 (unless you use BouncyCastle).  Fortunately the most common formats [OpenSSL MD5 with 3DES], [PKCS #8 V1.5 MD5 with DES], [PKCS #8 V2.0 HmacSHA1 with 3DES]
+work with all versions of Java, including Java 1.3.</p>
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>pkcs8 example:</b></u>
+
+FileInputStream in = new FileInputStream( "/path/to/pkcs8_private_key.der" );
+
+<em style="color: green;">// If the provided InputStream is encrypted, we need a password to decrypt</em>
+<em style="color: green;">// it. If the InputStream is not encrypted, then the password is ignored</em>
+<em style="color: green;">// (can be null).  The InputStream can be DER (raw ASN.1) or PEM (base64).</em>
+PKCS8Key pkcs8 = new PKCS8Key( in, "changeit".toCharArray() );
+
+<em style="color: green;">// If an unencrypted PKCS8 key was provided, then this actually returns</em>
+<em style="color: green;">// exactly what was originally passed in (with no changes).  If an OpenSSL</em>
+<em style="color: green;">// key was provided, it gets reformatted as PKCS #8 first, and so these</em>
+<em style="color: green;">// bytes will still be PKCS #8, not OpenSSL.</em>
+byte[] decrypted = pkcs8.getDecryptedBytes();
+PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec( decrypted );
+
+<em style="color: green;">// A Java PrivateKey object is born.</em>
+PrivateKey pk = null;
+if ( pkcs8.isDSA() )
+{
+  pk = KeyFactory.getInstance( "DSA" ).generatePrivate( spec );
+}
+else if ( pkcs8.isRSA() )
+{
+  pk = KeyFactory.getInstance( "RSA" ).generatePrivate( spec );
+}
+
+<em style="color: green;">// For lazier types (like me):</em>
+pk = pkcs8.getPrivateKey();
+</pre>
+<br clear="all"/>
+<p>Both RSA and DSA keys are supported.  Here is a list of supported formats:</p>
+<ul>
+<li class="top"><b>OpenSSL "Traditional SSLeay Compatible Format"</b><ul>
+<li>Unencrypted PEM or DER</li>
+<li>Encrypted PEM:<br/>
+<ul class="openssl"><li>des</li><li>des2</li><li>des3</li><li>blowfish</li></ul>
+<ul class="openssl"><li>aes128</li><li>aes192</li><li>aes256</li></ul>
+<ul class="openssl"><li>rc2-40</li><li>rc2-64</li><li>rc2-128</li></ul>
+<br clear="all"/>
+<dl style="margin-top: 1em; width: 600px;"><dt>Note:</dt><dd>OpenSSL "traditional SSLeay" format does not allow encrypted keys to be encoded in DER.  Only
+unencrypted keys can be encoded in DER.</dd></dl></li>
+</ul>
+</li>
+<li class="top"><b>PKCS #8 (Unencrypted)</b>
+<ul><li>PEM or DER</li></ul></li>
+<li class="top"><b>PKCS #8 with PKCS #5 Version 1.5 Encryption</b>
+<ul><li>PEM or DER:
+<ul class="pkcs8">
+<li>MD2 with DES</li>
+<li>MD2 with RC2-64</li>
+</ul>
+<ul class="pkcs8">
+<li>MD5 with DES</li>
+<li>MD5 with RC2-64</li>
+</ul>
+<ul class="pkcs8">
+<li>SHA1 with DES</li>
+<li>SHA1 with RC2-64</li>
+</ul>
+<br clear="all"/>
+</li></ul></li>
+<li class="top"><b>PKCS #8 with PKCS #5 Version 1.5 Encryption and PKCS #12 Key Derivation</b>
+<ul><li>PEM or DER:
+<ul class="pkcs8">
+<li>SHA1 with 3DES</li>
+<li>SHA1 with 2DES</li>
+</ul>
+<ul class="pkcs8">
+<li>SHA1 with RC2-128</li>
+<li>SHA1 with RC2-40</li>
+</ul>
+<ul class="pkcs8">
+<li>SHA1 with RC4-128</li>
+<li>SHA1 with RC4-40</li>
+</ul>
+<br clear="all"/>
+</li></ul></li>
+<li class="top"><b>PKCS #8 with PKCS #5 Version 2.0 Encryption and HmacSHA1</b>
+<ul><li>PEM or DER:
+<ul class="pkcs8">
+<li>DES</li>
+<li>3DES</li>
+<li>Blowfish</li>
+</ul>
+<ul class="pkcs8">
+<li>AES-128</li>
+<li>AES-192</li>
+<li>AES-256</li>
+</ul>
+<ul class="pkcs8">
+<li>RC2-40</li>
+<li>RC2-64</li>
+<li>RC2-128</li>
+</ul>
+<br clear="all"/>
+</li></ul></li></ul>
+<hr/>
+<p>
+Here are links to the raw samples and test results:
+<ol>
+<li><a href="samples/rsa_result.html">2048 Bit RSA</a></li>
+<li><a href="samples/dsa_result.html">2048 Bit DSA</a></li>
+</ol>
+</p>
+<p>The samples were all generated using OpenSSL's
+<code>rsa</code>, <code>genrsa</code>, <code>dsa</code>, <code>gendsa</code>, <code>dsaparam</code>
+and <code>pkcs8</code> commands.  We're curious to know if
+PKCS #8 keys created by other programs will also work, but OpenSSL is all we have to play
+with at the moment.</p>
+<p>The password to decrypt the samples is always "changeit", and they all have the same RSA or DSA
+key.</p>
+
+</body>
+</html>
diff --git a/docs/rmi.html b/docs/rmi.html
new file mode 100644
index 0000000..6d7b2b6
--- /dev/null
+++ b/docs/rmi.html
@@ -0,0 +1,102 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - RMI over SSL Java Example</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+ol.points li { margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<span class="hl" href="rmi.html">rmi</span> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>RMI over SSL <em style="color: red; font-weight: normal;">(experimental)</em></h2>
+<br/><b>3 points to consider:</b>
+<ol class="points">
+<li>To run the RMI-SSL server, you must invoke <code>LocateRegistry.createRegistry( 1099 )</code>
+from within your own application.  You must do this AFTER calling <code>RMISocketFactory.setSocketFactory( impl )</code>.
+RMISocketFactoryImpl will open the registry on 1099, and will open anonymous RMI servers (where port 0 is
+specified) on port 31099.
+RMI-SSL, as shown here, doesn't work with <code>$JAVA_HOME/bin/rmiregistry</code>.
+<br/>See the example code below for help with <code>RMISocketFactory.setSocketFactory( impl )</code>.
+</li>
+<li>To run the RMI-SSL client, you need to find an RMI-SSL server to connect to.  See #1, above.  ;-)</li>
+<li>If you don't manage to find an RMI-SSL server, then the RMI-SSL client will automatically downgrade itself
+to plain-socket.  There is an important security consideration to consider regarding this:  RMISocketFactoryImpl
+at this time only guarantees the security of the registry and the server sockets it opens.  Client sockets
+it creates might be plain-socket.</li>
+</ol>
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>RMI over SSL Example</b></u>
+
+import org.apache.commons.ssl.RMISocketFactoryImpl;
+
+<em style="color: green;">// RMISocketFactoryImpl tries to detect plain sockets, so you should be able to use</em>
+<em style="color: green;">// this even in situations where not all of the RMI servers you are talking to are</em>
+<em style="color: green;">// using SSL.</em>
+RMISocketFactoryImpl impl = new RMISocketFactoryImpl();
+
+<em style="color: green;">// Let's change some settings on our default SSL client.</em>
+SSLClient defaultClient = (SSLClient) impl.getDefaultClient();
+client.setCheckHostname( false );
+client.setCheckCRL( true );
+client.setCheckExpiry( false );
+
+<em style="color: green;">// By default we trust Java's "cacerts", as well as whatever cert is on localhost:1099,</em>
+<em style="color: green;">// so this is redundant:   (Trusting localhost:1099 is some commons-ssl magic).</em>
+client.addTrustMaterial( TrustMaterial.DEFAULT );
+
+<em style="color: green;">// But if we had used setTrustMaterial() instead of addTrustMaterial(), we would (probably)</em>
+<em style="color: green;">// no longer trust localhost:1099!  Using set instead of add causes all previous "adds" to</em>
+<em style="color: green;">// to be thrown out.</em>
+
+<em style="color: green;">// Meanwhile, RMI calls to rmi://special.com:1099/ need to trust a self-signed certificate,</em>
+<em style="color: green;">// but we don't want to pollute our default trust with this shoddy cert.  So only calls</em>
+<em style="color: green;">// specifically to "special.com" (any port) will use this.</em>
+SSLClient specialClient = new SSLClient();
+TrustMaterial tm = new TrustMaterial( "special.pem" );
+specialClient.addTrustMaterial( tm );
+<em style="color: green;">// Here's where the special cert gets associated with "special.com":</em>
+impl.setClient( "special.com", specialClient );
+
+
+<em style="color: green;">// We're might also want to be an RMI server ourselves!</em>
+<em style="color: green;">// By default commons-ssl looks for "~/.keystore" and tries password "changeit",</em>
+<em style="color: green;">// but we can change things if we want:</em>
+SSLServer server = (SSLServer) impl.getDefaultServer();
+tm = new TrustMaterial( "trust_only_these_client_certs.pem" );
+KeyMaterial km = new KeyMaterial( "/path/to/myKey.p12", "password".toCharArray() );
+server.setTrustMaterial( tm );
+server.setKeyMaterial( km );
+<em style="color: green;">// This particular RMI server will only accept connections with client certs!</em>
+server.setNeedClientAuth( true );
+
+<em style="color: green;">// Finally, we tell Java to use our new RMI socket factory!</em>
+RMISocketFactory.setSocketFactory( impl );</pre>
+<br clear="all">
+<pre>
+<!-- make the page scroll a little more -->
+
+</pre>
+</body>
+</html>
diff --git a/docs/source.html b/docs/source.html
new file mode 100644
index 0000000..6c2fc85
--- /dev/null
+++ b/docs/source.html
@@ -0,0 +1,38 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - Source Tree</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<span class="hl" href="source.html">source</span> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>not-yet-commons-ssl Source Code</em></h2>
+<br clear="all">
+
+<!--#include virtual="tree.html" -->
+
+</body>
+</html>
diff --git a/docs/ssl.html b/docs/ssl.html
new file mode 100644
index 0000000..86bfa4d
--- /dev/null
+++ b/docs/ssl.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Author" content="Julius Davies">
+<title>Java Examples for Creating SSL/TLS Sockets</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<span class="hl" href="ssl.html">ssl</span> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<a href="utilities.html">utilities</a> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Code Examples For Creating SSL Sockets</h2>
+<div style="font-family: arial; margin-top: 18px;">
+<b class="n">Note:</b>
+<br/>SSLClient <b class="n">extends</b> SSLSocketFactory
+<br/>SSLServer <b class="n">extends</b> SSLServerSocketFactory
+</div>
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>Client Example:</b></u>
+
+SSLClient client = new SSLClient();
+
+<em style="color: green;">// Let's trust usual "cacerts" that come with Java.  Plus, let's also trust a self-signed cert</em>
+<em style="color: green;">// we know of.  We have some additional certs to trust inside a java keystore file.</em>
+client.addTrustMaterial( TrustMaterial.DEFAULT );
+client.addTrustMaterial( new TrustMaterial( "/path/to/self-signed.pem" ) );
+client.addTrustMaterial( new KeyMaterial( "/path/to/keystore.jks", "changeit".toCharArray() ) );
+
+<em style="color: green;">// To be different, let's allow for expired certificates (not recommended).</em>
+client.setCheckHostname( true );  <em style="color: green;">// default setting is "true" for SSLClient</em>
+client.setCheckExpiry( false );   <em style="color: green;">// default setting is "true" for SSLClient</em>
+client.setCheckCRL( true );       <em style="color: green;">// default setting is "true" for SSLClient</em>
+
+<em style="color: green;">// Let's load a client certificate (max: 1 per SSLClient instance).</em>
+client.setKeyMaterial( new KeyMaterial( "/path/to/client.pfx", "secret".toCharArray() ) );
+SSLSocket s = (SSLSocket) client.createSocket( "www.cucbc.com", 443 );</pre>
+
+<br clear="all"><pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>Server Example (OpenSSL/Apache Style)</b></u>
+<em style="color: green;">// Compatible with the private key / certificate chain created from following the Apache2</em>
+<em style="color: green;">// TLS FAQ: "How do I create a self-signed SSL Certificate for testing purposes?"</em>
+<em style="color: green;">// <a href="http://httpd.apache.org/docs/2.2/ssl/ssl_faq.html#selfcert">http://httpd.apache.org/docs/2.2/ssl/ssl_faq.html#selfcert</a></em>
+
+SSLServer server = new SSLServer();
+
+<em style="color: green;">// Server needs some key material.  We'll use an OpenSSL/PKCS8 style key (possibly encrypted).</em>
+String certificateChain = "/path/to/this/server.crt";
+String privateKey = "/path/to/this/server.key";
+char[] password = "changeit".toCharArray();
+KeyMaterial km = new KeyMaterial( certificateChain, privateKey, password ); 
+
+server.setKeyMaterial( km );
+
+<em style="color: green;">// These settings have to do with how we'll treat client certificates that are presented</em>
+<em style="color: green;">// to us.  If the client doesn't present any client certificate, then these are ignored.</em>
+server.setCheckHostname( false ); <em style="color: green;">// default setting is "false" for SSLServer</em>
+server.setCheckExpiry( true );    <em style="color: green;">// default setting is "true" for SSLServer</em>
+server.setCheckCRL( true );       <em style="color: green;">// default setting is "true" for SSLServer</em>
+
+<em style="color: green;">// This server trusts all client certificates presented (usually people won't present</em>
+<em style="color: green;">// client certs, but if they do, we'll give them a socket at the very least).</em>
+server.addTrustMaterial( TrustMaterial.TRUST_ALL );
+SSLServerSocket ss = (SSLServerSocket) server.createServerSocket( 7443 );
+SSLSocket socket = (SSLSocket) ss.accept();</pre>
+
+<br clear="all"><pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>Server Example (Traditional Java "KeyStore" Style)</b></u>
+
+SSLServer server = new SSLServer();
+
+<em style="color: green;">// Server needs some key material.   We'll use a Java Keystore (.jks) or Netscape</em>
+<em style="color: green;">// PKCS12 (.pfx or .p12) file.  Commons-ssl automatically detects the type.</em>
+String pathToKeyMaterial = "/path/to/.keystore";
+char[] password = "changeit".toCharArray();
+KeyMaterial km = new KeyMaterial( pathToKeyMaterial, password ); 
+
+server.setKeyMaterial( km );
+
+<em style="color: green;">// This server trusts all client certificates presented (usually people won't present</em>
+<em style="color: green;">// client certs, but if they do, we'll give them a socket at the very least).</em>
+server.addTrustMaterial( TrustMaterial.TRUST_ALL );
+SSLServerSocket ss = (SSLServerSocket) server.createServerSocket( 7443 );
+SSLSocket socket = (SSLSocket) ss.accept();</pre>
+
+
+<br clear="all">
+
+</body>
+</html>
diff --git a/docs/tree.html b/docs/tree.html
new file mode 100644
index 0000000..1e543b4
--- /dev/null
+++ b/docs/tree.html
@@ -0,0 +1,156 @@
+<pre>
+   <a href=".">.</a>
+   |-- [2.5K]  <a href="./404.html">404.html</a>
+   |-- [9.9K]  <a href="./LICENSE.txt">LICENSE.txt</a>
+   |-- [ 441]  <a href="./NOTICE.txt">NOTICE.txt</a>
+   |-- [ 235]  <a href="./README.txt">README.txt</a>
+   |-- [4.8K]  <a href="./TrustExample.java">TrustExample.java</a>
+   |-- [ 23K]  <a href="./TrustExample.java.html">TrustExample.java.html</a>
+   |-- [3.0K]  <a href="./build.xml">build.xml</a>
+   |-- [ 13K]  <a href="./download.html">download.html</a>
+   |-- [6.2K]  <a href="./index.html">index.html</a>
+   |-- [4.0K]  <a href="./javadocs/">javadocs</a>
+   |-- [4.0K]  <a href="./lib/">lib</a>
+   |   |-- [ 46K]  <a href="./lib/commons-codec-1.3.jar">commons-codec-1.3.jar</a>
+   |   |-- [273K]  <a href="./lib/commons-httpclient-3.0.jar">commons-httpclient-3.0.jar</a>
+   |   |-- [ 37K]  <a href="./lib/commons-logging-1.0.4.jar">commons-logging-1.0.4.jar</a>
+   |   `-- [350K]  <a href="./lib/log4j-1.2.13.jar">log4j-1.2.13.jar</a>
+   |-- [189K]  <a href="./not-yet-commons-ssl-0.3.8.jar">not-yet-commons-ssl-0.3.8.jar</a>
+   |-- [2.3M]  <a href="./not-yet-commons-ssl-0.3.8.zip">not-yet-commons-ssl-0.3.8.zip</a>
+   |-- [1.3K]  <a href="./oscp.pem">oscp.pem</a>
+   |-- [7.4K]  <a href="./pbe.html">pbe.html</a>
+   |-- [3.9K]  <a href="./ping.html">ping.html</a>
+   |-- [5.7K]  <a href="./pkcs8.html">pkcs8.html</a>
+   |-- [4.9K]  <a href="./rmi.html">rmi.html</a>
+   |-- [4.0K]  <a href="./samples/">samples</a>
+   |   |-- [  66]  <a href="./samples/PASSWORD.txt">PASSWORD.txt</a>
+   |   |-- [  66]  <a href="./samples/README.txt">README.txt</a>
+   |   |-- [1.5K]  <a href="./samples/createPBESamples.sh">createPBESamples.sh</a>
+   |   |-- [4.0K]  <a href="./samples/dsa/">dsa</a>
+   |   |-- [ 14K]  <a href="./samples/dsa.html">dsa.html</a>
+   |   |-- [1.3K]  <a href="./samples/dsa_result.html">dsa_result.html</a>
+   |   |-- [4.0K]  <a href="./samples/pbe/">pbe</a>
+   |   |   |-- [1.3K]  <a href="./samples/pbe/README.txt">README.txt</a>
+   |   |   |-- [ 20K]  <a href="./samples/pbe/java/">java</a>
+   |   |   `-- [ 12K]  <a href="./samples/pbe/openssl/">openssl</a>
+   |   |-- [ 395]  <a href="./samples/pbe.tests">pbe.tests</a>
+   |   |-- [4.0K]  <a href="./samples/pkcs12/">pkcs12</a>
+   |   |-- [4.0K]  <a href="./samples/rsa/">rsa</a>
+   |   |-- [ 14K]  <a href="./samples/rsa.html">rsa.html</a>
+   |   |-- [1.3K]  <a href="./samples/rsa_result.html">rsa_result.html</a>
+   |   `-- [4.0K]  <a href="./samples/x509/">x509</a>
+   |-- [ 993]  <a href="./server.crt">server.crt</a>
+   |-- [1.1K]  <a href="./source.html">source.html</a>
+   |-- [4.0K]  <a href="./src/">src</a>
+   |   `-- [4.0K]  <a href="./src/java/">java</a>
+   |       `-- [4.0K]  <a href="./src/java/org/">org</a>
+   |           `-- [4.0K]  <a href="./src/java/org/apache/">apache</a>
+   |               `-- [4.0K]  <a href="./src/java/org/apache/commons/">commons</a>
+   |                   |-- [4.0K]  <a href="./src/java/org/apache/commons/httpclient/">httpclient</a>
+   |                   |   `-- [4.0K]  <a href="./src/java/org/apache/commons/httpclient/contrib/">contrib</a>
+   |                   |       `-- [4.0K]  <a href="./src/java/org/apache/commons/httpclient/contrib/ssl/">ssl</a>
+   |                   |           |-- [7.2K]  <a href="./src/java/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java">AuthSSLProtocolSocketFactory.java</a>
+   |                   |           |-- [3.5K]  <a href="./src/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java">EasySSLProtocolSocketFactory.java</a>
+   |                   |           |-- [5.8K]  <a href="./src/java/org/apache/commons/httpclient/contrib/ssl/StrictSSLProtocolSocketFactory.java">StrictSSLProtocolSocketFactory.java</a>
+   |                   |           `-- [8.8K]  <a href="./src/java/org/apache/commons/httpclient/contrib/ssl/TrustSSLProtocolSocketFactory.java">TrustSSLProtocolSocketFactory.java</a>
+   |                   `-- [4.0K]  <a href="./src/java/org/apache/commons/ssl/">ssl</a>
+   |                       |-- [3.1K]  <a href="./src/java/org/apache/commons/ssl/ASN1Structure.java">ASN1Structure.java</a>
+   |                       |-- [7.1K]  <a href="./src/java/org/apache/commons/ssl/ASN1Util.java">ASN1Util.java</a>
+   |                       |-- [ 17K]  <a href="./src/java/org/apache/commons/ssl/Base64.java">Base64.java</a>
+   |                       |-- [3.5K]  <a href="./src/java/org/apache/commons/ssl/Base64InputStream.java">Base64InputStream.java</a>
+   |                       |-- [2.7K]  <a href="./src/java/org/apache/commons/ssl/CRLUtil.java">CRLUtil.java</a>
+   |                       |-- [ 18K]  <a href="./src/java/org/apache/commons/ssl/Certificates.java">Certificates.java</a>
+   |                       |-- [2.5K]  <a href="./src/java/org/apache/commons/ssl/ComboInputStream.java">ComboInputStream.java</a>
+   |                       |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/DerivedKey.java">DerivedKey.java</a>
+   |                       |-- [1.9K]  <a href="./src/java/org/apache/commons/ssl/HostPort.java">HostPort.java</a>
+   |                       |-- [ 19K]  <a href="./src/java/org/apache/commons/ssl/HostnameVerifier.java">HostnameVerifier.java</a>
+   |                       |-- [3.5K]  <a href="./src/java/org/apache/commons/ssl/HttpSecureProtocol.java">HttpSecureProtocol.java</a>
+   |                       |-- [9.9K]  <a href="./src/java/org/apache/commons/ssl/Java13.java">Java13.java</a>
+   |                       |-- [2.8K]  <a href="./src/java/org/apache/commons/ssl/Java13KeyManagerWrapper.java">Java13KeyManagerWrapper.java</a>
+   |                       |-- [3.1K]  <a href="./src/java/org/apache/commons/ssl/Java13TrustManagerWrapper.java">Java13TrustManagerWrapper.java</a>
+   |                       |-- [8.3K]  <a href="./src/java/org/apache/commons/ssl/Java14.java">Java14.java</a>
+   |                       |-- [2.8K]  <a href="./src/java/org/apache/commons/ssl/Java14KeyManagerWrapper.java">Java14KeyManagerWrapper.java</a>
+   |                       |-- [3.9K]  <a href="./src/java/org/apache/commons/ssl/Java14TrustManagerWrapper.java">Java14TrustManagerWrapper.java</a>
+   |                       |-- [8.4K]  <a href="./src/java/org/apache/commons/ssl/JavaImpl.java">JavaImpl.java</a>
+   |                       |-- [6.6K]  <a href="./src/java/org/apache/commons/ssl/KeyMaterial.java">KeyMaterial.java</a>
+   |                       |-- [ 21K]  <a href="./src/java/org/apache/commons/ssl/KeyStoreBuilder.java">KeyStoreBuilder.java</a>
+   |                       |-- [2.5K]  <a href="./src/java/org/apache/commons/ssl/LDAPSocket.java">LDAPSocket.java</a>
+   |                       |-- [3.0K]  <a href="./src/java/org/apache/commons/ssl/LogHelper.java">LogHelper.java</a>
+   |                       |-- [8.2K]  <a href="./src/java/org/apache/commons/ssl/LogWrapper.java">LogWrapper.java</a>
+   |                       |-- [ 23K]  <a href="./src/java/org/apache/commons/ssl/OpenSSL.java">OpenSSL.java</a>
+   |                       |-- [2.0K]  <a href="./src/java/org/apache/commons/ssl/OpenSSLTest.java">OpenSSLTest.java</a>
+   |                       |-- [2.2K]  <a href="./src/java/org/apache/commons/ssl/PBETestCreate.java">PBETestCreate.java</a>
+   |                       |-- [3.2K]  <a href="./src/java/org/apache/commons/ssl/PEMItem.java">PEMItem.java</a>
+   |                       |-- [8.4K]  <a href="./src/java/org/apache/commons/ssl/PEMUtil.java">PEMUtil.java</a>
+   |                       |-- [ 34K]  <a href="./src/java/org/apache/commons/ssl/PKCS8Key.java">PKCS8Key.java</a>
+   |                       |-- [ 14K]  <a href="./src/java/org/apache/commons/ssl/Ping.java">Ping.java</a>
+   |                       |-- [1.9K]  <a href="./src/java/org/apache/commons/ssl/ProbablyBadPasswordException.java">ProbablyBadPasswordException.java</a>
+   |                       |-- [1.9K]  <a href="./src/java/org/apache/commons/ssl/ProbablyNotPKCS8Exception.java">ProbablyNotPKCS8Exception.java</a>
+   |                       |-- [ 20K]  <a href="./src/java/org/apache/commons/ssl/RMISocketFactoryImpl.java">RMISocketFactoryImpl.java</a>
+   |                       |-- [ 24K]  <a href="./src/java/org/apache/commons/ssl/SSL.java">SSL.java</a>
+   |                       |-- [7.6K]  <a href="./src/java/org/apache/commons/ssl/SSLClient.java">SSLClient.java</a>
+   |                       |-- [4.1K]  <a href="./src/java/org/apache/commons/ssl/SSLEchoServer.java">SSLEchoServer.java</a>
+   |                       |-- [5.1K]  <a href="./src/java/org/apache/commons/ssl/SSLProxyServer.java">SSLProxyServer.java</a>
+   |                       |-- [9.8K]  <a href="./src/java/org/apache/commons/ssl/SSLServer.java">SSLServer.java</a>
+   |                       |-- [5.2K]  <a href="./src/java/org/apache/commons/ssl/SSLServerSocketWrapper.java">SSLServerSocketWrapper.java</a>
+   |                       |-- [6.9K]  <a href="./src/java/org/apache/commons/ssl/SSLSocketWrapper.java">SSLSocketWrapper.java</a>
+   |                       |-- [3.8K]  <a href="./src/java/org/apache/commons/ssl/SSLWrapperFactory.java">SSLWrapperFactory.java</a>
+   |                       |-- [7.5K]  <a href="./src/java/org/apache/commons/ssl/TomcatServerXML.java">TomcatServerXML.java</a>
+   |                       |-- [6.7K]  <a href="./src/java/org/apache/commons/ssl/TrustChain.java">TrustChain.java</a>
+   |                       |-- [8.2K]  <a href="./src/java/org/apache/commons/ssl/TrustMaterial.java">TrustMaterial.java</a>
+   |                       |-- [ 11K]  <a href="./src/java/org/apache/commons/ssl/Util.java">Util.java</a>
+   |                       |-- [4.5K]  <a href="./src/java/org/apache/commons/ssl/Version.java">Version.java</a>
+   |                       |-- [7.1K]  <a href="./src/java/org/apache/commons/ssl/X509CertificateChainBuilder.java">X509CertificateChainBuilder.java</a>
+   |                       |-- [4.0K]  <a href="./src/java/org/apache/commons/ssl/asn1/">asn1</a>
+   |                       |   |-- [ 10K]  <a href="./src/java/org/apache/commons/ssl/asn1/ASN1InputStream.java">ASN1InputStream.java</a>
+   |                       |   |-- [2.4K]  <a href="./src/java/org/apache/commons/ssl/asn1/ASN1OutputStream.java">ASN1OutputStream.java</a>
+   |                       |   |-- [4.1K]  <a href="./src/java/org/apache/commons/ssl/asn1/BERConstructedOctetString.java">BERConstructedOctetString.java</a>
+   |                       |   |-- [1.5K]  <a href="./src/java/org/apache/commons/ssl/asn1/BERNull.java">BERNull.java</a>
+   |                       |   |-- [1.7K]  <a href="./src/java/org/apache/commons/ssl/asn1/BERSequence.java">BERSequence.java</a>
+   |                       |   |-- [1.7K]  <a href="./src/java/org/apache/commons/ssl/asn1/BERSet.java">BERSet.java</a>
+   |                       |   |-- [2.9K]  <a href="./src/java/org/apache/commons/ssl/asn1/BERTaggedObject.java">BERTaggedObject.java</a>
+   |                       |   |-- [2.3K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERApplicationSpecific.java">DERApplicationSpecific.java</a>
+   |                       |   |-- [1.7K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERBMPString.java">DERBMPString.java</a>
+   |                       |   |-- [1.8K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERBitString.java">DERBitString.java</a>
+   |                       |   |-- [2.0K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERBoolean.java">DERBoolean.java</a>
+   |                       |   |-- [1.4K]  <a href="./src/java/org/apache/commons/ssl/asn1/DEREncodable.java">DEREncodable.java</a>
+   |                       |   |-- [2.2K]  <a href="./src/java/org/apache/commons/ssl/asn1/DEREnumerated.java">DEREnumerated.java</a>
+   |                       |   |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERGeneralString.java">DERGeneralString.java</a>
+   |                       |   |-- [2.4K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERGeneralizedTime.java">DERGeneralizedTime.java</a>
+   |                       |   |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERIA5String.java">DERIA5String.java</a>
+   |                       |   |-- [2.1K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERInteger.java">DERInteger.java</a>
+   |                       |   |-- [1.5K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERNull.java">DERNull.java</a>
+   |                       |   |-- [1.7K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERNumericString.java">DERNumericString.java</a>
+   |                       |   |-- [3.5K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERObject.java">DERObject.java</a>
+   |                       |   |-- [4.4K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERObjectIdentifier.java">DERObjectIdentifier.java</a>
+   |                       |   |-- [1.5K]  <a href="./src/java/org/apache/commons/ssl/asn1/DEROctetString.java">DEROctetString.java</a>
+   |                       |   |-- [1.7K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERPrintableString.java">DERPrintableString.java</a>
+   |                       |   |-- [2.4K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERSequence.java">DERSequence.java</a>
+   |                       |   |-- [2.2K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERSet.java">DERSet.java</a>
+   |                       |   |-- [2.3K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERString.java">DERString.java</a>
+   |                       |   |-- [3.6K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERTaggedObject.java">DERTaggedObject.java</a>
+   |                       |   |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERTeletexString.java">DERTeletexString.java</a>
+   |                       |   |-- [2.4K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERUTCTime.java">DERUTCTime.java</a>
+   |                       |   |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERUTF8String.java">DERUTF8String.java</a>
+   |                       |   |-- [2.2K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERUniversalString.java">DERUniversalString.java</a>
+   |                       |   |-- [1.5K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERUnknownTag.java">DERUnknownTag.java</a>
+   |                       |   |-- [1.7K]  <a href="./src/java/org/apache/commons/ssl/asn1/DERVisibleString.java">DERVisibleString.java</a>
+   |                       |   `-- [1.8K]  <a href="./src/java/org/apache/commons/ssl/asn1/OIDTokenizer.java">OIDTokenizer.java</a>
+   |                       `-- [4.0K]  <a href="./src/java/org/apache/commons/ssl/rmi/">rmi</a>
+   |                           |-- [2.1K]  <a href="./src/java/org/apache/commons/ssl/rmi/DateRMI.java">DateRMI.java</a>
+   |                           |-- [2.1K]  <a href="./src/java/org/apache/commons/ssl/rmi/IntegerRMI.java">IntegerRMI.java</a>
+   |                           |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/rmi/RemoteDate.java">RemoteDate.java</a>
+   |                           |-- [1.6K]  <a href="./src/java/org/apache/commons/ssl/rmi/RemoteInteger.java">RemoteInteger.java</a>
+   |                           `-- [6.1K]  <a href="./src/java/org/apache/commons/ssl/rmi/Test.java">Test.java</a>
+   |-- [5.4K]  <a href="./ssl.html">ssl.html</a>
+   |-- [   0]  <a href="./tree.html">tree.html</a>
+   |-- [2.8K]  <a href="./two-crls.pem">two-crls.pem</a>
+   |-- [3.8K]  <a href="./utilities.html">utilities.html</a>
+   `-- [  27]  <a href="./version.txt">version.txt</a>
+
+20 directories, 126 files
+
+	 tree v1.5.1 (c) 1996 - 2007 by Steve Baker and Thomas Moore 
+	 HTML output hacked and copyleft (c) 1998 by Francesc Rocher 
+	 Charsets / OS/2 support (c) 2001 by Kyosuke Tokoro
+</pre>
diff --git a/docs/utilities.html b/docs/utilities.html
new file mode 100644
index 0000000..d4e3134
--- /dev/null
+++ b/docs/utilities.html
@@ -0,0 +1,91 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - Utilities</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="index.html">main</a> |
+<a href="ssl.html">ssl</a> |
+<a href="pkcs8.html">pkcs8</a> |
+<a href="pbe.html">pbe</a> |
+<a href="rmi.html">rmi</a> |
+<span class="hl" href="utilities.html">utilities</span> |
+<a href="source.html">source</a> |
+<a href="javadocs/">javadocs</a> |
+<a href="download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Ping</h2>
+
+<p>"org.apache.commons.ssl.Ping" contains a main method to help you diagnose SSL issues.
+It's modeled on OpenSSL's very handy "s_client" utility.  We've been very careful to
+make sure "org.apache.commons.ssl.Ping" can execute without any additional jar files
+on the classpath (except if using Java 1.3 - then you'll need jsse.jar).</p>
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>"Ping" Utility Attempts "HEAD / HTTP/1.1" Request</b></u>
+This utility is very handy because it can get you the server's public
+certificate even if your client certificate is bad (so even though the SSL
+handshake fails).  And unlike "openssl s_client", this utility can bind
+against any IP address available.
+
+Usage:  java -jar not-yet-commons-ssl-0.3.9.jar [options]
+Version 0.3.9      compiled=[PST:2007-11-14/14:42:18.000]
+Options:   (*=required)
+*  -t  --target           [hostname[:port]]              default port=443
+   -b  --bind             [hostname[:port]]              default port=0 "ANY"
+   -r  --proxy            [hostname[:port]]              default port=80
+   -tm --trust-cert       [path to trust material]       {pem, der, crt, jks}
+   -km --client-cert      [path to client's private key] {jks, pkcs12, pkcs8}
+   -cc --cert-chain       [path to client's cert chain for pkcs8/OpenSSL key]
+   -p  --password         [client cert password]
+   -h  --host-header      [http-host-header]      in case -t is an IP address
+   -u  --path             [path for GET/HEAD request]    default=/
+   -m  --method           [http method to use]           default=HEAD
+
+Example:
+
+java -jar not-yet-commons-ssl.jar -t host.com:443 -c ./client.pfx -p `cat ./pass.txt`</pre><br clear="all"/>
+
+<p style="margin-top: 8px;"><b>TODO:</b><br/>Apparently Java 6.0 includes support for grabbing passwords from
+standard-in without echoing the typed characters.  Would be nice to use that feature when it's
+available, instead of requiring the password to be specified as a command-line argument.</p>
+
+<hr/>
+<h2>KeyStoreBuilder</h2>
+<p>org.apache.commons.ssl.KeyStoreBuilder is able to convert OpenSSL style public/private keys into
+Java KeyStore files.  It can also convert Java Keystore files into the PEM format that Apache likes.</p>
+
+<p><code>java -cp not-yet-commons-ssl-0.3.9.jar org.apache.commons.ssl.KeyStoreBuilder</code></p>
+
+<pre style="border: 1px solid red; padding: 10px; float: left;"><u><b>KeyStoreBuilder converts PKCS12 and PKCS8 to Java "Keystore"</b></u>
+
+KeyStoreBuilder:  creates '[alias].jks' (Java Key Store)
+    -topk8 mode:  creates '[alias].pem' (x509 chain + unencrypted pkcs8)
+[alias] will be set to the first CN value of the X509 certificate.
+-------------------------------------------------------------------
+Usage1: [password] [file:pkcs12]
+Usage2: [password] [file:private-key] [file:certificate-chain]
+Usage3: -topk8 [password] [file:jks]
+-------------------------------------------------------------------
+[private-key] can be openssl format, or pkcs8.
+[password] decrypts [private-key], and also encrypts outputted JKS file.
+All files can be PEM or DER.
+</pre><br clear="all"/>
+
+
+</body>
+</html>
diff --git a/samples/PASSWORD.txt b/samples/PASSWORD.txt
new file mode 100644
index 0000000..ceda279
--- /dev/null
+++ b/samples/PASSWORD.txt
@@ -0,0 +1,3 @@
+Password for decrypting any of these files is
+always "changeit".
+
diff --git a/samples/README.txt b/samples/README.txt
new file mode 100644
index 0000000..ceda279
--- /dev/null
+++ b/samples/README.txt
@@ -0,0 +1,3 @@
+Password for decrypting any of these files is
+always "changeit".
+
diff --git a/samples/createPBESamples.sh b/samples/createPBESamples.sh
new file mode 100755
index 0000000..af39169
--- /dev/null
+++ b/samples/createPBESamples.sh
@@ -0,0 +1,106 @@
+#/bin/bash
+export TARGET_DIR=/home/julius/dev/commons-ssl/samples/pbe/openssl
+export OPENSSL_APP='/home/julius/dev/commons-ssl/t/openssl-0.9.8e/apps/openssl'
+
+export CIPHERS='
+aes-128-cbc
+aes-128-cfb
+aes-128-cfb1
+aes-128-cfb8
+aes-128-ecb
+aes-128-ofb
+aes-192-cbc
+aes-192-cfb
+aes-192-cfb1
+aes-192-cfb8
+aes-192-ecb
+aes-192-ofb
+aes-256-cbc
+aes-256-cfb
+aes-256-cfb1
+aes-256-cfb8
+aes-256-ecb
+aes-256-ofb
+aes128
+aes192
+aes256
+bf
+bf-cbc
+bf-cfb
+bf-ecb
+bf-ofb
+blowfish
+camellia-128-cbc
+camellia-128-cfb
+camellia-128-cfb1
+camellia-128-cfb8
+camellia-128-ecb
+camellia-128-ofb
+camellia-192-cbc
+camellia-192-cfb
+camellia-192-cfb1
+camellia-192-cfb8
+camellia-192-ecb
+camellia-192-ofb
+camellia-256-cbc
+camellia-256-cfb
+camellia-256-cfb1
+camellia-256-cfb8
+camellia-256-ecb
+camellia-256-ofb
+camellia128
+camellia192
+camellia256
+cast
+cast-cbc
+cast5-cbc
+cast5-cfb
+cast5-ecb
+cast5-ofb
+des
+des-cbc
+des-cfb
+des-cfb1
+des-cfb8
+des-ecb
+des-ofb
+des-ede
+des-ede-cbc
+des-ede-cfb
+des-ede-ofb
+des-ede3
+des-ede3-cbc
+des-ede3-cfb
+des-ede3-ofb
+des3
+idea
+idea-cbc
+idea-cfb
+idea-ecb
+idea-ofb
+rc2
+rc2-40-cbc
+rc2-64-cbc
+rc2-cbc
+rc2-cfb
+rc2-ecb
+rc2-ofb
+rc4
+rc4-40
+rc5
+rc5-cbc
+rc5-cfb
+rc5-ecb
+rc5-ofb'
+
+for CIPHER in $CIPHERS
+do
+  export OPENSSL_YES_B64_CMD="$OPENSSL_APP enc -$CIPHER -pass pass:changeit -a"
+  export OPENSSL_NO_B64_CMD="$OPENSSL_APP enc -$CIPHER -pass pass:changeit"
+  echo -n "Hello World!" | $OPENSSL_YES_B64_CMD > $TARGET_DIR/$CIPHER.base64
+  echo -n "Hello World!" | $OPENSSL_NO_B64_CMD > $TARGET_DIR/$CIPHER.raw
+done
+
+# Not supported by any JSSE implementation I have access to:
+#   desx
+#   desx-cbc
diff --git a/samples/dsa.html b/samples/dsa.html
new file mode 100644
index 0000000..6851348
--- /dev/null
+++ b/samples/dsa.html
@@ -0,0 +1,114 @@
+<pre>
+java -showversion -cp <a href="../download.html">build/not-yet-commons-ssl-0.3.7.jar</a>  org.apache.commons.ssl.PKCS8Key <a href="dsa/">samples/dsa/*.*</a>
+
+java version "1.6.0"
+Java(TM) SE Runtime Environment (build 1.6.0-b105)
+Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
+
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	128	<a href="dsa/openssl_dsa_aes128_cbc.pem">samples/dsa/openssl_dsa_aes128_cbc.pem</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	128	<a href="dsa/openssl_dsa_aes128_cfb.pem">samples/dsa/openssl_dsa_aes128_cfb.pem</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	128	<a href="dsa/openssl_dsa_aes128_ecb.pem">samples/dsa/openssl_dsa_aes128_ecb.pem</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	128	<a href="dsa/openssl_dsa_aes128_ofb.pem">samples/dsa/openssl_dsa_aes128_ofb.pem</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	192	<a href="dsa/openssl_dsa_aes192_cbc.pem">samples/dsa/openssl_dsa_aes192_cbc.pem</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	192	<a href="dsa/openssl_dsa_aes192_cfb.pem">samples/dsa/openssl_dsa_aes192_cfb.pem</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	192	<a href="dsa/openssl_dsa_aes192_ecb.pem">samples/dsa/openssl_dsa_aes192_ecb.pem</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	192	<a href="dsa/openssl_dsa_aes192_ofb.pem">samples/dsa/openssl_dsa_aes192_ofb.pem</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	256	<a href="dsa/openssl_dsa_aes256_cbc.pem">samples/dsa/openssl_dsa_aes256_cbc.pem</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	256	<a href="dsa/openssl_dsa_aes256_cfb.pem">samples/dsa/openssl_dsa_aes256_cfb.pem</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	256	<a href="dsa/openssl_dsa_aes256_ecb.pem">samples/dsa/openssl_dsa_aes256_ecb.pem</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	256	<a href="dsa/openssl_dsa_aes256_ofb.pem">samples/dsa/openssl_dsa_aes256_ofb.pem</a>
+   SUCCESS    	DSA	Blowfish/CBC/PKCS5Padding	128	<a href="dsa/openssl_dsa_blowfish_cbc.pem">samples/dsa/openssl_dsa_blowfish_cbc.pem</a>
+   SUCCESS    	DSA	Blowfish/CFB/NoPadding   	128	<a href="dsa/openssl_dsa_blowfish_cfb.pem">samples/dsa/openssl_dsa_blowfish_cfb.pem</a>
+   SUCCESS    	DSA	Blowfish/ECB/PKCS5Padding	128	<a href="dsa/openssl_dsa_blowfish_ecb.pem">samples/dsa/openssl_dsa_blowfish_ecb.pem</a>
+   SUCCESS    	DSA	Blowfish/OFB/NoPadding   	128	<a href="dsa/openssl_dsa_blowfish_ofb.pem">samples/dsa/openssl_dsa_blowfish_ofb.pem</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/openssl_dsa_des1_cbc.pem">samples/dsa/openssl_dsa_des1_cbc.pem</a>
+   SUCCESS    	DSA	DES/CFB/NoPadding        	 64	<a href="dsa/openssl_dsa_des1_cfb.pem">samples/dsa/openssl_dsa_des1_cfb.pem</a>
+   SUCCESS    	DSA	DES/ECB/PKCS5Padding     	 64	<a href="dsa/openssl_dsa_des1_ecb.pem">samples/dsa/openssl_dsa_des1_ecb.pem</a>
+   SUCCESS    	DSA	DES/OFB/NoPadding        	 64	<a href="dsa/openssl_dsa_des1_ofb.pem">samples/dsa/openssl_dsa_des1_ofb.pem</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/openssl_dsa_des2_cbc.pem">samples/dsa/openssl_dsa_des2_cbc.pem</a>
+   SUCCESS    	DSA	DESede/CFB/NoPadding     	192	<a href="dsa/openssl_dsa_des2_cfb.pem">samples/dsa/openssl_dsa_des2_cfb.pem</a>
+   SUCCESS    	DSA	DESede/ECB/PKCS5Padding  	192	<a href="dsa/openssl_dsa_des2_ecb.pem">samples/dsa/openssl_dsa_des2_ecb.pem</a>
+   SUCCESS    	DSA	DESede/OFB/NoPadding     	192	<a href="dsa/openssl_dsa_des2_ofb.pem">samples/dsa/openssl_dsa_des2_ofb.pem</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/openssl_dsa_des3_cbc.pem">samples/dsa/openssl_dsa_des3_cbc.pem</a>
+   SUCCESS    	DSA	DESede/CFB/NoPadding     	192	<a href="dsa/openssl_dsa_des3_cfb.pem">samples/dsa/openssl_dsa_des3_cfb.pem</a>
+   SUCCESS    	DSA	DESede/ECB/PKCS5Padding  	192	<a href="dsa/openssl_dsa_des3_ecb.pem">samples/dsa/openssl_dsa_des3_ecb.pem</a>
+   SUCCESS    	DSA	DESede/OFB/NoPadding     	192	<a href="dsa/openssl_dsa_des3_ofb.pem">samples/dsa/openssl_dsa_des3_ofb.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	128	<a href="dsa/openssl_dsa_rc2_128_cbc.pem">samples/dsa/openssl_dsa_rc2_128_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CFB/NoPadding        	128	<a href="dsa/openssl_dsa_rc2_128_cfb.pem">samples/dsa/openssl_dsa_rc2_128_cfb.pem</a>
+   SUCCESS    	DSA	RC2/ECB/PKCS5Padding     	128	<a href="dsa/openssl_dsa_rc2_128_ecb.pem">samples/dsa/openssl_dsa_rc2_128_ecb.pem</a>
+   SUCCESS    	DSA	RC2/OFB/NoPadding        	128	<a href="dsa/openssl_dsa_rc2_128_ofb.pem">samples/dsa/openssl_dsa_rc2_128_ofb.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 40	<a href="dsa/openssl_dsa_rc2_40_cbc.pem">samples/dsa/openssl_dsa_rc2_40_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/openssl_dsa_rc2_64_cbc.pem">samples/dsa/openssl_dsa_rc2_64_cbc.pem</a>
+   SUCCESS    	DSA	UNENCRYPTED              	  0	<a href="dsa/openssl_dsa_unencrypted.der">samples/dsa/openssl_dsa_unencrypted.der</a>
+   SUCCESS    	DSA	UNENCRYPTED              	  0	<a href="dsa/openssl_dsa_unencrypted.pem">samples/dsa/openssl_dsa_unencrypted.pem</a>
+   SUCCESS    	DSA	UNENCRYPTED              	  0	<a href="dsa/pkcs8_dsa_unencrypted.der">samples/dsa/pkcs8_dsa_unencrypted.der</a>
+   SUCCESS    	DSA	UNENCRYPTED              	  0	<a href="dsa/pkcs8_dsa_unencrypted.pem">samples/dsa/pkcs8_dsa_unencrypted.pem</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md2_des1_cbc.der">samples/dsa/pkcs8v1_dsa_md2_des1_cbc.der</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md2_des1_cbc.pem">samples/dsa/pkcs8v1_dsa_md2_des1_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md2_rc2_64_cbc.der">samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md2_rc2_64_cbc.pem">samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.pem</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md5_des1_cbc.der">samples/dsa/pkcs8v1_dsa_md5_des1_cbc.der</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md5_des1_cbc.pem">samples/dsa/pkcs8v1_dsa_md5_des1_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md5_rc2_64_cbc.der">samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_md5_rc2_64_cbc.pem">samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.pem</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_sha1_des1_cbc.der">samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.der</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_sha1_des1_cbc.pem">samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.pem</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/pkcs8v1_dsa_sha1_des2_cbc.der">samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.der</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/pkcs8v1_dsa_sha1_des2_cbc.pem">samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.pem</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/pkcs8v1_dsa_sha1_des3_cbc.der">samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.der</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/pkcs8v1_dsa_sha1_des3_cbc.pem">samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	128	<a href="dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.der">samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	128	<a href="dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.pem">samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 40	<a href="dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.der">samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 40	<a href="dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.pem">samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.der">samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.pem">samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.pem</a>
+   SUCCESS    	DSA	RC4                      	128	<a href="dsa/pkcs8v1_dsa_sha1_rc4_128.der">samples/dsa/pkcs8v1_dsa_sha1_rc4_128.der</a>
+   SUCCESS    	DSA	RC4                      	128	<a href="dsa/pkcs8v1_dsa_sha1_rc4_128.pem">samples/dsa/pkcs8v1_dsa_sha1_rc4_128.pem</a>
+   SUCCESS    	DSA	RC4                      	 40	<a href="dsa/pkcs8v1_dsa_sha1_rc4_40.der">samples/dsa/pkcs8v1_dsa_sha1_rc4_40.der</a>
+   SUCCESS    	DSA	RC4                      	 40	<a href="dsa/pkcs8v1_dsa_sha1_rc4_40.pem">samples/dsa/pkcs8v1_dsa_sha1_rc4_40.pem</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	128	<a href="dsa/pkcs8v2_dsa_aes128_cbc.der">samples/dsa/pkcs8v2_dsa_aes128_cbc.der</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	128	<a href="dsa/pkcs8v2_dsa_aes128_cbc.pem">samples/dsa/pkcs8v2_dsa_aes128_cbc.pem</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	128	<a href="dsa/pkcs8v2_dsa_aes128_cfb.der">samples/dsa/pkcs8v2_dsa_aes128_cfb.der</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	128	<a href="dsa/pkcs8v2_dsa_aes128_cfb.pem">samples/dsa/pkcs8v2_dsa_aes128_cfb.pem</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	128	<a href="dsa/pkcs8v2_dsa_aes128_ecb.der">samples/dsa/pkcs8v2_dsa_aes128_ecb.der</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	128	<a href="dsa/pkcs8v2_dsa_aes128_ecb.pem">samples/dsa/pkcs8v2_dsa_aes128_ecb.pem</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	128	<a href="dsa/pkcs8v2_dsa_aes128_ofb.der">samples/dsa/pkcs8v2_dsa_aes128_ofb.der</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	128	<a href="dsa/pkcs8v2_dsa_aes128_ofb.pem">samples/dsa/pkcs8v2_dsa_aes128_ofb.pem</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	192	<a href="dsa/pkcs8v2_dsa_aes192_cbc.der">samples/dsa/pkcs8v2_dsa_aes192_cbc.der</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	192	<a href="dsa/pkcs8v2_dsa_aes192_cbc.pem">samples/dsa/pkcs8v2_dsa_aes192_cbc.pem</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	192	<a href="dsa/pkcs8v2_dsa_aes192_cfb.der">samples/dsa/pkcs8v2_dsa_aes192_cfb.der</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	192	<a href="dsa/pkcs8v2_dsa_aes192_cfb.pem">samples/dsa/pkcs8v2_dsa_aes192_cfb.pem</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	192	<a href="dsa/pkcs8v2_dsa_aes192_ecb.der">samples/dsa/pkcs8v2_dsa_aes192_ecb.der</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	192	<a href="dsa/pkcs8v2_dsa_aes192_ecb.pem">samples/dsa/pkcs8v2_dsa_aes192_ecb.pem</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	192	<a href="dsa/pkcs8v2_dsa_aes192_ofb.der">samples/dsa/pkcs8v2_dsa_aes192_ofb.der</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	192	<a href="dsa/pkcs8v2_dsa_aes192_ofb.pem">samples/dsa/pkcs8v2_dsa_aes192_ofb.pem</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	256	<a href="dsa/pkcs8v2_dsa_aes256_cbc.der">samples/dsa/pkcs8v2_dsa_aes256_cbc.der</a>
+   SUCCESS    	DSA	AES/CBC/PKCS5Padding     	256	<a href="dsa/pkcs8v2_dsa_aes256_cbc.pem">samples/dsa/pkcs8v2_dsa_aes256_cbc.pem</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	256	<a href="dsa/pkcs8v2_dsa_aes256_cfb.der">samples/dsa/pkcs8v2_dsa_aes256_cfb.der</a>
+   SUCCESS    	DSA	AES/CFB/NoPadding        	256	<a href="dsa/pkcs8v2_dsa_aes256_cfb.pem">samples/dsa/pkcs8v2_dsa_aes256_cfb.pem</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	256	<a href="dsa/pkcs8v2_dsa_aes256_ecb.der">samples/dsa/pkcs8v2_dsa_aes256_ecb.der</a>
+   SUCCESS    	DSA	AES/ECB/PKCS5Padding     	256	<a href="dsa/pkcs8v2_dsa_aes256_ecb.pem">samples/dsa/pkcs8v2_dsa_aes256_ecb.pem</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	256	<a href="dsa/pkcs8v2_dsa_aes256_ofb.der">samples/dsa/pkcs8v2_dsa_aes256_ofb.der</a>
+   SUCCESS    	DSA	AES/OFB/NoPadding        	256	<a href="dsa/pkcs8v2_dsa_aes256_ofb.pem">samples/dsa/pkcs8v2_dsa_aes256_ofb.pem</a>
+   SUCCESS    	DSA	Blowfish/CBC/PKCS5Padding	128	<a href="dsa/pkcs8v2_dsa_blowfish_cbc.der">samples/dsa/pkcs8v2_dsa_blowfish_cbc.der</a>
+   SUCCESS    	DSA	Blowfish/CBC/PKCS5Padding	128	<a href="dsa/pkcs8v2_dsa_blowfish_cbc.pem">samples/dsa/pkcs8v2_dsa_blowfish_cbc.pem</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v2_dsa_des1_cbc.der">samples/dsa/pkcs8v2_dsa_des1_cbc.der</a>
+   SUCCESS    	DSA	DES/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v2_dsa_des1_cbc.pem">samples/dsa/pkcs8v2_dsa_des1_cbc.pem</a>
+   SUCCESS    	DSA	DES/CFB/NoPadding        	 64	<a href="dsa/pkcs8v2_dsa_des1_cfb.der">samples/dsa/pkcs8v2_dsa_des1_cfb.der</a>
+   SUCCESS    	DSA	DES/CFB/NoPadding        	 64	<a href="dsa/pkcs8v2_dsa_des1_cfb.pem">samples/dsa/pkcs8v2_dsa_des1_cfb.pem</a>
+   SUCCESS    	DSA	DES/ECB/PKCS5Padding     	 64	<a href="dsa/pkcs8v2_dsa_des1_ecb.der">samples/dsa/pkcs8v2_dsa_des1_ecb.der</a>
+   SUCCESS    	DSA	DES/ECB/PKCS5Padding     	 64	<a href="dsa/pkcs8v2_dsa_des1_ecb.pem">samples/dsa/pkcs8v2_dsa_des1_ecb.pem</a>
+   SUCCESS    	DSA	DES/OFB/NoPadding        	 64	<a href="dsa/pkcs8v2_dsa_des1_ofb.der">samples/dsa/pkcs8v2_dsa_des1_ofb.der</a>
+   SUCCESS    	DSA	DES/OFB/NoPadding        	 64	<a href="dsa/pkcs8v2_dsa_des1_ofb.pem">samples/dsa/pkcs8v2_dsa_des1_ofb.pem</a>
+   SUCCESS    	DSA	DESede/ECB/PKCS5Padding  	192	<a href="dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.der">samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.der</a>
+   SUCCESS    	DSA	DESede/ECB/PKCS5Padding  	192	<a href="dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.pem">samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.pem</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/pkcs8v2_dsa_des3_cbc.der">samples/dsa/pkcs8v2_dsa_des3_cbc.der</a>
+   SUCCESS    	DSA	DESede/CBC/PKCS5Padding  	192	<a href="dsa/pkcs8v2_dsa_des3_cbc.pem">samples/dsa/pkcs8v2_dsa_des3_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	128	<a href="dsa/pkcs8v2_dsa_rc2_128_cbc.der">samples/dsa/pkcs8v2_dsa_rc2_128_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	128	<a href="dsa/pkcs8v2_dsa_rc2_128_cbc.pem">samples/dsa/pkcs8v2_dsa_rc2_128_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 40	<a href="dsa/pkcs8v2_dsa_rc2_40_cbc.der">samples/dsa/pkcs8v2_dsa_rc2_40_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 40	<a href="dsa/pkcs8v2_dsa_rc2_40_cbc.pem">samples/dsa/pkcs8v2_dsa_rc2_40_cbc.pem</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v2_dsa_rc2_64_cbc.der">samples/dsa/pkcs8v2_dsa_rc2_64_cbc.der</a>
+   SUCCESS    	DSA	RC2/CBC/PKCS5Padding     	 64	<a href="dsa/pkcs8v2_dsa_rc2_64_cbc.pem">samples/dsa/pkcs8v2_dsa_rc2_64_cbc.pem</a>
+</pre>
diff --git a/samples/dsa/openssl_dsa_aes128_cbc.pem b/samples/dsa/openssl_dsa_aes128_cbc.pem
new file mode 100644
index 0000000..7af858e
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes128_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,3D7028A746BE6B09694E16A222C543CB
+
+RkTEJRJjGfaMfNc876Tx1hD92cblJRj7TvUafRKnH0J3Zv7l67MSG/6rY5HD91HP
+s9i9Se+H8Sjn/HaUl3QTZv04egloNlL3MPSkI5fusR6maZGPVLRJBLfVKYQZVDja
+9YRe+ZhXMS8jTe/IhYMcTlQLBnnwmmgZC09Y9Wm39idu7lytOl3JBMgz0aUNA+P6
+lN2MtaQyIBXHbaqfNDGFn/r7+MH4CGw6MtrPzGqRJgGMHhV6T5o/x0nEU+loQVOK
+mPkSZTxBbn7xUb4JvFPnLTbsI4Cnre3QmfmDwkCAklQXqAIT9Ex1Slq8qaCc6TEf
+mWJQCYPUkpQOqyinR8o1VbYm3DFFvE5F+CktJrppqkQvAct0dQNjMTBFxUjCkZum
+qGfAslGPBREmmnsExm5GThYqA5LN+qo2prBtvt6Eso0i2jNiXA8bi5OfDzDr24R5
+/RKUdFPf7keaAjg9jSArwp6EfM3y3sj2riibwZlty2ckPJw3SwxIe6QSMwKRbKlh
+GJoi05/cO0NxQYhMmlwVN9v5+YpvWmT3CsFvCA+Zb5rXPx2AZpFv8YoHdQb0qyEs
+b5YuVoavL58+BWIPQpeYy/jttR5pEPpgM+C/6/1o4Cae4lwppP2OYFl1fsqyqbKh
+iadErB6QRaJCnfnhG6511CxY+vZtQE5EM36blOl/op+6G+36ApuqDtfA0C074daV
+uHfcqA/g5dODEJP+ps6yoWtM5lbd5bZZVidWhrU6Skbt0faF9w5ECF0qkYDGqF85
+qqFcaoimq+NP7EtUEFSneOee72zYALXyzjoEU9InktzDi0Oufojzc1gjhh7LbObw
+UBANPHTsbaL6FPTEs4a3JYSyat9m/R5GAaT0EBynHxvdQRGNhtEWFPkpGYUrAz9W
+0A9mNX1as8Jsxkh9wqjgOR6Xpbqh0aFHNnkodwV72H5ROga5EN8/bbuCBxInNzy8
+o9z19AnajR7vCW/p42QwsGfSolQgE3KBdqWsle81LcCPVQPQshXzcjgBHZbH9/mY
+M4bX4iEsC9yeNgoMcHtIagOKipsqd4nuPskutf07Mh71OXFuxsVyGcOBVhhdZCb0
+3ZYzVi+nzORPRZ93nPXipy3+NmoARk7mhXDgX9p1bPI=
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes128_cfb.pem b/samples/dsa/openssl_dsa_aes128_cfb.pem
new file mode 100644
index 0000000..de088f9
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes128_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CFB,C0CCB782DF620FA388D9A356F8B7C346
+
+DftIvr+HZuCHBanw4n8P5ZajHAw1ldQkSgLxtxY0ZYhhVDLEqEqh6z+4ySjZz5SR
+KY7kYFo6yJnURurg3DAGvJ55s6jgyrRHQZkhiO1fBxhyarOfcBjJauJKDT4uhFtC
+LWZ7dqft3PlcHi09mFKjK+BYjULe1QkdrKQlV5FBpCj7ENuHqtfx//bV+IWWVnbu
+QRx4ec2nNCiS2qiI9Qg7fgMdXWrpJlr8Zvfmn0Mta3Dn9SWR9hK5J4d3xiBtaF0F
++BNuszy9poxnsRaORZYAsBh2vdLaQyn1gGdehlsWG4J2Zb5RHApYczJcp2AoPX4K
+j9wAzlfLRSZ4Lt5edShd1zf/iDxegBKQFFHTfPA6uu+fe38qckdxVyBdGaCCBvUz
+Quu2DjjXdCWWo8To5C28LVoVyAy+qJaX86vn7yw03/6n0y2dkydiB3u6wnucsom2
+HfLX+pdyarFoNvtCeSW3Y/1Eqd54dDhz3GrSTh6c7G+wiRziKpTduEmoZ+l+CIrl
+tWxmh59YTSeX4mi48+fxTA8xaVwD/j3VuA/jTOQWDW+DXU2z6OcAQ9rlOnT6Jad6
+P2El+vgLrIFbC4eJs2ry6bszqFJ4wieBVnazPCUADLSsXVwbFuO9oB4129y3Yg+U
+dE+lN24KV0kC/YIdO7c2PghaFY98CVrBX/oocHy4j122fHfboiPNh7S7n6cqJHh2
+JKKQK1qTdfULAN5ypecl27gWeM2i3ib2C5jJiOFUlwiAkZWLRJlsiJOk+b/rI5FD
+tM7yFanhEtcYumRRoSzKII3tF0h+z2AwzPdsyJDdASCzo/DmhB0fg0O8G0q/isNi
+VV2zL+w7mNmf79QsrGVA39Y+G/uKS2QPf3bGFthzYZwKH1M9hTN/do8wCCJJv7MR
+Ejnd32srumBOvGXnYtGuHnT3qRA1mj82B00bdfwCd09GGUr6mEQwfvsDOR3q4OfH
+eGCn9NkWKYvf/QAxCG9Vh7u62sUlXKS08hJcVAgBOzN10wFISTIOAvedt/q5GMvm
+nRuF/ixs6f6LNy/VgyztHoQ4vN4HBf8teDsbWSMDvlLkU6tQZjyuu8JkTjeDaqMv
+GbCzrRBldS3zMXX2OaWpZohi
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes128_ecb.pem b/samples/dsa/openssl_dsa_aes128_ecb.pem
new file mode 100644
index 0000000..4f69fa7
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes128_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-ECB,174C8C70B397BCF00CAECA7AAF7A0A73
+
+wzs0bJqGg+Scn00TgtgXyV6hopQKVWMEFnMpu6R/Sp1tbPVlr+m5+SppJFVyW3WJ
+YeFSwXzuVAsnbD9qIZpAlco1ZYpmRXaY6IfXJKYf58v2IrqkxVd6AwjGN2FloSNp
+b/DinJXJe807tNAkuBLQ/7QlkCv/BmZMeYBl60XYIH8LDF/T/ON2hREl49zr/GLY
+bwmVzgRpfl3c8QIt6Yl9uKOqCFJmMHD3YS+dT2RwuQwqY+U3DNzVoCci6Zjd+gL3
+eb/S6VstodSR55qF8Fkwt+sy5yL6XmhQaGWEgCwDwArN40MWIEpx4NaBxCcqHF7g
+o26bg6CZwY7Rv42RTHKHNPETegZneAMK+e1lNassSijak+A3ng9bxiBquWSKHe0i
+s265Rptr/GvQX0hLxmfjEjvL98dKVDZpvdBaWRqV2lS26jDPiFAHtVsXvF8uo25J
+1aS8FDHaD2DghC5aXTQRaVy1jlMTm2YZeVfiU6+7HVXBkLsVbShqEHxKylxgtB/1
+OAui+st60+o8lvRmn5dT2xnxLn81Bt4qron4pz0LdzC2xl0DqjhXyRsf7kdxr44h
+YN1YzmdU3fYFzQw+VmE8xECIjPukp+0HSb4n7BTGsWvqzntFIrzWGeRmNhjtMcwy
+YJoWGnz+WbxP3DJqSGNdFME7mNI/kaybIkOpbHLLlmgD7XWpeyGYtsU/rzrh5NXN
+YRj6Nf3TWI1zwS2xx95+/5vc5Df+sb1+/33J4hbGOx9KdfqoVlJZ16puvdTq97dF
+x8TVYxk2PfBJpvpChCsFlYBOB29F+kY2qoBKPbrvmFPsPCgI2q4gFuJ9pq1qyDbK
+pq9d1oewOOxR22VMQNGG7tL0tMmtXJ/z0n3Y1UE3aYiSG7apOhooBAQ8grpuwqbn
+mGTz6sYB8fHdCnedcxEUxxuFjXupmBcT2ulUjFZgFrG0SEMElgTDjtG21eurqPKh
+ZgxfkW+tM251WTi6sqjiQO8WYHlU7+XyO3BKfH5v3kz4qXxsmvKfh4UOfRy5f9YT
+Ft5oi1bos0soTvms0d8ckLt9Tph2wgoz3Sc++4DRcF53Ks9N6iUgtTpkEtmd/Uc2
+5+xewYmlfYO2qfiqiF/6dSVfDPjJYR/YLx8KBZ40/e0=
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes128_ofb.pem b/samples/dsa/openssl_dsa_aes128_ofb.pem
new file mode 100644
index 0000000..cddcea9
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes128_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-OFB,B32C602DACAACE3A4C55B4600D974E5F
+
+w1+kMXURdxpREW3giZg+PooayvatT1Pf1bY/h0Wcm8z0w7zRtQOyjCOdEPNxsdd5
+ZYn3qEIOO+wkw0v0PdK1AaegJfYMbMpSp/iEyFXU/LHS0FpO7o8zmUiAvdeEKAFt
+Qk90gFBiyQyvWEWsp32KQH1/eDSeSLeQbfRfDbh70DkB4nUjYMW/eFL9E/cHCmdw
+0LKUpEycc4s8i/mWCYJF+cQd4J8RHK+Ose2+5z86kHTrbFSlTBEZEXPDRHl8ZsZE
+477A6/Ndy0Mq3+NgMLSl8xacs2v3itdza3AJREVOzvnRmV+NmWtYQ4MQrJrLg2yv
+wfAf4b2r+k8Igbpzn3NCEYolecGfyEWftzTsqTutlFO7RfeW8go4v2MvEsmHTphQ
+k2qaQkdSTFaA7a2O4PKezJap4RRCJhq1d5bw7RwkCpbRshsvrKQqGdTGJxEZZfGY
+6pOt/qRL9LVCGUVdTTdje7fx9okx0LvKo62eKcUBh/AwZGE+ue28g6/77iABuVtQ
+6kgJ3lQK3AQwKislF5cBC9MAkiIomsoVOKiP6+yX74XIa7T+3aWXlsY1oX13+kMW
+zijwOrc114Sus2eS3xSCOWLYN+0GECMrh2NDGDW6tx7i3R20BuEF/IwHob1qjbkz
+hnS8KrRY+174avQDeF1lMSBz4Wfi0O1IDuxWRDRT2z31E4E8EIoJh+73NZr7w6JA
+8usK8RkiJ4ypoOPtRegXX6GBG5UYgI5bn1Ms2X5xSUGIXgG8IwjHDbAAd5xLSWp+
+01HzUsR+6wA3MxYiybTU4eOKNMviM1G4gGsKeuGrDsNnidrHfSzVyOGVVHr51xRI
+9Xie4FX/VX8/7Q5RMsA8Y2eN/yeVwXup65JRhDD5LjILVMy7aA90KX7y/s8KIYae
+n6lB7PtcpRWwhdYSYtnlrJmYmrl55d6ZQtJm2/xjnOBd+igY4YKNjh11xBL8YNo3
+wBjW4/lgrlvC7kbLxO6JIWipPr/6F3bjvmeLclTAZxjM1NU5HhTScGaEA8A4bq4+
+6Jiw9ZUw+TDCOmntkgEublcCMjcAxrawWYO/5EWuOAOkyBsa7BbfsUv3pgPugz70
+qa/CEkshP5e/1VZgFq/BNFtb
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes192_cbc.pem b/samples/dsa/openssl_dsa_aes192_cbc.pem
new file mode 100644
index 0000000..9b91632
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes192_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,7FA13403627D9E1FA02FF88F6D594679
+
+hZYB09uY4gjQFEHX8KGI33EzcJijYhBMNJCR9v8UK8IcQIITOfZxYV2BmrfQhuVh
+Kcar1JrQdnc4S7+UDFIjlLV9ErBCvIUQEflP2ByDhxl892EtVcoMKB3BJ2Rgi9mk
+32KhayXo5V2bu2kOv2nTAjp91LebDz/ylmhhJhI86BL0DLjnjTEl99v9OHQsMtb9
+cXZb51mwIynmqU7Wf+PchH83Yw0WOKs4MOrCtsqO9lL7Mf/MiSSiE+S/rpKLPXY0
+4aBxP6fw+HG57gPlNAvv/qKtJu8YgZDqVXhIKNDZRTSRX+B9R1Yo1tgmJVPhk/7x
+mmYUxIb7w9nqa5OrxzFHyNvo1U5dJcXyCEhvUZ3ImR1DZt/oGJYgrPd/8YcYbsNP
+LKmTLUKI5CARZ5KcOjfM8vpKqlfpCg3Yl1FaNIjM0eAhD6XrepLj3faAJW4/YEoZ
+SGMO5atbM0ERT9sNDJTG0iMW6xGL5l/6pzfsTKI/2yMaAeWAyvg1PySNoSH7s6CC
+CfqF0w0VpQEiOPb+qjtmjBDB/VW5kNrRiBQqZAgpO6mED0jAdg9o31tyuuaFDWzX
+41C2viVvxTx5A/xOtPvaDo9EMecc+7MpPLM2VhWhPDiDBYb8PCKqBOEwIyH119MN
+gQEC0IN/itc/J9ybHLCjrF1Rp83T3/XhAaXNVU9msBBpKNjawnwsUUj8gI0JRbx/
+5ehO32sQm8wkMyP/8iKDAqBRkDT3RIEmLi8ms+ZZRmLwGBkSZZzvOK3A5Dder4bp
+dIhOOetvoN6Bs9l1i6Dds64pwsy8IcnLLeNmOag+Qh8+pVUBNZ1zUV3KSizRKh5U
+dyT6VMILd2EAUJYLXs9HNFTtHZglRb96jQ3rkHGmAepeIVnJlNGKByvDUsJQDGl/
+bGNk5Ejz93ylY8JzR1GaYyFVIUU0qY8khbo7bSn/o6II+KjyTTyTkV28jTSD5dYe
+upGHOzmqpGi3Pzaz3DXpbLcMzwYrMP9FuXuqkVWToDs87DCfGqskKtko+zlTV7/P
+eBILwUawtXMJfYntkV247FffKgS3/BNkgEE+iNthOsFMSoqX/3ESBKJdJDfKRH0J
+BkYL8O0I7OwYzfU3gCWVZ8AvAhd+nSqp4H3QUK0QM2w=
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes192_cfb.pem b/samples/dsa/openssl_dsa_aes192_cfb.pem
new file mode 100644
index 0000000..9dd5b15
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes192_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CFB,3E445502677C77AC6ED115F8EFD9BBB7
+
+fJXVVcgxhZJXZANfEWDbVmz75ocICvntATRNVgt92sHgl1B2c4cgQC4Xmu7WM/Bc
+ocUlcSpWnoHtWRDumw2cwB+fDb5k3e9qb+aL2juzHkK+kYd2mkRjW8KSG6D8HIwq
+fpvV6NQmVrxI5+n+uabwfil8Ecg9V7GD6ta0QSgt0lc8clp01se+VDacX1uCB7zG
+NtJsr1wUM0SQbEWPEcpLUoYfK0qSO0h8fpnagKrNQLfzFbk85arkpD9XBzxpNO2p
+2fYsc3xZ0RkFauSZGt6ehu0jh1TZNPYDURvSn3uVrseLyR0Gt8LWp+hjIUp9Kpo2
+fLUVaH/7wxpdCAYzo4Ub/gHPfbxo2E5qYmE1oTJyAHplaDqSg8pbwJofiXl12gMM
+IyIC3SCHZJph7xqbKa+W/X4ChxYuN23ZMZ72cmqH4tH/j9IpKrpWEeqjxaj0EwDs
+R06Sz/qAqs9iDMKTkuFTMxGhc09DV9sN4NYczEIEas7gploOdryJGMCM96RtMDS1
+gjW21w0wyfqa7ogsDJJ2/HqKL73Zfn7l0jzmqya7YwcToEfKOSP+a2Q/y3Exr4KO
+FY5PLwKvpBaFcFzJoYhAaPphUzzAQuQFgXj34f4JU9bAXbf7ol7Swcv9JP9tN/mF
+n7z55BbPfC1EiyGyDjeUDWw4XIYF6LtRK3lnvn4uSZFXLmYMJJthwwC/yS+D65LW
+vsW9uuQ2qEfEC3hVbMPP+1KMgRkb9CVbSXBH+B7UoaUkGsJYzdSDeHZHbwiHgxqH
+jb6WcjtUjh7W2VO/MnHBrLg8dnC77OnR4IiqJq/6TenuSu0N/4mm73SH7BtYAugu
+ok/2H7GYfGfWjOnd+QvG/Vjsb+l9gtB6SXYFiWuThjB/sU4kHH8LUUOmGRlC3NDz
+w4pv+cR3tS1zX+evPL0BsZ3ynDSGRbMpss7xVooxIPacFwDN8kHUnWvIBpQKAizq
+blt1owc97vidf9OnZxUMpzw28/PZ+y/vRYSPQrde3kH8mJmu1FC6tLZnqzuCSsgR
+SJSr3/8qqSj3XrAW+nj0Y2P8lItNdFXex7j/RuX3eV5QIyK7uY+z8ZP4gf5q9w54
+p+dQi7Vx8acRjbsU+r85+MRR
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes192_ecb.pem b/samples/dsa/openssl_dsa_aes192_ecb.pem
new file mode 100644
index 0000000..c7608e0
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes192_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-ECB,C625A2E97BCB192B31A8E33CB0CD857C
+
+jM0PVjU2r063OACSZgLkaS9ppOj4idZ9hgkdMi58Oi+C5bfhZavbjROyxCG0EMGz
+HnAIRJ4pkJeZTnGElmOEFbaNPb42NAvcrYXAP4XNu5FbZ2SqGKwRnjjN8z7s8+Ip
+MrCyJsWycYy2BNaksJRaDNgazjKgqQxGFlQPJ+j99E4dk5QaduOCrf6YQ2G+1Q+m
+2/uqVujTwmverPnHDNhQI0ZYMY+l8+oVcPHIY3TR3ufecvrGkjFgKH0B+/L7gWSd
+ASvldEnWuFtPMiYnqCPtLgJNKSXO2nlumLc4Gz2ruvYKI1qGPXsVLIGnxISVLUzT
+VQz7NrRYwlvSLWdQNqbrEPvEu4q1KstqIkiPRoC98vG4+VRkf9AXAGqxA+vKYktP
+2Ui/SLhoC/seh9pxYXLsmqP+8bxcNM3VsJQoUUFM2PtfyvzBtuQ7mJQTSFSXgBym
+qXvzx749S4xOot+H6r/bCh8753MMEsgsM39jBsRm1zbaBjaNFG0UBdfFigHWh1zx
+4I44pIHu1AQDexjnfaUVrZFbys0CtM/Wy/3y0I3+mar1Wg3Rc1XL1PJzwDqBoZst
+vg1h0L5OPV1c4CekFnAEx+VI6ImxENoYtZCpbpt90kz3GxRY/eS8roS/SRJ7KizC
+p9bWEsUMwJ4Jl+xvV/VtVG96nKzlU13gkI6lMATYzImK4Fh7hH/LBy/UhNVL8X76
+3fo64CCwE3YkrWEmBDdxt/K8Knj4MUPjBgy/ETVRC7ziG0rUwRSd7zLOoEALMHig
+AtNX+juPvPU7yARw317Q9lZXeytf1AmGiFGjYZR/mduAa9M415uWm6zutIJEz+q8
+KV93bm18JUaQSrX4D6m8IgNhX0EfmRYAIFnB3rv+1rsb61q+4USk0L/1vKT/fGGm
+yvXMCA10N50wGS4wovMYQIl/giMEU8e88f+gqImU1kporgESIOUYUm9tOZ80w4R6
+ITlKCzRuoptMQBGZeJIWfWNLxwYq7NXKpvjNeSOeOqQ4fxhkzEetFERG/2hnszmM
+pqwoZBZQ8bb+T6cmJD1GuxoO3ev258WIUkEZTkFYK2Q/+QKymPZO4ATSAO4N2UqQ
+4TXRqUs4i+1f/BJU0ahnSgmzrynGmskUonKxt6T87lE=
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes192_ofb.pem b/samples/dsa/openssl_dsa_aes192_ofb.pem
new file mode 100644
index 0000000..5010035
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes192_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-OFB,7E4DC037A44E5DEE4E005CED36B18C16
+
+hvLtWTLg0+cMFDo3jN0yZc8S7fE6cDdZcBK0aRy+Eg+9kWlnmR/VYqG4xaich3VQ
+wkyhNpBSAoUHY8OKkB8hYsqbGkuKxQ6Db4IJlahCTFgb0yO2C7pUrtGDTvmXVq2n
+qJ4c+4CILeyzIp5yfy0dE8CAsZZcLEdSpPvaNK0VPZEPhelm4WdqqLozYVibR0KS
+2BbVO+E7yHGC/G3xtdbduuYpID1pLwyaebUCNgblggn6FJ0G2+Iu7lndmMU4B1Wr
+phvb+Fd1kL5421u8OOKRVLS2yMtlzbK2Mz7NclEzEs1m6K/xJUzztxImAxElBiiB
+YfOw5WLy278DuD1GCBkSuAKB4XWUtlq0+tJnCzAG0yrdMloKH1m+XF3MXFiRTXgE
+k08PcZchoNgGP51Rcg77skATP9OMamcjnkMx1B8YxTx9O5Vv/oSIjGQrr+t2np2t
+JU1dHTr9QrCeadSz+My0sjlZrL3ZisAwBbu6C0Zta1P1eB+i8ORZvm9HvmadcyyE
+y5oQWv7XwSfAQup/4uuAJ8bQBunIH/ajMF1WmD8rzLcUjG8W0rnBWUtjaxxBdkWv
+xBzgMPm7Q+L/5yhL/TMH3dkUBq+Cg5VQSe9EspNRGKBUgfKYk67Y343Mv91xKtX8
+8Tmh/WlnYXDv8QBnFJZXVnf8HeSFHsHDzfTgAmWHdhisTNwmgSFvBK5ghvhvkbXI
+UIPi+FgeB7P3ccFYnmoMq5qgK0Ki4lU6v57soDrjRl/NttfXdQEhLfWO1zXNANLk
+lqEhJSvBPZY4/FiOW4kNaZg2oRswz/+Bmp3amsK5TwBcI72rnH6SW5ADqPCcTP+h
+IrH4L9wnhOXw7QLk/h58JwiEc8suj5n0PJPQeHKajizd/EpUzVAuRTAl4GMvxLCY
+rALxeRaEXfJH5i/0UQydEvdU3ZP/LTibAqStXyVlSBZmKOg0GNQ+aAiHZyBnI3oq
+QuD0KuJi84ETMLU2baRydTbVlQDr8O0vxnCNlPkFFOqVpWyOyBgMctUfFJiM5c0l
+1UT6dc2F7NF5WOuoDCVw+Jp974CJuBSRGpdQKGms1Dvjwrtnf0ycstswXHvp2ZhV
+IVeCbT4WWh4f9bp6STkdquSc
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes256_cbc.pem b/samples/dsa/openssl_dsa_aes256_cbc.pem
new file mode 100644
index 0000000..17289b2
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes256_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,307CEE18F79CA333A38CA90E75B248C5
+
+qyg9Q1cX/FGOoP0NFzrCRLwmR6bai7JzDiCLFCthciYkMIWLIVzvyTg850YD3dw3
+Wusli8EQJig8DEpFSM0WBc1Rne8U4168nKuRnFUaP+VWuD4UpNDt66cT6dMoqATD
+kZGdd+p8ReO9TK9gO/ZZU4R+q3OUpjxX44szxj/EIVSgphi8R0rRSxl/yFRnGHyO
+xfpM9NxgMvBYlyxl5w1Lp/ictuF3D505nF/uuhzGL5a+WWhSnssMFHF9vxXTu21/
+3Cy0C3Qah9eV/C2oyAU7GGsXHIfqFqsgMjQN+cTFqMyFeg6g0J7hytDAgZVBXIFw
+UuzMbxUUZU9VHcZzwqstkg5BmUI3sgW6gibBUzuJrmo7uLrCvHyj9oehSMqeuPUC
+EXFqhw6Nb+jZMkvW9J9qFYG9eg3PQsDErIdVK8aWdLrLyc+O4gycOdMbR8aq/3Z4
+TlV7Ye650EvQ13bwZghZyKel6Rjt4P1MagGriNqCcLVVsyrRXAiqjq8cyJgYtoXF
+1VMBZz8ob2FH9+kvk2sb4+T22sTYwiqAVaLnCsuJ4dmS5wdBrhfF4oyHYV2KOVgG
+64GqxiF9/whvbAWSM4cU+KslKnWGZwz53LKleafrgeFJ2P1ldqnl0on5EQ/m9bzt
++GSGwzZGRmhf5NoyhaH+OCkq/h1UP+LZ5kDJCqH/l1JZbvJQkGNKzt1OroW17GnQ
+EgihXAmhy/xOAIZkz1XKa3bNvgS1F9yreAxJAvBHB0QzZ1HrablsaTKsZOtY1Qvq
+e2OdpJFm+SrI7RUtbp787Yl9pH2cLEdto+WH8gtgXloS+b11Q7broE42w9MIJrno
+kzs6eDWafSExTvpi+29OJEtK4PNezmhOxzTUIsG0/8d9Vd2WYqrLD34ze68X8qUa
+CoIXYP8VsQLoXVzX7VnMBYTQ+YOR0Ntq6pRj07RbJrNiOt8qcWGslzE17ERuCr0+
+ZFTGy77KOksKjLksvRj4oshQjRhVYZscPNnwKODFDvOPsGFjDoU2Sg+W8kcfE6Bc
+1RQwk4N0cjkC2JXXk61QQjh+efWRBqPN6va+ixUcsZSxndCIoBk4qtqtsyTFEcC7
+LdfCC96RGnXlvroiPHvrmJYN69JAyyRrnhiYfaaC98s=
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes256_cfb.pem b/samples/dsa/openssl_dsa_aes256_cfb.pem
new file mode 100644
index 0000000..06718a5
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes256_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CFB,337D3978222A1367F5CFE08611416E9C
+
+GVmy9WG3oR1Vpfxnfpv1hFvXGzBgE+c4jplSw2BAlKnbznCPbZLc3WF/ZMv2851O
+iE/8sdcetzoAlm3jGPoDi6Y/FqMFmcbqtro7vUz/SVgi1HDI0FXjOTPtFe6xfzhv
+84qt5lz5VAUueTKFXEZHqM9tV7lHt1FX86VutNObn8pE7nAWVX/Xvq+qWUsEx0ik
+YjZjLY696pyz61hnxZE4jKZLRx/9a6vWYaVfzsEi2FLw9qAsw6ILp+xDaAeKa+Il
+YVkgDPi62NPr7cRX1WCiw+/feNYPgUfGiBNkd2mOnAr1yOXFM+YALw5V+q8I6ZKN
+k8R7skAzRZkwTJ9WaaFGD/UypYmhe2b9Jp2n0BMEn5RpW4o1DTIHmfMSUmUPp5w3
+HjbtdDUWIiuplrz7mUE2sez/3bMbcoiO2Ym9SInJKBrMFSvyasg403u4QESYQhC2
+Lwcocb5ixXoczHjef3CogL6BhL2oZwXCl3OBqpMOJJJKXUPRhN8bvgV41UIsiGtN
+TFUXqYdpbmMkxJNMGiD3mKWpSm2MMdQYnRlxNh0wXLi5sHckD/WS4yFrNsCIMVDT
+W094liK/Z7BmplY4TyqKhsRlFVQ4VOo/W0WNh7Ayp0siIfo8vHDyoQsnUkn/EUER
+UZG1lIy6/y1RSg15GWpdi1bvT9URjElh/U944LSYD28K2VU8aPKaRBokk+K3AyR6
+YhZRCBr6uIVZ8HDkBL5OW0eP69/jdbyc4MnWRa6C0d0boA7N639j+NQz9erYT6wu
+RkInmBbVfxQD6HLkMwiuU23qLP+QQTLkH7rQJmnRPSwAKEE8RiXWi4/TnYW7d0AC
+Bj8oaK6DO+J9t1pdj0IGluf52iUwAOf2Pxwvu44ovaF+yb2n3P7S5maDGLTV/xBW
+D6nEAct9cYj22/aRDTLdpOfG0L242vjQLnjrgezBLraa9eTy29hR5FU5ACH5sB72
+rxUSwoCHCJuNFSxC27QwZqeCFw51epwXxLv1CjqsQi2So12qH+vFVtL/1YrFBct0
+dzwbdNk0S6UyPRqfiOE/+Iszzahmb/GgskPJdfT5Y03FnpDWfOotpaAebrY4t6kz
+/gs8pxupvdKw4eWsxVCL9KOP
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes256_ecb.pem b/samples/dsa/openssl_dsa_aes256_ecb.pem
new file mode 100644
index 0000000..ab0f64d
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes256_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-ECB,267E98B92F05ECECABF28790E81DCFA0
+
+MkVFB5/gKxAksBI/g96MmN+ujdt0XFXC+7MI+0/OJ/H0LXlHlLpwfGlx/Je73Imt
+rOZveXf4I8sBCF1Z0Fhzb3TTTDxcastJGKWAVKaPzKkWdxNeUjx0kinbrkM7Spfa
+yG+wW+Srtfyi6LzEsbCduDK7hzfDnLbgKymdDeP0TVeJzEdXgXcV09a01GA+CEVX
+aHesQLNHyYm9nxFxK0fAnKo5r1I2JsozSWNTG3VNbiItxtfoJdXTn25I16qXjKzn
+MOn/A+RBpO+P01j4uk0q0SPJMlIYIX+RjgAoPiI5R5vSeucsdUJo1sWnSfqLc4yP
+vUG5wD/+lYrxsXiW61KdwIg3vy/ty5+GqwNgNvN0FZM8DvK+NQ9K/IpoW5RE4ioS
+ZNm1JpeGJiywsBf3Pi9mwR44tTVY0Jwa/TTQp1kEYGjhYXMIEvf+LUHwG5KO2wmD
+kDediMDUPaUx9K34eSpgIUln5d+1viMpC2VcDIg4tYjAODtGRxzgDUr3mbuoVl8f
+GqusTAdsNoIyilY44XxA2odHa4S8yXsx1f54P8fRYbA4Xo179LY1Nh7PwQPm+rI2
+mERkCsvns9jP1zJRuS1lYW1Dqjtxxq8Nt5RAsEwKQYLO4DfsuMZPblEXPAwSGb/N
+69xNs8ZFHm3KT1r7FdUrVpHk2vmqsetNa/g2wRTEuBmRCgrtTtEDWgdBNtDoHlBR
+pDIWgwNvt7oJIU0EbQkUgW8bmg1p7jxXN8Bk2QKZoOytxA4TB3fR1p92VkXzrkxn
+l+Z815BNfqnNCU5nNzLwk3jLgksZrDnLu4sXykIBC/bpP5fubnT7iJYh9h6ZGFeY
+QLUP//ssuZM2auNjTVykWUtAiglROzxnFZjMXEbujOKbm70Uj3YvAHjoKalkti9x
+MTj/vpR0xBv/iDtTFl12HIg+IEGL1PfX4xy2avvJO+XGFD4zcnrLfTMwtUJQjdQH
+dUMWP8VI266u+B6wGfcrhdCYqtvuLVUvbISU3YD/tP+esXh563kPnXd2UuaS3ErE
+/7Y/hzyUkDjJ2g37Hq3M4wbaEg/a6osDtfg73thDMadsbTLIDjHKgAgBv4umNtA8
++EaP0stzRH3ayHL/f4I5bHC8bMIAumKM6zap6tBiork=
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_aes256_ofb.pem b/samples/dsa/openssl_dsa_aes256_ofb.pem
new file mode 100644
index 0000000..7192ffc
--- /dev/null
+++ b/samples/dsa/openssl_dsa_aes256_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-OFB,A2D4D65382905DF6EEE7A315B10CF2D9
+
+CpLeywQMv8uZGrgJYM8rZ01awWHJWH/ZKkNi1rpQhaI1BAShQbIUvpY1IsMLa0/E
+g2+oj+Aa1UE4UDsAlzcfsKG9QHS8nOYWuLpU7VAyjC6wUPn0yI0sxxKRd4dmPIgW
+w3r0xO187yqLAjIZCj4y+3ANCjw+rLpZ5Zq8KAN4j6H1NEmzNoNVQbwY0hpsyxwE
+Tg7TkI5IyNKQSQC48EuZh16cJR48l36gzFOmZKr47gzS0zivvED4Vxdaey+WZkoF
+1XW4VbQGHRnLEn/I8rziic9E5pvvcZt6K2NwvzXrkS53ufFYZcgxNRxrdM4yLz+r
+20Unn2F2KqumB1RAliKo/PtudO7XfsPNc7rbF/stGhlxDWTyPU2HMX9tw3JkWDfG
+rRsG4RJOQgsx0Q73/7XPhgu1J2Wp39a/QI/IHwZ+rWIerdUPhs/MRRPoduAfSSZo
+r2z8OPJAlMWLwAjmmKDGhpTp/21n9xLo8tbvqmy8Frz+kAxAHXeHCTWUbxA+URKb
+s5NKQALX3wYHT9Xq0A27A/Zrqs5elqc/IQL58nU/Da3a3OfPB4+MNWeWU781ohhi
+VkBgMRbnQNCC8OPoeMd/At9GDEEj1rDxx49pJdMMwxXS04P43LiuNSmndCei2cQh
+/7cho8YTbdgjKF2kVCZvYXBVsu7Nn834kJw7eMH6slU+VM45jTkOTr2uLzKWrBL6
+YONiK2xdD9NlDcTsX4YRkt+dByJEcDAuvprVdnLKpFXAOWDLW6e0o0siuFIGBtgX
+NR5vA5llpOkladJk+j+dxX4u5Ql9KFPtD9uM05ik5VQCZN8pxy6On3GUeSdoAE9i
+i+rtgZofs39mZOTxhYr+Djnq3WiWntV91GImwhqiXxUBI/fs91+yy+FWphpGORaT
++Rab+cyvauBsdTAoSjjd5cNXXsztfDxEhLnZ1yWMQZxVgV7tcLevVo7e75pSZrN0
+/gMQAH1Fcxtbrdzg1fehLiqTEWp14lFyDCkqAqQ5C9niCqwyf8+6Axaukk4ImmP5
+n9eIykRezLizjA+GCe2oC1jXpVEEYVzOJpbBAwZqk/jlyNd0m01URxvhOaW1/M41
+uWDeQp7ljJrtiyMqD5P3STGR
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_blowfish_cbc.pem b/samples/dsa/openssl_dsa_blowfish_cbc.pem
new file mode 100644
index 0000000..8b71187
--- /dev/null
+++ b/samples/dsa/openssl_dsa_blowfish_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CBC,B23E9DCDF6361CCB
+
+BTPCHNUVRgsKo1up9Ktshx00vDANb05S4S0LPU/wzG8sj60db3bX7Uzr0PPy7ShH
+1zPv0PECYla1dh9nVBPOS4EQE3uHyzuDMTg0AsiR8TpysuI+a4y8XJeAhkU1DTD6
+YzmaodjbCrhautYUCzvcui/sWWXTUSWH/yrFOxaaxLpccacCssGlPc3Tmr5brPmO
+xaZvO32ii6z7WAP/WmyRoYH+BSqmUBhObolifBD5kg1ilPfCk3xMtz4lbJRWANsS
+r6YWPwo+qh1TIQWw40Kz4oQOteVNiwh/dvYGxMkd9Gs4J9nY5deKYExoWlYcci6N
+VOrGA6HBWzfFx/QWWGK77xE8yQ8HeeZUgkWwYoSyAmxjPWgCj+BT5gbYV3W9E6UR
+T3lsKGtI/lMW9N0DVcLdur0lLIBFiVbzxoUAL1SteLJ0mbu/Vnk4VhI5z5mOmSxo
+bU/HElXdjIhk7hdTU5PMNSKiAsxNh03NiPsTpEASMhz+oP8BuJZh6Zi/K3qMYH3u
+6BYmA+Ua23fFYd/kz2TclVwiQ1HQjO3+9l0aSgLhHFb3t0spYbx1Ld5+bAb8b30Q
+9w/fNab1mB6hFgaqruPErfI0K8BZ845oAiakZBfKnTRQxAlKNY5gWvSiPDWlkfIb
+uSBW6csh62iQM1/bcW0voR21NGS+WdQ3eg16vv0HMhmEXmEvtAuCGb6ZMqY117s/
+VciBymZzwdLKFjCqrLn6enYrT7uneOoq/8PaXD1rdMuKGL4W2LqGH+Q0RU+1hyBJ
+7ipTQqystqi6HUU2R1/PI4K73X0MMTB0Jfkd81S6GmjkMYCFCHmHXCdNULjbjzT4
+gppgVW5joIbLKNPHJ78lw4BuMxcAgptmtQBADnWZQNF/pBnIVAY/pdHgreIBTQ7R
+KL1/ATp3+gtGd37FOGZilhq8C4ML+w18M0iTUUfGg5svUvmtw+NpNWMijTJpu3Uo
+KqjMj3NbwCwu2b9qxwalC3qWOgAJf4Z784+i2GOvACk2Mw2QyXoZV8Qm520M+idR
+rj6DIfzEf/86TWH9IrGukDbJNB74QHgdXd9upyt4sL6uHMxPwz4nnhBB7I8B/Q59
+oB+3CBpYIANihDscUbiNSsw5/AXNtMuA
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_blowfish_cfb.pem b/samples/dsa/openssl_dsa_blowfish_cfb.pem
new file mode 100644
index 0000000..8372cff
--- /dev/null
+++ b/samples/dsa/openssl_dsa_blowfish_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CFB,A39496D20CA5F694
+
+A9ZO/WPm319cQ3hoxaEsmuGVDkMVhCuRzFfSWC4hVBsxKHd3FIw8xZpGSkEI7+aL
+cMtcyxTQn4jVV71Sw3vyb4N1+2i+DAd+63l8LztpTBQi1o2gTBqmqL9esV3shqWB
+JV7uyOi94olPea0Rf5PMRXx1bAZs9U0TV+5XHAQxM04lXRJajxiN9LBZ1OMRiUVu
+SdoHdXh077ylUQmgDaGQktWYuVH6leq7Yc9CF3nre6njFiUrpk61iPki7+/FgWzq
+vToqiYaWffy+1lB7sXcL88BtFaMWAOV5A48Mv05miTb00VbJqdKL+SDmu6j2Soxi
+Qk3k6Le0heXFHqqkURMKOrr6tepqKEjmy8WTELwMnuT5vNngMqDKpNyhdsIEJW69
++L0imi4fWIelCd7PMI1bbPAp2QsB8Rndjlfj3irVm0AtubL/rbep3JT0ezukoScd
+wLYNTlDdaLfEggry/1kYvPBMolU4xqDxg7C0quwYxLuycEFzU2QmWNtRn0xkfx+j
+ruApr4getT6q2fJznW7coiW+OE9Ik7JgtYUGEZuWFUeydDHa9PiJ34w9t/aw50Sk
+arATzKH66zM//g1zgzg31SmziKeE375skyQr2+1S9RajmdZzEUDL5ajsdrbALflf
+UPQNr0YEF92DRHsI4O39L/+k5fesiiU38u0NoKv5DDRb5T1lQeesDZCZBowQP5KP
++6o6lnj8kCeccpGX/eUukPXFl6mdddAJ/vLptHC1zaRp2dlKPRfedZkRm4Wduplh
+vQ+6oGqkjep0Q/LSRcVP69m91CZot86lAn9Ct0jfJu8o7Ua7KBeOB2k/rx1nUaZG
+BOjHQRaSvPA7FVKCP1UlT0GR2hTb/VcW3UQJ7fCY8E4hc1kPfoa/T+mf0JrHtlMm
+364YQh6KLgcsgVjsPBXnTN1+POH0Qy0xp/0VwQIQFWKwU7gsXprfs/uYx0uD2Ev1
+w9kIWLovIGmBh6HKptqTnjtdwhqueez5kb3MkrCMi3kqVmV1TEQoklz6eBbloXbX
+SyR5jivLmuaoCJOA3oQ/A+75bwcvUP4iULZbdTpM2rnURyljKNU9Hwxim0neZ0Zv
+4kiOZuhQKkGfj0gv5bRkDAZC
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_blowfish_ecb.pem b/samples/dsa/openssl_dsa_blowfish_ecb.pem
new file mode 100644
index 0000000..58acd6f
--- /dev/null
+++ b/samples/dsa/openssl_dsa_blowfish_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-ECB,6105920EB281329C
+
+ungL+71R1VG+DP1CKuROEP1pESqlLeGoX/vupWbGTWR9VoK4v/9e1Bh96r+hEobm
+LvgsV1xhWrnyRMMw+W5bSJCfBH627SxqHltgxPhyKCNAf76cTIAdxxXgLZAxjtJi
+mjuBDTNHdJ8NiAxJKLL6dr/hh+Vt1Lk9Gr/x7UdocQnhxG+IZLDSOFdXnFb8EBtK
+kmAXXyOL14Rerywi6pmbxaculi/CihuFm4u6GXvunFjtP33eObzKLRub5ktbCtol
+97rbDoAAUsPPm4efu6Fs/3CE/BfvjUf+cmOYu6pIKQil9VHtxXloXwkeykI9Kl92
+uZVT+e9WEn6oZslAzCnjT/r69+V0Bf06AP0zkdTK7lRNBhmcR9fAgHpxz52GC2Bt
+xsqEzU7d+adCy1M73tT+bA2RBUnbA6BoCDHkvtmZTGV4mkAv11tVxU9Zqeglvi/w
+6QVDQYo/b9U8GVkQFo0oh4xNaAUNdT/i1OIy7d+6UR8k1S9+r6SGVwS3er20trWN
+8mAJ3dWiy3yLreggSqEvwHSpwrUQP8uxdTZOlFAy+xmwuEb3AgT4/sHQN7sJjAN9
+ISdzp+B5tBbM3kQgvEXUZckVykM7jgyv7SJ9DoDaYXvlfOVFo1oM3aWf57DcB8KH
+WIV94r4USVElJERYHH9sR61YtTi2lIi1zuAQZKCf3ShJcgU+vh2ZZ3vRPQhAMXjZ
+0Doi5uxi7HK/MVenO1CzNmsc6XQtyTtONqlJVmBoSq3Il8phMkMXnaOeNrQsT/1X
+PzbQ6MpWEr2WkKsQn5hNA9b8BIZ+cwk9zeFbhwLH5ewjO25BWJkFra4gGFJl+HZf
+vMNFjlnxuMjqM+Fjn3YH/O08P3nF/3ZGezqTCV8OJigB4Cdfbf9OrNtJSvCVsH1q
+YB/3+KOO5mKObH0Y+k1pvwZsXMkj7exAEHh+nFLldjo7tBAycqUHK0RaZ29TOjqH
+J6/4SSzMTJL5PF9Ayjtx0Vai4sFrjRGgnvdd8tddA/bWq6JC5i0yWIWjCEu0+b1q
+q8EHdE39+gbANJn2lKsEAOOt242bsjKR+bblijaaEgZXHZyALOThcEXxn1RaFFgC
+4Iv+DftZrU8lOiEvN8w00K6GDy9gbByG
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_blowfish_ofb.pem b/samples/dsa/openssl_dsa_blowfish_ofb.pem
new file mode 100644
index 0000000..2558ae4
--- /dev/null
+++ b/samples/dsa/openssl_dsa_blowfish_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-OFB,56A8F965C6533468
+
+91TyUkVkBxdl1ZXkXezMngH3YsE2cuXhiEFySx+dWZqFWcOQ3S6izXXqvk9B5sZg
+O95SFlZ917dU+SFACzB8dqwYo0QmxvH0zaAIMBguuYib6YZVCd8/ElX0vyEEo68O
+9V856HAks6w5WZk4zTC/75skb3tdLRWgG42oBlXHW7GsL6y29Dy3xvaWHJ3vpKXF
+HygbvR/TiSzhWj/jJB6V4kCQAAm99yyMxpmo3e4Wis5AwGgf9XyHJx0gUCeyNqez
+i6UJMGnYsHl1H67ltpN13trIXRcXTUDhFTadRz/suaR1R8IEefkpsnBEPnJwBuPY
+tUQzlolPKuwbPXFukpJrhi7It7dLsDsw5DUYvyOnHkDXJ4vFAIplCKdG0+KLaYKJ
+pXI8FH6X4M1YbIPTF+k1dhCAz7Cz+cEBA5hfJfSA4p7L6f9NBPWso3DDsyAbdPx9
+JJkVPtu0ofZHzYuD9nIhRsXjK9zaQXU0szLBdtGw7rfmPp3ftXeBcXDnO2ZdXL+j
+PK6CJm0ktjnUMKY8gpWahUUfImwebQ8+uQYv+NNn61rtfCaGQWMStXaNYgq54YLs
+D5ImRdvWm936tNUCeoik0yhPVlriNC4gKswRSUxD/nNIetsPl4FB4DIS/W5fvWZf
+WYKwW1UlpC/HagbUVIuZcOrAMFTG+zLYS617lzZh7Y7K87GJH+jVwgbYSbHHFWCp
+V215NLfofwlV5pFwq8djbeEnBhKi9SbGlZUyaZKKyDoIIEnwaxg8BoModBEWHyWp
+OUmw/v81TQu6RwJYxl1C1U9n5w4yjtXr5oowgu6WRYXwWXZtevtLkHrhcuWt21ud
+Cq42ojFrb0GqIcYWDXF3Wjp4nLZ4pIqg5kadpJpcFYx+fcL++Jnxs9l8Ohqwn1br
+/UvY+gTmTwnICapIwovVjN6p6cT6MAok82oemWPZNPYXVwVkGewCH3DWqfeRYsdg
+6gDWeIwyk2Eqn4bxFz40NrNZaLqcmQPaJVRReCV7Y0jQuQWqSYKkBHgFodf2GPMg
+DRqs7doN2MW7Is6qjyc8CDDzPcSuaqUz0gzohupDfD1vAtuoC0X6U+m/8NM3yuE5
+CKE8rofcKcxmFAr52CUUsJBL
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des1_cbc.pem b/samples/dsa/openssl_dsa_des1_cbc.pem
new file mode 100644
index 0000000..f6fb1c9
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des1_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,7D7F5AED62DF7398
+
+PvrGaVyP4qWxH3LR5bOjrjTZN9KEZ7eujPyBYWV8pE7+kBc01RKaHuOfntMncXPj
+cTvtvPq4z/Odrme5s5fem88QAoxB2BqM0VNviUMcCcAG+hgsYjYWjUDdSY+piAD5
+dhPcTHfSwgkA16c9pd+vNojdDKHEXzIci/gdrkJQXi9z+Orfb++NluGFUjAvQNlh
+n+wi72AVwFaSPfguwAtWAZNmL37dZO8VzuCTkhciHaJSZFtS1G5rLBIo4JzW6AZI
+PLEENN8fE9C60WYkfQB0PI27ksTS2xPF2b7MeaBwdPRU++hwZ2QwXH7nYlCWn522
+8wg3/QWuFIMdqtKaOjjlwvQxApV7OouRCxIFnolM8HvpZ7HvEVVT6oqcsJG339FJ
+Ru60QxuVsnz6ykuP2OoGTtGZNYo5cgBSpXrpUSmOp8HHblWa6+FSatNkBf5MxJvv
+pMRxcYJ7ftFCGgpKI38GgeBPkpv9Rr8PUplZlgnXkZl8trhjb0hzAAJrMqPkMQ2m
+rOgsIWF+gK6MdnZdSnY1DktPYSFCkfJt0BZMGBDXcbr8RKHeV1vJNWAPOcmTsV/y
+nwzv9EA1KHeMnT+wQ54q7jkRtDLIS+zSWt3qW0fJQzNR3BrMBrsij6GfRZ++PL3v
+4y9D+cDFVX6LMXUDLK8kxZ11A5rSuL4HROtNnIQf/MItKNK4Y5c4PAKAMGLQpPS+
+5dgmKiu6jAIKUVT4BOEjMJ0P03JZKQkPxVB9GgLQLGCq77vz6NaTWhJmz+qTdZoL
+JCvAAShdkVa5gl4hzuvKnmY9VftsPVlOUthuO4NYimnjZs6p0sXZKnxQ4J4BpbkX
+mX5Fs6RU0YTQphu2v+NFhcPpYwRiwn15CVUDW61Sb87HZ5xAzwQrlpFY0LI4TqE9
+6ITUYzgpVVAlslKHNePMcjTj78V2MImHlq7xHSVPEGkkPlsDWxG0snZRkmM9aAu2
+g8kqf8MVngWbWhxqXHA35wunnaBhpBxAgqE4r2yAhyfCJNF3B01zwjt4LeTnduj7
+1ZA6EPechsSQUGQNGBoSbO5zVbIQaRZvAl2MwPU1YWCCbjaiDDRp9bHhX8vQbI/v
+4TRfKX8FUSai83qORQ+Ncshg+gYkeCJc
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des1_cfb.pem b/samples/dsa/openssl_dsa_des1_cfb.pem
new file mode 100644
index 0000000..c3af8d5
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des1_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CFB,6215481F0FAE54A9
+
+4ZA2xcGT6hS0kQObPwTWmluIl2wTnoL2jRMbxrr7usOZSLYISprcATZWieEKLsu0
+kNNzIptFCmRDt0b8VlothTS2jBIh5nlu9LqvaUlIrVuMEn7umslWrLK8JWnHVKOO
+dMfqNcgmYlkbEfmmXLtlCbfQHT2kVlopD58yxf26FTQ+27l+hSX4wn2uD+xFUAcn
++9ZxAWQDhi2PYVKqTTPfhCPaKW7hjYdocADnIZg+1mhH++8fPxlDmBQBmMOid53Q
+WV9LI4Fps90d7GumX7qSUFZTkBKN3v+E2ahnoP2bTBQGkqWamKFTc/4uLCEGlSWU
+qXaGCy1AwPa9As1+B/jLkTstoslJppqvOooWW2R1o7JHqN44luXXQPZ+BcA7dSdf
+zRcMCpudB0AwHBy3mnUNuBlUjsf4rEpq51HPSS8duYow2I127uI8m8OCoZCaUVid
+msxVMSJIiDCiBi18EfCjMfGLtQVxJefMv2hmcAXQXSRDJTEw8Lrtm0Mtp7XK2B0A
+v8Kqpf3x+VBc770Xoy0K1/fe5oLdvJrJOLO5PVcVXIS9B/DTqIQ8ObABJPZ1sCKA
+sV8XebteS8fNXmFrVKBTmHBpUY8H5Z++VfDtKZZUBYSOqbFT+UU/+xJKlKICzFTo
+YWsmPTgFsu0Z7/PMyg/rccrb9fMWRXa8et0JGoF2NlYu+lkRb/nYPe84oS8RzZT1
+dtWJMiiom4xRgENDhV6/AmA9IuyXT3QbDfFB+ntdyk94U+Ms0ODNcdA4JmEa/f2k
+zFjtEGWHPH8Quit+zUt+8JnWSSFp0mjyA2ZtEj/6Qg5rqAZMdlpTo7rcuYOTHScn
+ic/H7V43SuMlRAM+xx1bGrNzjWUugHrVb7Kar56pSRPtSOQ00Dmz7gB8V5LU63n1
+YX3faatiPUNRG1dArcW36o9dZ5x8O5TErPHRJNYG+96UNoAzHMXoi5thuRyVbzne
+FpOqgxsryobcht7fwHuYgUq92QoY2qG6qMwHc2A3NrVFi8lJ0R83SN0lOzLebulu
++zDvrvkkRyH14uoAWi/o5IGBv1yIkO9vYApntrSO2aLnbevht9MuDJqW/Lkb579Y
+LG/sVwxTmBT6jdCgTdpd1ExE
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des1_ecb.pem b/samples/dsa/openssl_dsa_des1_ecb.pem
new file mode 100644
index 0000000..d17a90f
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des1_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-ECB,1040C4105685E404
+
+66Uasevd2pON2SFWljlVyWqmErfZn4XomzLHlUoagIwnQUEgCBCCpUscES98fini
+roGF/iaY59JnUCMieugke7/GZF1C0aXbIReqds7S6VFfu4Ni1OQTkL4rIauHrWab
+vgoE4+18OlWw6Rc0wwJ8NT/NCOmb397yTeb0w8VYERyzpwSLXxQ0BCOq4vOUX7BT
+2ABX0moazjUSyTO9BQZpABF2SshxaWFbAc3QRwH4QnO1bm7Pv7b1rvjrvPZ9LxgN
+fwjXG+yfHFBBojbEtFvgXRsSSyV5WCmAgYLgk5/nIDFSnRQGty0OuP+itX7SUK1I
+PH/ZjdIwezMKbyuon9D1AvdOEC1xiKEdmJCWSokm0djIVNmYbv4dtfrQE6hYdMtt
+C0LbsT7ef+jl0xG3k+WK24OsBVhTaqj8axIPZIVLELOPlx4EMfaFQgUjgqf5vPhO
+x6RSSRy+poFwtjI6ip/xu7ygqmcY9COXCcSffk1vpw9v+6WcMaYmDLwBTrTCNsdI
+7i6VJa1GiCrsn5o6ydGgdRNkF0N0sUfGnSzRUgd3BGd/fvxhBmcxHUnr8srrHYm7
+D54VL0EUsP33F1VF2ELl94GlWqfAj8NGBDkTbpUcqOeL/ERxdUWfX5IEc3h7fprs
+UjjjQ+d3GRliRs27m4ZuLtGeDEhDtlTC6qtKyqgVziPMwG46tcqyFzhbLCErHNW1
+07JcoDRc1LkXImSeWgjjhskUX8nc2/q5giTVtGmiWMQwEc7aYQ1wPbVAIGPQ4PE2
+XB8zvvPEaj0wXs0JjicrfzUBo6cRbdfmWIfp+ZoTUfr+gS/aZm+VYt1G7v6u7Qel
+AtoSdpN623OvqIP5ZDjOKROmAdMbXkxwwusVNQhkbdTzDYNy/yJnJqUUlhsN0VTQ
+y+O8Fz7Q7fEYIk8Euz3Uf/BTVGbLSNSA9n++CJYg1nam1S51WhCXRDckDLR0c4C8
+v3zpJvaQYW+xZUmlzrYRQgxkfzv4+j9W+kZLgvitQizXfTsuDyO8gwIt2csfGkaL
+EgX2+oITD/sGoaSoGknY42ePI3pPXHlhBjPq6ZWZ7uh6Ia90nV1j/PAcOEoAspAh
+pEdIAkFJA76qN9JBnK7lRMFXu/EWtBjD
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des1_ofb.pem b/samples/dsa/openssl_dsa_des1_ofb.pem
new file mode 100644
index 0000000..2d36cbf
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des1_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-OFB,BB20E846FFFBD3EF
+
+WeRgcZKkDTSxqvtZvx9WwUZYqXUUpY7siLG1Vm5jXPaEFOEQhmvGuNYn2cwwUYKD
+RMN5+sE51urDgI/xk6jdS9oZE6IlfkGeQSUoEOOfPVyVD/0/E2G0QTcKAAWB56K3
+setBb2ORbM2ZhetYUp1scaLObMEMQ5LrZaqtA/jUd2Pbs9D2MqafEH0Gde8e7mXy
+1fGNJWlj8XtAdmi2BeDKZHx5Hu0r/BOTic++L0Sv66wbjHw7RDji9Rdv/vyq6DIi
+0v0ZCexiNVed4mqD/3+8eGQ2z02UD7aZPy6T7E+b8kBuBi2ouB4HqgexVtz1L9x8
+VBBOBdpOLefwCZlNaeceg2kSIP9mMK919hlH472BO615YB4ugaCilUNLpvv9T85K
+s4hTB5oDcQH6W68mz44vWqSwED8JcdMYvivWY+3/zBSUvkyI8+8AErnVr8tvTX29
+aBhfegKV0MbRRRirj/EcxhUhtfgbAtllZ/Wpo0LWpIsHT0GeUfWdUerbFyh/8Tfr
+OQzC14xoLHdACDz5IDrLaLd87hZrKDJOELvzoSugg2W9NAzGbfoWJGVlvZ0miZcO
+teULyYcK/A7Wcba+jmFaXMrKVhNH0IuGcU+Pf1lYcchjAsdnrFMVRsNJ99QWlN0F
++dTyRgaiCInnmJqT83fI58dMmaJPpMeW26jItPWZWAA0vlQB1RgZ8C7i7V4keuVc
+0PYolX8WpLrrpUpJKOTdW6rmeHokJC46gOZoXEwZCSKUUgreROLgRN79RMBHKjoj
+0vSZWowgH82fNWYWQbJk5z4ldulWEVye3tQhRNsZarAWPFEteiKDTSkawmBpaA6q
+dJWiA+EdrVvnNmw5+xkbciMX0nj4xKsjRgPawdMFZaZNE3xu2LkrfGKDa1ne3JdL
+nDeyygGRDsl93oJ799maHaTLDyub0CMdyf2MssPLFklJdxwbtxNzbI0gt0NhZu43
+FDg91Z3hlAjg/Q2h1dVM22m3pnju2ygF11HUQdNExHlv5w8LWMeqWQ5j7WhSbM4c
+s2v5JURZ+jXFEf3jCs9h6pLlQNaipDkUQA/6DKHf0VbZJzKxBiRCwSP/YuQ6H3yP
+dHGRAd5CQnNc3Vv+yyRqQT56
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des2_cbc.pem b/samples/dsa/openssl_dsa_des2_cbc.pem
new file mode 100644
index 0000000..98d3682
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des2_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CBC,89A720DEE88FA71E
+
+ozUacsBZx7E1NCxbVYJJHQ0VTWl8RX0z/JzYNP58zcCIi3Cab2qlUshZP+Zb0Na9
+vlHabEqQCGsP8uLzneN6LDDaLmf+ucxKvCRrx5h8wl7DQcA5cAQhGofZuqChPqLj
+1lExS4ZaAi9lRL6aZhf6rgI/apkj+9Ky89sOqJxNhj66NgoOOh9XH1Uvrffv3jT9
+RxeVv5qYcAgfX4aIAM6KjC6iTZ8NyWmIoc8izYQycOsSAn6cqtdjmyc/264OZUd/
+1Tj5PG0q/Kinh9UBJ2F+pQgU4pDlWczXEIwtnmJ2mWyHBe2zuGWtP1uQFUIfwkEz
+KDTTFB0lm/00Xts+vGXgy2q+IvhqlOXfCkJGcP+OArLoyE8cu2xU4KS4qXUITSr0
+i3seUuTrda4aqrfyjNuM0tL/cUSEuT7aSlKdqSmRtYl9fTsmbCbndLKKuDJnxUrB
+ocXfuCEZNMQ/q/8DvwIX3l7RRIiJwqEg5+Ue/s2FTFJh4Iar/1gNQSApwToFHHhV
+XOU0pLY899B+1z10Nop7ELgJEKBK5+zMMBhB2t6nlMU3YojAH5qWEPa6D2Wr0Wu7
+x4DHqk0wEB6cDZ0PZGlWNOBP5bDB85GehAWKy73A73wYZCi9eCQnLh1Zjcjl+6T4
+fli2K+944sUKaUnY8sVT/20aXm1CRqNvgLknZMsg/eGZWX5F9+Jn/MviXmsH3LfE
+6VShEkNTFEsRUqF44Tvd2BZ6pObDPRDOkMgapzqdubujUesvb7LU3yNCRPBPngRT
+ZTXQynnbH0yfnFm6+0BYWtD5NeIzILwZfS6IRMSsCBMas5rCc7O2Iv0yhk/8K0f1
+Og1YH7pctbz1oAPmN/EgKZ1K36GTt33zfrwHpmKZ0jOWF90BQMgZ9dL+VyOMJYjL
+MiyetxwDdiP5TUUAKxXdr9t3AvxVPxL8aVjLb86kJ9HD+IgWUDqiROe88sD30Vww
+7R3sQhhl7drDGwUBj5MLCVhtE8Uli7HdaYC5CvuvlCAQN871whhk2gN27eqp81ou
+RB4kNaDK8qSn83ISnueg1jsQhUGy6B2Rx+rePxx3QwDsrMGf/u/tFJ1VcLlhmOJa
+svVKTMq88OAnZA1Hg6QlB03obSF9U6lJ
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des2_cfb.pem b/samples/dsa/openssl_dsa_des2_cfb.pem
new file mode 100644
index 0000000..edd5d8b
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des2_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CFB,AC1BA482ADC9EB3E
+
+tPu6t71kZlKyKaRiXgAMCmyxL/P6dVH/sPVY3KDFI0FsAGoPZaD8s7BkLLOy30Y1
+66kmaaWiaPjQN2g5zMrszrXh4AXazrjMrmIJ2NksNXz7aiySFafyYjyCPA+LIu/n
+KnfoE42KYEmENgMSUV9sh/nlwYS8I6LWva384BIWaG3qnFgfZ4gwgiI/R+1/lPXa
+olOpnI5szYMiV+som2E+I8lgd+Ahf2rempMnuwyWTDmUvYWwst7F5bz9XbmJyeWY
+HDDaTPy2Q1yRYBRvLTm64iA0J9j1TpJnSNm0uIRTVOEIZfOwOx20tFjo7RREunAx
+mEm+kmn4AIYhw5RQE5XQQvD42X4MLyc0M94k5pQHvgJFypXeJ4VsH8pkd4bqfy91
+qiPiKdA7nWnbedExwiwSPOhjOLkmQrXjsMVmoqqexhckJfmNOaXYtnQ8cZc50HjB
+6ccsjyLdQbLx1KT3e/NgfH4VxW4/hbbt3p0HMIxTnwt2lNG3AoKmLlOYSecuA4PB
+EE6oOauIKyJM8pwMV0hfBQ/MUQOnhHG+dbTn0kW91fRZiVPPvJiJ4NmEwD3ks3jM
+pLYZRot1Cd2ksJ79G4NXDFakB2bZ8EwtlQUrQHwW/ykPwiwpqCCha1PUzgsmG3hK
+U8bDWWQMqXtpSmItno1mF0H2TZzdbLpRAZe2lu8/mwww1qZfPE+MLPnCp050+BCw
+Hbq8fF1WVpJvsE5CKzi7Ll7bSrJ6BslrlzL4mFnnGmuz/mbBIL0MO24FNyVGKQlI
+hEzGu8lgp53pG4oSUZ+79CWBkn8mesk6iEOWcFojLKrlhnxZ7mDxBYfDp/2Bmna4
+lFt53zmQHJeYiO4J2TEXOQxvDWvcOK/SnAoLXEhUCRP9vTQm2Ahj1QMmEVvEybOd
+mRpcaJXUOgirS7Ulwc6ZhW7MoFFnS3UluI+gS0oXRW6hCm6l9poDem4etU+IsG2m
+4k6MoMLrak9lSheB1uL+xC0S9k20CZH0X8Hj5atb4R7T5+lTle/fVw1RGdfil1NK
+/ytD+CLpSV15Z6VGVGlzfXTIXYgCIgbZpFxOZk2tsdUm0dPBjR/ZhdUh4ofaxA8K
+jE8HLuW7kCkvmEfdsJxuRVVQ
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des2_ecb.pem b/samples/dsa/openssl_dsa_des2_ecb.pem
new file mode 100644
index 0000000..35c220f
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des2_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE,3D3D716B17DFBD33
+
+XDCVsv17xsOpLWONR8xKRYxnxvWs+bdU+2XCqoqH+cM/vR4+g4lqSPSAco0/LkyX
+q0/C7/BE7mN6fzUMiECYUKS2c739CBVwDJZJBVGbMNFexaQRmlSxqhmbQ60oalaG
+HZfpCLLHQvrOZ3O82aYuEfsbqJTEPkGm4lUn/5psQwudmu4qyv8GFR4wVpNcg9JB
+rDzesxi1aU6dgHSlLHrG5ot+lAITh40SCBQdwkcvixyDIi6l4FX2AyNrcQYmFGp1
+C3XaOn74ADLyo31Iy6rCb0KId6J+S+1aPUW2r1Xb6irI13/QYzIe8/fDfuyV7Ofq
+BKtHdu/oIfzl2X8BkuxJ0CEFxyyEE9majfItPnUEjX0Sn2PfOEwzq5LYYExpNuxe
+pHr9gtB+hSXC5t1b6ifv9PHErMNmBLdgLX/FT4PuL6URrn3LtydPcfW6XMkHtGgH
+zD/nnn8Kl1qXmkRbWHbREcOJB/O/Q53UwD26BsX+Sjwn2cfsgwQvZFzvmq/RwsCg
+Ej9FK80Tvn3ce+Kdt7LGUc9+KaH1OIn7qLcYu0Fhid/TzPCBPQffxpUJ1HylDaUz
+v1txJe3C//rg/42e5GUlKqf+/nzCmQeoaqZDG+VU3UKlngIYitlpwEq5fq/E8V35
+JeuHzFjYj0k9VNsOHY/4AqmEm9qi1yxb7WGINsysO+29RvfRD1bm2Zqhi/Mg7YBo
+8K1GowhW6uGFf+VCPORihMIxoT6xBU4xn2kX09EKrVdekrAi23QzslZXM6Ze0fxH
+7LlktJwah4/QFHwB5qXwmHq3lN4Nj1id+CElVZXjvbKvc4+mRd7VSn++05IFjTK5
+2r4FHifwpkGASJtVbF/7ZseaoOz9sHARx/MFSUp8kRZjOCzstWj6I0Fou51BTtRn
+1ZCey4e1eKVnV4F1XNdo27Aw9aZjF4Zn5hZfUPuUYBwN3W33l8FXRdYEoT/JpiQO
+8LS36SSZGVA0c6nanZoeDZsrPNtPJa8ANHR0QMwBDOwNr22uuJEG/nLvBfquG4HL
+Iy7nxBebe/0MXvsxK4OjjDzmYQL2msMlYffOABOVLCbtaPC/HBKUcmcpZ28WAzdN
+ArkPEcJFTgzI+hCAVG//uV59MkDnUZ+e
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des2_ofb.pem b/samples/dsa/openssl_dsa_des2_ofb.pem
new file mode 100644
index 0000000..d06c31f
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des2_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-OFB,0472499818A0CFA5
+
+A+t7NfS0c6IsREc9+AzXRaMGW5GR2Ao+WBBxXdxNJZ2n6DWTcNHYL1VZsnVOoc9z
+N2PBfTjYQkNtehp4LDnypbooUI8gJ98T33PLkJ0/L03fs5iEiULcrpBLGc9gsNoO
++f0JcI4xNfE7bGvtveliBWBsn6KeCdwrdcOXziWGQCge0pftf7m4HZ/t/0ISfjXK
+x3ftgiwrvLSnCHfp50xXdN4FGRaIj/V+C50efu/hkAaZ4rCcTxgEcvi+TKdDjmcy
+MfxWmUmeGiT0MRongCZB7XH6g4sI3nwiDASLzvZ2dBysLD0wOhR+g8yumSH2RW5V
+rTr7JQANZzdZm4MpOv2fMCHzDcKEtPd+OlYMHegwE3p0y4CLeYByT4IdyKHVLiWx
+lwAKtZ15VlREgXqBIgrtG5ooEIIjdlabIckAhRc5yOX9sXsMePRyPgQSnG+nSbQ7
+6Y1l+3XueWXjsnr6SIXI5wbszM+TFbZAU6d9tb7B63R8ancHHSUgAbmSL7QpYZxD
+oNYseUzgPv62oMbX9VxiWJ5ZgwzS+D0zGALw3Tb/YVTxI+/VZ58ITZ59I1cg26HT
+H3P1thNPIee0zz3zewMdILgQLh5RWkJhn8/oawDhVVPBba72uw2nGF2aXwbLWx7G
+eJ94GeikGHOJby/J4G+0D2lLlI90jP8KB2fVqHxENGKSMLjZFERGvpiPTgHxWcgI
+SS3ORTxuJDzqG3qFfMhFwQnq6tbOsny27scEQZeNMGecfqGLWE+oclqfKKDQDm11
+JUQnsnFAT3cNFyd2bKefeN9co9NS1UTUw1m3gDH29kwmggFLwSccTFobrIoh5/le
+qiaHdEdmd1Fvp2nMAVufwmb6G1dizT37benyr5Gzc8CHZUMibFEIhjkmG8RQ4dyb
+Byai6j2gf6rzsbKiVtKqgCgMCw5LG8xypzitCBc0+DsYBnlAyS4hXYm41eqMtMsF
+vrP5uS50iDbAMBjuIpWdlRewjxEqiLPZofjbMGwbrvDu45LQ76rwLww5OUj6567b
+FJRcXQdyt/bWqB47GnAZq8NABCtY9HG77nTgqstOqYOOsdkuZC33JHAwTwa+b8tq
+2Y7Zo35CmITqLxfjr2IT5Yeu
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des3_cbc.pem b/samples/dsa/openssl_dsa_des3_cbc.pem
new file mode 100644
index 0000000..f73edf1
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des3_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9BF24F7ACA100D50
+
+71AQTQlq7BkcUMR0+Ghc8O2ykT347aaFUD9BYHXBW7SzEq4th3itEQQ4QxflbgR0
+2XZQE+dNK+s891XnEkf+8ZIIQc4LKr4m3P1t8UeAQvMbHRfAQ1u2/fMf5xwYMqsW
+BscjoQ0lFOcb69nb24E4taRu+MRDF2+eah2hlbHGbsTezIm1VzFRX2C4mnWyfffX
+2WyJQPlZpvOY4kkv8tRvW+nbZ0P7bRjjxrSbCeUVI8X3m0fiCJ0fMVg1MMaj8JxD
+AgIKBBIJV8SYRw3NqiGk/mIlMq4Qtl8PWEFBRf30DRD8RIqOO0yV9Czu/u1hcmxN
+x1/ZExbwOFAFwE/GU+NMegFRXC4toNIU2Xo1C84URpAvVAwwe6SiqWFTSTEHnRu2
+N/tfJlaL2yFrfRnp6mcNN3T8Rk376skXk1zml8Deh6rNU254yK2CFRgm+79W+CeR
+Gb1wxDw0GQ07Zr6/hNBfpAND4qEdyxYAfJQYOCufXiFFxWp+99TGKN4T/+Ab5D2j
+zKmpYFPJj2vuULLPGIJPnCVNjM5v2KwbFY/95Jh3JEF255TORfj2P6HETcjZr0pD
+TCk13jxgKs3mq98Vr5LGEJ4nUcm4GoZayIbeaM7heJTWmvQyP6PRZIDWi5mHs7K2
+wGUrutGZcxzLtaQkavQPf79xt+0CI9D8Nuz4FrKMS2ng+rWLzT3be46f6hJaX1KP
+cy8RLQfaWpFGBPHr8UKhicOpdbGjxxfBUM7Jlg2o1hQIWmSuj53SygZ/EQnqBV7E
+GG+Gf3RDl1Ab9ncOr2WAA5TOQ/yVBEYXy2W3TDmxuwf/fWvwF2z4DLq/J7pieEM1
+b1IuOlcDWNu6eKAhsrq0t6I/wYNB/7qOmIcMxn1dzDHjic3uO65IMH2swXmk7tuZ
+ExdHGutPDZKYG3TgMyMYk3W9YeoEZAjF3TodOYNpmtaDmftjIuxlaYzmtkQCFHGh
+cRlnPXJwaExSYrySX+1zsuqU2QaLB0AyTlAgkUdiLQOzfmHtiHt4Pgyv/o1z/PgJ
+VTVyu2IFh75H6CnSQGgNHIH6QGN3mcMIZQ5G0U2r46X+7+nnodOky09H2Gq71nQf
+vSk1M2ZoaOuo437zG8SlEuPKimz/d+PH
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des3_cfb.pem b/samples/dsa/openssl_dsa_des3_cfb.pem
new file mode 100644
index 0000000..eb957ba
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des3_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CFB,DDDE26F919588654
+
+ulZ1WOcK/yY3ugpb4uN9s8ejFImurz+p4en3zaCfEMdv93V0JT2T/49e+OvIMaOz
+4ShAD3AO5zOXkZd5AUDI5Oi7mMIH2sUmhiJ+0xZMWITbAduYvt69lCGFchpQ/YRD
+G4jT1PY4WQX9o7nN1EYyPnH/vx4Rk6lnOZz7UNpK51SBSBk9lkF/d3bH3J2+pYaN
+G8VET28OIVTs4nqNdu8nxoE8u/Y3aW3FVsFCA/ZhmBD81Odb4rHAHCqJl00ApW91
+nvpTkTjfF9+EfdOE3mfLA4R7CEVWaqnfzvNrVCOILs3qSFGKbIBPBBBJbc4d4pEm
+G+8g5gimV+oL/Q6njSi8s8yV1WWf/nqK6EKd2JJglW700V8dbGHjhGChNTM4Px+C
+RfTF+kXcQZpcsax5ULUz+4KKD2Ub5EcWumg+LAe36VVTz/zDTxhTzsm0/iN68KTM
+jzKjIY9PkVIhZikVkp4s8pL97rL9Tota4OGMacPx3C58MSwJSg7fdUehAcnj+GC6
+Nfi+iHxVpJP4QnFi4BotFxlb2FoVhoh51YdaUehqD0IsoBxrQCmT8nVaz9asJMCY
+CRXNO/2pUpNJY0iGjHfvdmT/aRf+gmat41bX/1r6Xxujf09JF1iS5v/fpYQsshZc
+N+xysjZ8Bps2Kx57XSUTz3NrwMuliJgw6ZbDYBHGSSl2lueUanNArE4iLakuf5BK
+zuf7iVNTZEww904RhnA3HnivRH2b+Q1mWxTezSYZTs2Qr62mJ5ewiFjOlv6hPUfx
+T8/ka54Am8dHsgc3LUDK4pFFR0Nk82yU52FJPbGsggKZAde2tUnDgup6gNmzEjA7
+rSWxEfg53fHda79SQzrKaPGsuWr5b+cl20rGycqN54qZafKFah2tfCzgGdVZG+Yn
+Wq5wvZK7Elmjz+URvKitFhw39yscj4TLlEQ3K/jZVu5/lsyyu3imiUholwMCSuhV
+fg667XbT1qSw8KPWoloOSDQr60d2cK8Olg9DjfMgqmDxVHMuALB+O/dhJq4Jaa9c
+e6ycERign27Fv6j09/aAGrsaB9gMXCOmMhYGSoBUptjb2dx8mN/z3fEG9ykvaDiq
+i1+9GnfRKIYzfxTa3PCpA0B+
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des3_ecb.pem b/samples/dsa/openssl_dsa_des3_ecb.pem
new file mode 100644
index 0000000..1dc8182
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des3_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3,695F5DA31042DDE2
+
+dzOyRB2M6CfzgilwOWNhrea/0Zt1EmJSCDPXO7kQz0LpP3/keHgFL14NqxQU6puh
+gYn8TKE+H2f+l8xoNhT6kdRI5OZP85NlC/RvzcIPJkriBgMeLwsRCvhxg0EujRa8
+popm8yF2E8N9YPdz2CcrUW0mttVYeSy2YO/pi5rTJBeqqIjqFYjHPEmlnoNqboQk
+aflRKFw/rZgsE4gzoMKR/yso/GmSIXj48h9G9CyLWPFIDi8LdiiBG62wxK1TDFDI
+FIcU4KY8QyHSYc3DdYJJM2kXxvSy5BxbvWkD9cZS9+CuAvDyGI9dfF6g60f2tCA2
+AxIHRn78StCNbRN1xBfkqw0BremGo8G3H8w6FrdeS1rKzzYqAe3XhDO/uN/0aRAz
+Yact4CIYbZgMRhTJh6YhWma9UfYtxslmTNkxmMptS2SvOVSbhPFSQJFIVWaN105f
+HGmLwoRwV+Xd7nLX5hcR0Sozr58m/1FYun4c4797/bcGA5nDKQ9+u/GvOtqGhIU4
+EY5mkMhqt4MdDdKozQvATqWeSlESIFBZgG5sAQWuRJ9g2Pn1N2GTveY0ofIXV575
+WsharLOALP87zUur0E92LoBrbFAS7/nJ7T7F1Ye8ZoG88qs+vJy8SUVCrDjUqfgL
+90YHTKvmq3fJ+DO+40pLU+aiRBPin65h+5J0jW7f+eGpJV1S5dxIYKW0D1+PgcP5
+URVYuN+cGWROH4DN7zyIFPh1lls0GtAf1to+zBy9QYUFAjt2lB/oL/d8RRso4rHG
+8cUdXilKzAApI63nq0pKN2k9hAH5wGzxg3vWJCbsrXuqExsgZ0EFLR1IOX5ISCCZ
+g6TKiLDDSFBfWKTsix169JzCCptFwE+u8lY1b0A2ApCClXeS5+HvWlC/vtkuqCKj
+V51xSR7ltzosktG/gSc6wesbp0RlldK3Ee1l5Ld3sgoxFZd8aBuMVVfvqz0Li0ac
+883Yr9+nSvc9WspdytrfjcbUxmWtBxsDtVqhuIM4eNusUPY/L6FJhfX2kgjc8RNf
+MNJXiMOaTmQfVCTmKZDF1EN+4IZfdrudL+UoesTzasdlDXGKc5gCecWiQpn/hKto
+6YwKToh84r1R4gDcQGM+DL6wa1W5bVbD
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_des3_ofb.pem b/samples/dsa/openssl_dsa_des3_ofb.pem
new file mode 100644
index 0000000..86f2019
--- /dev/null
+++ b/samples/dsa/openssl_dsa_des3_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-OFB,BB994897E99A8F6F
+
+Gx0S/6H98EIJK9lM7TBQrFejxjBVE0kcbBTVNTCJCuJ1Ik0s6+OqG1OFOLdXJWva
+M+k0WEWKhTAXtrrbzPiu01u+OVpIQ3xhgzt0rcU8UigfLLvMdqXoyuUTzCYHBraA
+ByJ0+Z9nK5r/OAJkq4gnRfhsDajZgOy8rZAdyIui9rom5emcx1GsnpW8WdRCuu5l
+kHEyaG5nHtUyZobZk1kNbkqelByCAFndV/eook4kycEytZWNPpFP+tUaXma92vDV
+sg3h2qODMr9ElrbvKYujOuFoO77BYM4oxlE/WtWpD29hmxaIgmnlvwUI7HerpZg8
+DbKYV/8ncRolxoE1GqO2dM2nLKaNKra+n5REJBpUDjwe/eV6dwcj5Uvk9nocEt55
+3qtmPbevuXga9mL5iTN8dm5RgrkzCX4LBu5fB3WviuseUBAqpKgq73RCutNM2gDm
+5CkV7Iar6tV+LgiUcgoo8RAnJbysFT6jQkGPYhABFKzdzrFFDDQUBpcLo6hgHpyb
+uQqjVXR69JFxdQpJSuc6cH60jzRQOvgwpCzpRiJL0mgXNXv51K87ucEzM81Z0UpG
+O4GYnsbo7PQfeLAE1PjP2B3xj8kgcRxWbHkQ/vIHTEAtJcXmAquULi+mNKAFb578
+qlBs77sLICgtpqBUzfoiH1ozcKHOJ3XB3yPYt7WKIxn3/rwqrgRDrPbyrrDmV+FC
+veepr8m8ZssbZjKy3z1js+jcvjKJOY6U/7Uc7IfZ6AjBXrkJIDEtn9RPoexG+av/
+P/LDsCF0ChhP44KZi5q5TLNvAmbvNL/7oogaSq9nw5hJYLiu2gScOAAv1h/j9yhE
+f2mz/xTHjr35m3Ax6wLPk2yS53PATS7XXQtWY8E0LJz7gOkSDvolwnyc5aRgS9WF
+H8DyqWi8vYzVLNd1qM1mAR55qrVhWnmlDmw+f2OJmP+6MNAoptW9nsUaeOk5xJVy
+QNSwJCjzp6ujIn5UhmrS2u59HW3hiW0J/O7aalBXYQxUv/qllKkrNmX8HlB/1r2C
+IniTw/Rd33TsNTBx8tqq9IpnAG4s51xHBeXT0+Sd4zNh+fIqAYLNuMllHMlM/oFu
+A7+h4TYAxEccchEha3GD6CMl
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_rc2_128_cbc.pem b/samples/dsa/openssl_dsa_rc2_128_cbc.pem
new file mode 100644
index 0000000..8a7d018
--- /dev/null
+++ b/samples/dsa/openssl_dsa_rc2_128_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CBC,B0CBF8975CC514AC
+
+eH3gBb3Shpdi9fkBr66H3xWR0XnIrKhPU1KABtoaYxE3N7su3duXHlx4zpc3YyO3
+s2YwjN64PdGYgFdwrznf97SjdI+MSJgu2wMxxTwJwOltEPBdbvNWEpq8SLdfdlDv
++zndoR7YnMIhQPp5Hch07dhwpY0hn3RELxYf32ALEbe4+xG8/LZWUBoKdgOn+trk
+1Oh0VB3eupjtsdxDWMMN3Ar+l/1AfdBoaQcHg3UdO52U+mTc38QAaMA+9Gplkz+Z
+YwjWz4tyltvTDWGAYGuhxTPVt3IoSewGVHWxKezFujNEhj6wuJBTlpN5T1pALfbD
+JUiGEmBXOPcxwa3QKmVKJFcA+p5eOYY15sqsIhcaXxPgzjO6JQWMErkaOnyB9sHg
+fQTXHwMau2HqzjOM8Qa/lQyv9nf45IFupKoTT6Kja2WzAVxd9KGW+NZSAa+okRSr
+GQrsXrJBFl3+wKpXN3alj94GK6aqCBiyd3d+pp2NyM9TorZhfWxbQamPmQVaU4aF
++nJjB+lW30wPZM6Ik4UqsgXolYXZCtV4cOaZ7g9ub2AYmYCA6yIagRFfjuEs0/f2
+MNN+qu1Z0sg0oCCpqO9kVcnnC4jIaXvU0egZVlGZ51GP7iR5VsLmi3VTbebnsvT7
+x8XYI1WHYuANsSBNRJj7vmrolzVErsX90FInNcnc7o43KQGyeR4E+vSdqoLHbk3A
+2HL9YLDV5cdvGafL6faVKFxUaA5CWCFVtrV6MPJAm/xWs5nu3wr6aNsDk/0R4mqi
+vzQe9EjkMprrihpXqFGpTaehJQFgLaE3FwnxPeUFawqdKIqaKf+stx3i24LkDSPs
+ukLiYS7cPcDYXN9kI6a0fqGtT/gL7NVa/jxsrl5+da/alvm/Ai7TJsUUi8dMzqIy
+85Hv6xWyPrwCbar4Ehq1CopxWvINo1AnvajIkBHvh4EtK7B51stOO6yNEV7spYxb
+nze92IMAtRNWO/yp/p/nccy9PB8/e2v41T8EN4MJuDxGX4k4cG0k2IGzBDcBM1pC
+YfmkHzMBGPsq3CQ85balLEWQTgR5nr/8+TabxyloED/Sw7mLM4gqMmn2KukzMxT6
+qeiFiGtmv2TbD7OWkaLj1Mth/ns1Of8U
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_rc2_128_cfb.pem b/samples/dsa/openssl_dsa_rc2_128_cfb.pem
new file mode 100644
index 0000000..acd0a47
--- /dev/null
+++ b/samples/dsa/openssl_dsa_rc2_128_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CFB,CB9482EEE6EC0DA2
+
+Bo62wJPRVVYQKoP0egdW3dLX4yU/Dbkx8TtIsNxNFhdwpGWtEGzervoU73+6aaWF
+LME/HVPUh+iZPKh9HuwSiP0GtwJzCv8arDp09mxGJ7XFcqz3AS7T+K9A1OclVa5o
+LwQ6ynBtCsmgiVlS/haNjeONqCtpy0kERgathUclwQCLTnQBZmu/l2Pk8Gdtc1Tc
+osmKc6BDlPOyofTt/UnrhVuZxasrS7tKEnVn/iZr5mjUZAqmC2mJcWT5YNahJpfO
+rawRjukIUOm0feFwov45+joTSIGDsNTYD3OV/+BF4ZgBMm33ApAE31JFoweUcI03
+2l+WS5qtmcwuOYGp0Np0BWg09KVwNbIghfiVUEjnqy55PCVOFH1RZrmHhPndCvHQ
+BwAaac0yAtd5vFWjeUf+pTbDmkA44g5f5aO9uQuB58WWkB8JCFpGZLizK4ISy5ay
+dE8+SjVGiMSZBDfAmiEokoYymc7L8bkTIl5Jo4TuMmtFcHnfohZd6Nue3aRzNZHJ
+E/V81IxIytHRlMl/dZjSujPw9FgmXSip/U1s8ESIVOVoy93HnaifgRfkkGggxp4l
+S8QqBvJTAJrQ9ygO3PBjgdKGi1XWvhH1Y5EwPJ6Wor4zzltftELEs1O9xfBT/zeV
+GENfUZZU+5V5ICm4K844WoiTkH5OIWAi/ZLK9XRqchaGWvMpv9UwBy3c0KOx1O4f
+j1/8pbXDv1iey2USNL/Nbw3nanIG0dIbUZ2g2U/FeKtfCfVHu5LJY+v6njKl58X4
+mthqvCZyyJy2U31MYUUDN/lgNffwLnzFc1AxYyxDZwviKmAIN+Ylh5jbxuElCS1T
+bpVd1+4aber+qv9Ar9G/PJEt9ZdHR3RB/tsEXv7ORke+fVzlKFQu9PKo4k25U/mn
+qfBcwlut9rMu19xsjbowqHyYJbenyrF55d00pp6P037cOKLStJECtpgir6HgTpo2
+Oyavx3OIH7ypvcyaqhFUqZI2EiGOdBwbSBp/jCqOrnAwTKo9uMcnmrsKj6EpjJzO
+VGK0DoieTEQ9VzGbqZKK34NHidE4j/MYW9lGKAADSy7Ey0CllvumHiICWOn9aJYy
+ObB64C3p8NFEcW5SrTzPtXeD
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_rc2_128_ecb.pem b/samples/dsa/openssl_dsa_rc2_128_ecb.pem
new file mode 100644
index 0000000..1ded3d7
--- /dev/null
+++ b/samples/dsa/openssl_dsa_rc2_128_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-ECB,4C5CF049EFF2E116
+
+M9XRNeRQW2K6U0bfpl3axdvsuTmsiFLkZ4C/76MLePY0HxePs3icSW82+t6awIpG
+gHfei8zevNlF331hGPW81XZAl8OaXWi+iGhIfKAInLKY//DBVI5dMTQUKTwBa87k
+oby7hLD+V4lVKr9o/tf2A43QjEkScVlxcofEnWUG84LkgXalsloaIAt7iu4qUMTA
+C1gTbkwex6bId97wvPQLvhFiOyrpsi5Nm98vEeJwMdb6dMNfLAd3Stjvhh5dGGaR
+BsRwDqgrkycYj6pOT0Zvg9fBxwLYeMk7PPo0bTEdY4itvpHXaRHcogsBJ62qnsFM
+mxk1opz6U0W9xKSNTCwLzg9xinRPXGDP5jz0zqE1nlQ1lrsPcsY+omKdaL/SGYlN
+vxDbm725eOoi1H0jsTGJsgcKJ7sKd6LTUEIAEsUvRAN+ro2zLhxteDP+gpCxTNRr
+ElOLddlDm6TB55lBkZVrH/0k/QQQ+L0lBi5Kgg/hE6oanMRGeKQvxhxRuBbK6tZB
+e0b0lffgZR0m49i3A+fTxa68lb6Lexggp6LAkheh6qOVAzSDWbk00fJ9SWNWO4oC
+9FNqu1yafLt3Xiyqv7iD1EOyGhYF8NDvbMpu+gM7qwbTPMjgXf9N9g+AxSbvrmHR
+5zGtJd+8BtU+139ZlsEv+cux1yxkYEypKm5MHfaa783b2zKuyOTMgOStvSOUgGhz
+c9dlWYPkgdgRkAMHzfIigHr9rQssde7pR7ZMlw75PxI7BI2ZF1Vj4weIkwH0SKFE
+fui/C67Uf78OHx4cVPANDk6cf4Ow8buH/vWjEX0p/jpOfNT9ZA6Otj0CyIQ56MjU
+L4nwFU7GqCbVkJtsHLI4sZmP4kH/3zuqVtwRTzQbQAWeTi6RCSwa8/amAStTPcX2
+WPRezgAtNzS1MBhileGuTP+opGdGOOp4AeCCJdFBzkEacRXylxdY7PUsCZI7mRSZ
+7AL1n9jbUbbgnl6zmqn7fybigjaTpLNSkVPOvVBxnNXxOW4n2HD4vA+q3a4d212X
+fWI+/y7mbYLLRs1LPPgjSLfPQ7Ye1Cj4KWy45Z9YBUtjdsEbaaHNp8TidgJKJuMJ
++sDQ3lvtJdIZZy26tzLf3ryE/+2KMTwG
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_rc2_128_ofb.pem b/samples/dsa/openssl_dsa_rc2_128_ofb.pem
new file mode 100644
index 0000000..331542c
--- /dev/null
+++ b/samples/dsa/openssl_dsa_rc2_128_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-OFB,F01B181DC9520301
+
+azqFQnexfYYO2tX4qlC6XLU2tPX5EdwOHsruz4uzVJmYFyRLlrgG57KkahVjWupu
+AHkkjhr9d9m/0/t2vFy5JEnF9WWcNA1nxqzfsaIKmnuCULzYzMWu1cFfTV2DZoAn
+npdxa/eYmcGRZ0u3aZHRGpGtP1y2sKvWmUInYCc69oigiEn1qyDkRE/tDAREh7C6
+DWRcva94GLj1igIHc61lBugZKBlchv+q8t02Ga1slM10QRg2dgAlF8uCPZe+NLUk
+8uOifATkKTsA8OsUgn9nRK9dH4FuZeD64NMCszOw7mYtjJ7YW0J0wYgC9BuEUcNm
+QTxellBcs/qSdi4pZWsO9JXxvoc0lTmvoiS0rL+JlB/UfubVQYq+C7ScVJeTUNKL
+6fF8hvfQzqDDjqx+qP4SgboAmIbL7tTJBeABnnhCOtaY5vSuT0l96rIQm/EZdlWD
+hXKcrhawaq6pqh/mV2S16e2gDRQyUX+jKvumTQhjN1+AkIb7EMR1ZLJFX1l343Fj
+5/V4D2+H3EZhbCdkz4uI6I0swDasUjtigcn19kOy5t1r49zpTJ3wxQptLRx4AXUZ
+zjVXVebGyFYSdu+Lks1VC9WDeisBW18kCg5IpOz3eo9ULBBQZnzSKS30OXlyO000
+/1Em8FPKSKYeST3SmI1aDObXOG/s4tyKTCj+e2VKROq8hDhJQUYUP0AgYkAnwURR
++XylYEfUrW9v758Kk3u82ZhEen/lLUQhWeXkzhVi44Lgih3Bjsm3jP5f7KO/5KfM
+UqECKIHR/p/H/klXPNmdFo919AFGcnxFjQCyhlv0Bl8FSc5FUkRl9TTLu+h5m/p2
+ONV63odsVGt2q/HmL+3hojX/BxSEP/8Mq1JHR4Dk0qqUpSxRtDw0XE9/LU6s9NZp
+zm6lkr5E2U6EN677bmem5QoxObNvc88EXGr0EvoWPnhh20lD3vQok7GBucnycoj0
+9NMmRUIflnj47quAGXI6LuTSzKqOOCZC4yNvdyRdil3DgyLLefr99m2WEe0HolDu
+pIyUsgHMlZC/YRVzqP/6DklhKDcvgWbBeqqhV1r/30rRkegHdsWiAEjmJadlBrJF
+szJZpa9obMH/q0xUH3AXXCkS
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_rc2_40_cbc.pem b/samples/dsa/openssl_dsa_rc2_40_cbc.pem
new file mode 100644
index 0000000..d44bc86
--- /dev/null
+++ b/samples/dsa/openssl_dsa_rc2_40_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-40-CBC,7AFE1927D7FEE9F6
+
+WgKt23n2XggL+3rzABzjmOq8sdOYfFuuYUzP6UNH3zdXRt/fh24/WRgRw+WCa5/l
+3Tt0/spkkMsgkkDwPPVLu0MUhfoUQyErK0F+8HeEdA82C7uGIgst4E2MS4bRXPR6
+w9U2R88xdUaljjahEbSMUG7JXecjL0WG+zLVDpDqMdlKNcMz1tnQbO1JNLZCJlfX
+ZlVPslMmTTxs1sqYgDhkAgh3FwSsKMj51nvedVCq2bAtSmgnz/bFDLT4c6N4iLf5
+MXP5ZUMUtWCac1hXayVw4koOkuPELKi2/1vWe7qDWJfqhKmRT2DV0Z1GKPjQp3Q6
+kGnD8oVxbKfCQDI6PSMOeBcWu40Y1yTbBHBFJO5+MdWsNOQI6CZGJCHNu2ZbOd+w
+tIcxZZjy5d4uY869PxxVxO8TmCRUn9hham6qfTw5Mmh7bOyxqID3fXlyrcE7KRel
+dlL9eQuLcA7wtH5vqpy6V28yWculvP7qmXAGUd1gqSYHUs8kipf46ecFwieCNPEH
+x/6hDl38UsuixchyyJTp5u9L5cKPy5PWXv773xcPguk01YhlmqrpTNZsdoJ/CTBg
+gal+o01rXd6snhp7IwSAppCPwh4YJumwdPjF6jUlmB/2AStF6kGaOA6BbJ/lQlCa
+cHAUaVlTZEyzSGShBGJUAN2AughiOq+2POgr5IgeoC0NL8ieMg7bMYjn7+Np4yZN
+KGmT1jZo7OmyVdh9mheahXTT4Axihfmy+uPTECuGjq4X3DVv79OvSFRpHXIXLnX9
+QkizsJKZc6v3FM6o5tbMDbJyelzaj8Xn8ANrugYMC1R4XImDSel6Bgxni2gHuTEc
+WrrILWnNSmNjz/yziFdu5VuQmYaJ1e50uenmOxiSQhL+53UzhhGCrw4ooAOSF5or
+s87oY1HO2aYq784A5UZVYGA6mYFjDDQSsbwp1LYomjoTrwoJML3P9x5SnaSrkEEC
+3Gm0R/t7SkdMmJhRc28uYarO2qdwyBuhoYRxw9Z6bXeaUN2WhJ7hILCL0KKZE4vB
+DuKxE/KgD8ijKpkUn+6fizWau6Lm5mqxyMyEDnCDkvlvv7DMoqZRJvVWSddNMd6t
+T94SaIiCDOY3SuQCi1361GGbVH2dXH+X
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_rc2_64_cbc.pem b/samples/dsa/openssl_dsa_rc2_64_cbc.pem
new file mode 100644
index 0000000..4a1ec98
--- /dev/null
+++ b/samples/dsa/openssl_dsa_rc2_64_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-64-CBC,6646FC6A291EFE41
+
+KWLSTeo6nX30rQ3WbgL/13WAEMCtaC32ksYorVhlN4ijjiDu5gEnmfLRNYK4c3LH
+IUJawIdZvHSVxjrKNjmKA18w+4kedYCCL9NbNswd5eO18wldFR5NlSI2FGggzANN
+OwJoHUOXggYxhc2/xbYHpQpl7gvJqZtAjyewyTDYeTC3VDFoB/JywQ/8vv1MN8Ce
+Zx1k6preAQrnqo/LEIm+GPUa9flzWZlCGTIC+obNkjJGZPuUKLM/1TqNsrum33aa
+gFwnz//khQULylIRwxfuOMCHTslFmrs/7MLLbJQyTa99S9kc+s2VDlaKWUn0BVe/
+MoCseykcuIcskavuj01SYySJU1YHBTu7RvhuYO8AQmnsAP3gWQUMvKy9aXmzsoC2
+0Nk3QCZiG+1hN423So4NPOh42OWbqrDls9PKhXvQ8H+58rAxW2s7OTN29Klo39ek
+w8SFjMEtt9kLNpwBCJrIlolXvhD5WQu6XbqI0CtoOrh2Ote1c4uN88HyIUi1Y2Op
+QsfLkKyx7yJcJrz356Ab5lbJKVpKJW+frEHI7rLlfJrj88uzsh1B7oPL/4fhaj84
+vNUfadRJ25ZivBiHHdUTrKk9CLsIDS/1DWM6sDclYjXiA7kgGNwJupOb2L6VEKPv
+eimiJ9ooKq00E96Dc8s23FteQqySNaUAcqDnAkS+ck6pXQECZs4uD79k4pck1SX4
+O20OIPo79pzcWrmYOrTIXH6ttOcB3lUQtB1fmcMT5RSJYVSKtgBxLPKhLcL18xfb
+1HbDkpdUqS0R/nK7ecMd/LP+UmMKPUyMUTfTUnlXZzsNsgIBkm1eDn9RkOGaV+oc
+wau6FWmxVSPs9Inb+7A+B/2bP0qyYnciKX41I/PClKGitm52ScJyrEN0XJhQ0O+C
+mPp9weJI3IwpDn/Mc46NQO9uk4rC2P9o1zfJXC38PlEDEC66a1Y6SEQOVN6iYkYm
+rVytxWjD4o5vC+GwYJPYrmkOg/SQK1AlK8TSpNC5TeRcZ8YIbPLRfKRUQvUVtFS0
+fyPK9zdariwubkiG1a9/NWCF9gN1/DPKFYy+p5Au2ICD0iTtOND9I/Yw8dqsjzsF
+4jhYQ+No+ytLYc4Zo+8s1RO7yduFz7XQ
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/openssl_dsa_unencrypted.der b/samples/dsa/openssl_dsa_unencrypted.der
new file mode 100644
index 0000000..32e51eb
Binary files /dev/null and b/samples/dsa/openssl_dsa_unencrypted.der differ
diff --git a/samples/dsa/openssl_dsa_unencrypted.pem b/samples/dsa/openssl_dsa_unencrypted.pem
new file mode 100644
index 0000000..ee815db
--- /dev/null
+++ b/samples/dsa/openssl_dsa_unencrypted.pem
@@ -0,0 +1,20 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIDPgIBAAKCAQEAyKItMopMK218pcmy6PkrMVXAv5dt07TdGBuNhVWpQ52ldK9X
+mL7CPKpo4Dy85EZRPvRNyOnhe+LRJZ+ReKntpEkEiar/ZsKVkUthPsiUMpoM5S79
+JK8iT8F9HdFjIFKaXGySBZ4xcrj8HQ/v75iolYCso+66Ybgjs9/nsWS0UQyGE6rc
+ibx7xPAtcbaGZUBaBtdkNER7+P2ueJwej89aNZxj+AKuvrWrArq6/5zOIhGR12wQ
+EQQjj7FQ66ZFivJ/AYsv1yXDS7mZBNp5eMuxk8Kmis/++HKcP7tdbVRnlfTGdBuN
+BMyOcBTIsE11jwikcI+KIbr9cEZoaikkm4KyuwIVAP4DZEC+/JZJ0PHSEtJTt6uz
+yn1hAoIBAHhLbqDib7zqaFBrNnbaBSNiltY3GxWM6uQT88NH9YWz3wXRb6i4KJFH
+9NtLbK0RF7MoQVprJY6LuGQHZ/e61Fs2EabDwT4vB2HT619fVUvDndbuSW6qfUR4
+y9kbG7zLkE4Mnym/ikmUwLABLA67cZUS9yjtcRXGpOkiTAQfCGBeUH6nWOFEaWjI
+fGNMQ5awKvZhIvGyN4Zvd+mE+199s/kAsCKFux2Sq9tYw3qS0Tw2IEebHsHvX7A3
+bvxV6p7czVxlO9+O0w7bBTekPpw1BnCYmPyy0H36g/7aF2V70UCWzER8zT1Pfh7d
+3P0hLqHYzX375l/7oxuDawtcDAV++iwCggEASajPdllHVQ8JvKdPH6qDkjC5XJTZ
+RK46mYm1cCu8Q9Dy9ZfL67CcJBpwKVHNC3sXmk4XPfs91AZf/t01qbMJvCrR8NHs
+jRyJkNIaMyDeWcFmO0KmMi374BQpFyIDQ6mK1y9BilneZ6gHDdfHMsKniLFW+SQf
+9hlwlArIPYuELu7riJhNcuRUTJEfybDHwM4/ht0IFbyUIFl00mMdTrozk+e/esEs
+QdWbx2UBjNs8meZPivFbT2HpQF1I0qZhtn3e7jcR5YatBQ3e4abnu1RrDc73q7d4
+g2SYQK3PmIWwxiFhJQTzeiQtl5rKzEn76knAydOtPVRgjXWzHUoW6Az0qwIVAMvw
+thRrEZxNdxELdnwW3rpYBm6B
+-----END DSA PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8_dsa_unencrypted.der b/samples/dsa/pkcs8_dsa_unencrypted.der
new file mode 100644
index 0000000..66d0ea8
Binary files /dev/null and b/samples/dsa/pkcs8_dsa_unencrypted.der differ
diff --git a/samples/dsa/pkcs8_dsa_unencrypted.pem b/samples/dsa/pkcs8_dsa_unencrypted.pem
new file mode 100644
index 0000000..22b8e3c
--- /dev/null
+++ b/samples/dsa/pkcs8_dsa_unencrypted.pem
@@ -0,0 +1,15 @@
+-----BEGIN PRIVATE KEY-----
+MIICTQIBADCCAi0GByqGSM44BAEwggIgAoIBAQDIoi0yikwrbXylybLo+SsxVcC/
+l23TtN0YG42FValDnaV0r1eYvsI8qmjgPLzkRlE+9E3I6eF74tEln5F4qe2kSQSJ
+qv9mwpWRS2E+yJQymgzlLv0kryJPwX0d0WMgUppcbJIFnjFyuPwdD+/vmKiVgKyj
+7rphuCOz3+exZLRRDIYTqtyJvHvE8C1xtoZlQFoG12Q0RHv4/a54nB6Pz1o1nGP4
+Aq6+tasCurr/nM4iEZHXbBARBCOPsVDrpkWK8n8Biy/XJcNLuZkE2nl4y7GTwqaK
+z/74cpw/u11tVGeV9MZ0G40EzI5wFMiwTXWPCKRwj4ohuv1wRmhqKSSbgrK7AhUA
+/gNkQL78lknQ8dIS0lO3q7PKfWECggEAeEtuoOJvvOpoUGs2dtoFI2KW1jcbFYzq
+5BPzw0f1hbPfBdFvqLgokUf020tsrREXsyhBWmsljou4ZAdn97rUWzYRpsPBPi8H
+YdPrX19VS8Od1u5Jbqp9RHjL2RsbvMuQTgyfKb+KSZTAsAEsDrtxlRL3KO1xFcak
+6SJMBB8IYF5QfqdY4URpaMh8Y0xDlrAq9mEi8bI3hm936YT7X32z+QCwIoW7HZKr
+21jDepLRPDYgR5sewe9fsDdu/FXqntzNXGU7347TDtsFN6Q+nDUGcJiY/LLQffqD
+/toXZXvRQJbMRHzNPU9+Ht3c/SEuodjNffvmX/ujG4NrC1wMBX76LAQXAhUAy/C2
+FGsRnE13EQt2fBbeulgGboE=
+-----END PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_md2_des1_cbc.der b/samples/dsa/pkcs8v1_dsa_md2_des1_cbc.der
new file mode 100644
index 0000000..b6afff4
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_md2_des1_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_md2_des1_cbc.pem b/samples/dsa/pkcs8v1_dsa_md2_des1_cbc.pem
new file mode 100644
index 0000000..8c2115e
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_md2_des1_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICeTAbBgkqhkiG9w0BBQEwDgQILnlhJxK+WWMCAggABIICWNqg8COg3x5fM2G/
+GrG28BE081hCiuAlNwMAeP+Akp0UNVbWJUFDGmpuMPmOY8vXlPfSJFI5FzCr9Wt1
+PIEtw66CoNvjN59Qb8EclEx/DaEv7rI74zpqp/gSkufYww8O87fPPk+qtEr0s0P/
+Ed+8rv/BERaaRa5nPx+7XhQ/VFeWgCPRNICmSB3z5CX2lvujY9rhw5cdiEkARg/N
+YwFwnx/L/ogBVntWHRoKkJj77TXXd4+Wx8wD+kyB7dvKQZg4Z9DhQSlQtKoDcUeX
+SCLdd9yRiuixDXGI0XMThmMnRfB7G2bT/BfucKCWvlPn2fsZKsdI7QOKLJm3b+Ud
+PrHc1z1HAlHhnlaBSWux/ZFxGrSuPS03z5lYfZEDzV0uFxCP9r9QYOEumfuiUAEk
+uIjoT8vfiSdL/ftONMx7yOIBnuVcW0KUO1K3wepccGIaOHd1oYJeCNab4yLELu2o
+qannuyLofxkY+F5N4j6cgw6FOpB2LBHIEzKNmz6S6GJLRaeUzIMzGD0fAsnaulx2
+HZqUNJRnPLPN721Ejwu14Dj2O1r2/4GpVUUzJu7ZmVLPHbfQxXXx8hy9Gp+v3woQ
+D2N1qjA6E0YMM9yfEtPJhLYH6JWG4t0X0ThFKe2ATIdoMFq9Jou9evksLrjNcNGE
+L78pgcuQ98R7YniY53t2tBpwrklrfCN5RMUPIuCM6JfUKyZngnnwPFus8xiwl8b3
+1Cm9fnlQkeZDjG7GkMuR8SIfydboEg4RGVdvdxlA9+hoybkOruxIsyzNwSO+VLnZ
+7Xa76zHGwT42cZHEyw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.der b/samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.der
new file mode 100644
index 0000000..f811b8d
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.pem b/samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.pem
new file mode 100644
index 0000000..c2c9efc
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_md2_rc2_64_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICeTAbBgkqhkiG9w0BBQQwDgQI70W+LvOB544CAggABIICWEnwZx+DsIKrb0WM
+p/+Fs1/XRo6e6aVFMACsmmbBvWaKqRpdrKb1kfQC/Fnprq2m+PouqdZOBujXcgGt
+Z0wzGJsO/rTQivfAtxQagSQus1c5OrXBvYC5FlIjSIS5sPOjqhpF9WkcsAvp2YZm
+TBYbzfzMMMfth1FD78LDYL3FgxnKFZLvxAmx1JNJPOPPihDDSUFR88riDR1Fig8j
+PeDA86iMGy9ruApr5UXP9GRsli64HrhgLbP4EArTQUnvSZz/ADjljce9K93Ntds7
+9lUIJgzpGAi3L+dCnhxdQGLamDCbzNvBvdsWqStQCh8sCoKtvoAiF/B7Q/lQgNTx
+PE89LluCNtPkKd6sU2FwqL1Yi8mnDmBr4xVLECOlbEyp/rdLdf2D2Uwv6+7at5tt
+dUokGy6lAO6sAPe5bVoAbhiWQozfaezfL/SwAQRDzvSfeIx8L1OFPFtinTx2pKYa
+glzLFJrjAPnQlcwao7j+6D0gP/O5tgFkYmNN8LfWwocDPNr5/V23jPBJwi6kDKOi
+wmFgLu5/ZJo4X7wNnbXuVMBS770ML4TjbgO3hNZgaIqXD9AhrNhRCHPsdiAUEp0n
+I0xwyrQdYj9zjjuo/9uVJ9b64+wRtBIROTobTajjQKs/pASG/tLSDYBpkx1RLuMM
+BqSSyx7D8+r8iSBBVUDGGUcFml0PC91ACUo+KQWqHQ8ERbg/kjeAbOQzUfeknhWm
+8yh5HEc2WpD3bwSy2cbIPgQ/A2icC+LV6juwEDuKWCGWnJCDGzA1SFY/NOmBbCrT
+Mxq6M6a9kkf1KnJYtA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_md5_des1_cbc.der b/samples/dsa/pkcs8v1_dsa_md5_des1_cbc.der
new file mode 100644
index 0000000..4b6eba1
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_md5_des1_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_md5_des1_cbc.pem b/samples/dsa/pkcs8v1_dsa_md5_des1_cbc.pem
new file mode 100644
index 0000000..39c76c5
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_md5_des1_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICeTAbBgkqhkiG9w0BBQMwDgQIWNmWjbywMD0CAggABIICWHcMAiGPtw2iCZUE
+IbuPuw56XzQVzgDvAWYucbrIxXgLVKhoI0yVxpba8Vck2a1z1sTDmPVAd3VVFH4s
+hiKWfItjkuxkAKz2VbUeZRijTCIEAJiLSB29hIBEJSjYwjrM8TjjH/6Qe/iDJ5ZF
+lHBzawtL5DYj7d04vkvBfprbNdyzx/2ClIX8G/6GV290Bhem+xytPNv1iZkNE9se
+zxPVfB+bj40zFkWataAD7mgJdjOzXfCZJtyEcj1gsyALW+QiLUqiaDQyiB0ygjLQ
+BKVYd2OSHnvaCzl+hH+swfFXb7N0Bu0ip5+0vCdgvV3g3kbeFh4zLhU8PFd/NFGz
+Lz+ggi4VvXfoX/AeuiDxazKwyEnqkiX84VeR2LFhxosfdAk1f+kMmGM3WDOXo87P
+F6BuJQojPkizO90pUZthsY0DESqxt5Hno35VBNKpusOLDeKzqSN8onjZJpA8054n
+fg6k3qM0HLsHL/nur5NS4mSIeLMd9jWlNTaWn9ErHprqTYqHNdHn0pHFDBLm6El0
+7tUuGfOBbxstQI6RApxiIuW5JGwmvkHdlImZr0Dlll4jfjM96ybvAi8WkoMN2geg
+CQ1i22/muW1k/fmlKrGaqzPE11glsRcGG1jhp9EHwcbWDI2ZDvseL/N7PivDkdga
+QOEiuDv0bzNdpAle95OCAtFhEBxO9moksMOm8p5G93lAmvJvV5BAsZlzj7y7Tybw
+eKZnXGK3CfUXdaoGGqbT6G/vCHgpN3Y3833g/QMqmgRKwgZvhRQYJivR62mb24/f
+zlmQDSgtENDag/LzYg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.der b/samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.der
new file mode 100644
index 0000000..a9dfab6
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.pem b/samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.pem
new file mode 100644
index 0000000..5ff8802
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_md5_rc2_64_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICeTAbBgkqhkiG9w0BBQYwDgQI8PQy9izofhwCAggABIICWE4fHw0T09n+EgDG
+t8tPYTSshSAHYi8EoFIvqyB7DNnZ6goes6H24JN03lFF+FIvC6rwYq5et8Ugde4O
+Cyk90bDUBRFUT7hcc2zsxyTXvUaEBCCPfaVnn8TnEzaQi0UnVvuKiSvKJ0bBY/8y
+bN0O/yaPKppwpegumrrxABAf8muqh/jB/p91OPMuLrmtp01chrRNakVKOlz05zJ5
+sQ//dphwrUn/5KaaUjk7H+jTHuFReb4R4MvzEUMu+P8Xf4WNk6eFxlWsVWeuDoeZ
+1TruVIJMDW1khv2dsh+fGVtmIn7x90dKnIQkT26R7R8btPnB3WmLY1JYtZW2zmR0
+so5sU6KhCKI3xbMh4C7zgAxu6R+Et09HvpuOme6vjjfCs1A3y3F+f1OS0R35BVXX
+8pctPGCL/rlPwSXXx9UmDMCQYDhbfDJBb8CqA8/nf+I3X7p4A1M3GuXJTgC13E33
+Vy/QDLT3yUWbZKQOypDR/b4Q/mYeMJweaF/JJUe4oeNsVjSZsBL/NV4niRy9ZIcZ
+xUMEQx32k8K5V00S40BwgLUDsuncsVY4ME0VvE7eXhVtYwVJ590ay5QRhuOTKg9/
+ilohSE3pBDikP54y0ng0Kd13T18DrVgYxb+j9Dktq3RkMbzgctevIVChuYVJC/j7
+YQkCBjfNihzFDq1E4cCfTfhxLtPp+UjaWnnGvUgwuqxbRKcAKMKxL/Yu0/tBvjjT
+yxdptn61fZMGYNdx7XJZg0rpNo6Qseje1McTLrtLMrX22L2I1Ut1Mo2r9qlpKCpm
+3aZVBh/y9biFn8U6rw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.der b/samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.der
new file mode 100644
index 0000000..792669e
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.pem b/samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.pem
new file mode 100644
index 0000000..674fe1a
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_des1_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICeTAbBgkqhkiG9w0BBQowDgQI2I9eXNtoy3gCAggABIICWB1+Jzm6a83jaMaq
+1SEE+0zERuQvg60nuzH52rSQCGU95tClKJNalXWj4CrTg9QeId0FT0H4LMA2VR3V
+jbu0F3zeP2+8wV+PxcArDB7vVsIE27/8cGbqMzNJ/2bxxpUd9z5NfO/Ez4yCVRhc
+B157Fa6xjrMhE8a5kRZm1Cb+GJTwys1/HlpyeCN40ZmPvRqo1bOd+bUHpXDMu5Yg
+MaVuz2tne78HORpE20ddHyYX+X6I1+z6cJ64Jp6Ohc2cxGA/ihxIY6ZndAtYvHYv
+QQNTzri7LiNh/Lh+MHO8ToMjLkxdEY2jcC/3YHowiTA6ZaxjDUyPAXISj1o+5vW/
+hzCSbiJ/WO6aBu5iLhlMf++b2TkLll11PHeq7VbAE4Ljfi1mUQpsQR4mL9RXaKiT
+pxUyu0JJOPtYVlHIJqFl9mlq4dF+fBmGddrqHbZm0Dfkjqu9KzeeCVTz1wZoByqe
+r2sNFEEUKS1jLfPWytnKeEpAT2Q17BzmYZ5n/l4yEqjIP2wCkwVua90XnUvfThGi
+EkK+EVhlkxoMC07GaCM2QMh8pUVTXaX6Y2g+6JSvgl66unGTWgu9m23Py20mlwU9
+AjfOjq+6KTUCyj/r1FP6Z2qfigCVx6QCWqb/cKiCUuFAIuuLvat4CeoJIElqJqVw
+ZSZlzUJHb1jY4FrGQzQ37r938H9sxNZoUWZBdZr+xpfClbCsR6otezoiewFX1Hht
+SXL0nOsHRhXfOgTw5FLTJwU2gIcSQHZK5ulb5z+jLMuEzDWJueOj5gbG0DaDEwFq
+TYY6+GzHjmiuQnCNdQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.der b/samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.der
new file mode 100644
index 0000000..75d37c4
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.pem b/samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.pem
new file mode 100644
index 0000000..0f8ac47
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_des2_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICejAcBgoqhkiG9w0BDAEEMA4ECBuhyw497mDPAgIIAASCAlgVSYSosi331Kp5
+/HuB+fawVN8+6yIdh9F7amRjaJDcNYEisZDrWTmygXgEdEFzJaoQ1eicxIBVis6+
+V968aeRKcF1VtEdB+varexHsCKPv0TEEx8zCHUwHtt7z8F1oZ3ITrb6GNDouEqSO
+3wm1MGEwcx10632ePnLe7pozwjHEYStYKlwOM80qdL48evXRm1ZzZRW+XvzDZTaa
+XriWXzRHMvZ+kV53oo8JJjE+XPUKWM5RvAFOoYTn8f4hzG3hI8a0Y78wzwFFbXTN
+e5xu6YlefTOUnnmbKh9NPlAyASn429nMs0kT2Y/a2arikQImKH9NDgh1NOk02ICJ
+xbG/eFvbch9Yz9jqiCPs8LxNkpCHZiwaXi0UkKx7ayPISIST8YwO8+RfhxG84hzs
+Ub8+Xf7UO9Rnc3vAXqG7l7j325OtB5cvID951YRfWxJ7I3ZWrgswiCFnXYP+0E7D
+Lyd/P++9cfFs5VZBgvw4i71CsFvYzL3INXCYD4CNykwE9A9Zj7hZzZ+TUiybg67e
+5Yyw5xZd/l0aO5akDW/H7i3v81Ng9dbxD4IZ/c2zNp87R9MkKkASjrLt63DBxnRE
+Gc0bgIu3DuufwHjAYaL51St9DzlaF0lag+qIq0999R5arqTecRSggRdSCETMWrzN
+ljiAoU85VHpfUgFCJREtLmhGijJfamTkpRnhaGqRlRE2Muwnmi/lyHJnuxQyGkhg
+lZzPsyU2jJovg98As3GSVX03fNPI8rK+fsmljJgMlNaD1oJcWGo7MDuP1d9LRZYZ
+fdcquhQmth262zbNGT0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.der b/samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.der
new file mode 100644
index 0000000..68b0a1a
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.pem b/samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.pem
new file mode 100644
index 0000000..acf3660
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_des3_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICejAcBgoqhkiG9w0BDAEDMA4ECM6ngp6E+lnbAgIIAASCAlhrFWJC8cJUasbL
+3SAaPd9yEfDHIZ94HihcFP8XHWZ5wEIw6F5gQd+FZS6PRJwxHIiZ+1v0iUs8KT0+
+e348cNrwaySjdzzbwlMUFR9CecmX/3dlaOLfiU8X4+TaZ3nXTvwyXkQon0Z4djgx
+7KUHt95t/c+FP0pXGboYmf5Aj23CXV3Jquy2RUKEPueUuqQ34AstgBlul2Sia/p0
+3kH2k/KZiPVRoKEwnUP66IOuWi/M3EfORM80RcWzAiBWuvRao7zqxFeYolXX0BS0
+V6v9ZiVv9NeLHMry5GNQ08Yz6jQwJN0pdM3Dj8qi/2FL0B6YX7eWc56V3wHubwdO
+7xx2ogYWLWybu7180g9FK+If/mkAUtVGcxqMm/j5wbmOOE1w6BAYaSxmxAeL3kEu
+r3g5r0vpbvTyDOBixXlrxQl0xsdME27YkC9IZWn+WetcBheOo76a79eblE0Qs6pH
+wBXnL4ZTcBVxDFoO2AjY6stioqYFRMAP1BliCBQIim380K3mgjNFhZ1jC0+HFNA1
+RO/xFAs0ytM0UlEz12Jk9z1DwrNX5nnNLLsNm49AADlrK0Dnfv5ues2eI+dK0noc
+zdQT7IeKBHU859iSqmepwtygyImM5TGIy4gxGD1xqJnv8cqFKE/ormCZBhuEI38O
+c7xXqeR/MbXE1VdV/M2E4SLvGmC738+q16wWG9kzGPcgk4yGzsHOGE3aRkaSYm1O
+ffekfyJR4M0h5gO+hT1X1fB4SToEwx5/+RIUTsNLl9+PkgZBXDU0rmW5hYRZrL2a
+RaU8WZui7X7WWAB3UrE=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.der b/samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.der
new file mode 100644
index 0000000..f79b30e
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.pem b/samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.pem
new file mode 100644
index 0000000..3dd4b75
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_rc2_128_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICejAcBgoqhkiG9w0BDAEFMA4ECFpivEsiPIHZAgIIAASCAli2TjjB4dAYatF7
+PLjdvx5RjdCm9l9DdWTHrSb4YVamt51U69itpQbWAk5LctxkNfhTsxsy1asZGSkI
++7qB3wXl3vycPQAyU3/jECK6XM4ML6OXE5fZ8W09ump/Y0yhQcj34unJ78T5T17N
+k/T61tovhh5HYDg+IcY63ZVUy9gllpMPavPdS1H3DNJBeV2+AMgOc+YmgvHYFOpd
+WcRGFqMe7QZ8M7XG9ru3S02NVfpVjioFHQcbRe8F2YW4lh2MkYXwMS6b+LFHsQc+
+9PPHqRVIH6HXuK0WrvMJ2DNMMAK4FwkvHwEi5poiXF1MGRq5BxDUcdBbKdM/v2zA
+veiAAAr+p1mti+1rWjcjHPfpWGLhdOmh6sGTI2Cmg3Z49DzT+bgWa9dmvfBaZOYu
+JcoNAkVMTD1bENktIHkjdxJG/+St/9q+NVdaQXB4ZPfkVeuAvcmwUgyyPggJKjT/
+YhRaBeKYHisG6MJo5JAIjeo6bi2eAo/9mdYwYwbvXPSu22n4LCQIyVbfF3Thfatz
+IRTmRX5F8E4zHz1rG5A8qwVgr1Bx3sM53Gbpu2orv1vDw5MFX/K2/q7W/uMI0CAS
+RBCW5VqP+MlqEO3UzIR/AU/wkN7rMAryLamEPnVDfAFKiScAUDewmdnHuRz0PSnt
+3+KPLxPr+0V43AnqiJzVEQLcUWB5b+B3+PLaUg96fe86B6LZnvTAaY9cooFCCB8d
+/ehmeeWUMDnHvOnv7yf/7ZdaDNoiyBenZsSZoAVGu6gr6D4guqocWeAKJ17vbKl1
+c7dkl0vwmLaS/4S2Tns=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.der b/samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.der
new file mode 100644
index 0000000..c29f0cc
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.pem b/samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.pem
new file mode 100644
index 0000000..dafc030
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_rc2_40_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICejAcBgoqhkiG9w0BDAEGMA4ECJsw2lYbcvERAgIIAASCAli3go11vsjJ3Gj+
+XTEOzG1k8m/n7LqUh95evnpUhaS08O8a/HX5DLfMSrA9cAAba+TNW1C2VDAcvsQY
+eYz8++Bb/evbtv4YJiSgUMqKtGAR0HeAnS46JgqwNEeARCK9Z5aJSSXKSIaJX9+K
+h81ppHdBURXapFTTqlsLDS5m0MS7NGzKYx6CEBrjKO4qXlphQvyKatBbnRL1+xk4
+EPnYHY6uNHBVuMf2zuc4N6j03N11sjYdRBSOnBrwjAXrMb/nCEqhJXRNN/cDBqGT
+v/ixYBYvLzh0zxoW/RqpzhtXLyIrAKBaN+HATgbcacQJoIq42ow5S3jxE74IzeiJ
+rqnvJY5t40146oMjMlPH3dYh/8I5BHF6S4gpFSs/knyYL55VrY8yU1QC5frsS7a8
+wehrIqrE0WssKzuWhUCZHXQN1Y3ywo7GmxjKqUadhZtwdyCEUKWvaimI11ISa0rz
+FxYw2Sx43UBoOTzSagCwv2jHibuU8V59QyNakZvdYoy9VupIxIQARJVAkcGCLn2H
+TP8m4OGnzfYyqXJGfHqIu43gbfztp7qDnlXCDvpI26T60g6vwtTa6G8ACV4K4evD
+x5OUE8jxA2mvKnV+STJOna4KGsadZV/j9v5MH63YI4DGTCVnDUVMb2/MlegDATVm
+cFn0A0CA6TMA0MuK0FogtbnSG99FYdEcpw7zxO+mzWufvYdewfT4mHDhILpuZSpc
+qm2FO/OnErsZw4U4/ZKql3wUWAsam0vvHQekRAKocUHgLMoAvmLzEgW+xOpgUpbw
+HXOKalNLA8Jw2hQ7aB4=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.der b/samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.der
new file mode 100644
index 0000000..f51c856
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.pem b/samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.pem
new file mode 100644
index 0000000..a6027f4
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_rc2_64_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICeTAbBgkqhkiG9w0BBQswDgQITUmepoEoZ4ACAggABIICWHldPT37g3sHtvvV
+ICHi12nOx12AAv4vP1fDXzyUPp/PmGIYymbCC7gOA4XdgPnNfYcsWvq99nY7zoSD
+j3vbSk4vBa/8d5Pen2hmJO8rjD6jrLqMIofviIxK70H6CE+rPpbyhgO8IAPhm9cy
+f76yH9q3qZw5i0K9CiSFQHOaiwepu2tBgu/v7ls4DasNKP+0wZ7bNMHg1AxQYRGe
+kmoXsyxrAH/ndShv1Saqu+zGY381E7/QSzQyxGb5DSzB1qQ5n/QHjZz1dwRljXln
+YNNDSYUbXueMsl7kmuzZHGMhVmlcq5XH9mbRxgI1+8h4TETbRbohHwhWkO4on476
+Vsm5ty7eJN+QVptiXM3UFCnPyXLScT10xi8bqoJXG96HbzYz0D96SrvHpN00pv/5
+GSA0DWdF7mGVLISumVPG/rAxyCY+l4RT3wb+e1cozJ69YtyzHMSOLWKCRKi4pnvp
+l4cHT9vUStY2odFNgD8kVZSGEsLjJYlbjSeA2ODle0fXwU25c8AVhdIoZNI9LYld
+MAggWH24CdEKGC8AxPjVpStg9NTIEppqwT4OROyRnk1OSibXZhAfyT7Dm2rQc2E9
+CMWa1fExB9lPo3jyufeww3hBt5BTbV6xrKwFpodxFBD+FAzbEdM/8+W7jljaou7r
+kdE+5kHKT6YAnUeACRnsZU04h8ZPq6MzQ/wlR6179BjCgagQmPpIf0CfrUNZOrQg
+ssRgQ8sq7z7h/ziPqoqDaxEZS1SzQMoVuO0P9S9mW3hLCmikIUQHCGZ2ZhK17D5T
+bdVtaimI9jw7vHpTxA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc4_128.der b/samples/dsa/pkcs8v1_dsa_sha1_rc4_128.der
new file mode 100644
index 0000000..101ef9e
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_rc4_128.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc4_128.pem b/samples/dsa/pkcs8v1_dsa_sha1_rc4_128.pem
new file mode 100644
index 0000000..7e14a22
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_rc4_128.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICczAcBgoqhkiG9w0BDAEBMA4ECPTj3whspub+AgIIAASCAlHPexOq5Jioh4/2
+9/DdnqDmv730znWAXFC1oubdtMYGs8HQjAZNObYdgUHoRcao8/DqVLJ4m7LY0RdB
+lPGwDzCtHQRMNep2Z9CtNRhfuZ24/3F+lgfjgvZGOYVSVAFr43ltcfrRZlEny3+8
+YAoa/QrLF/viQip3JuiniOn+cwSQ70KZaE4V6PXiqKxYQ6+uZzB+c0HM3WIKwwjx
+ZKiDu20LVyVeApsPrrS2SUJs4EVYaslCCsKlvZ2g6fDAYQiiwX2u3/0f2jO5g5Hn
+HTaYTj19zpe4mx9K3P/d+sOTEaI6lvv7RVoZOAFs9ILNpy1fr/uvl8AhzR2UPvlM
+0jhNn+NNuSFsDwoD0Fw8tuMvXghcw8imxid5eQ2iFIPcUhH6gPtVpqtRZsnSsW1h
+pUES9TYSPT4QwDjXqrcjmbg9o3ypNDA4emCWLhUuIcqw4zAUg9ww4gWTZmKOJogq
+NqpCf8/OZ68jFpzutpDqRbjLIJfMONJ7jK0XW9gtg1PhrapSlfETZS5tMPaJqMdj
+sa/juRQ9mmm/K7Ogzocyhui9FpIcOKtR9mfZPpdP3JVE0Xws0/c72JxOa/dyNsiu
+Q1CfGNSyL899lLyFJ1TJRAfifcrYMMRbR6W/BCxEm7yO5zbdtuzaI7/EmSO0uQ30
+DdPICp+2MphPX6ASo2v+u5Ra1nvzhZ4df1ST3LEM8+aFeEIm0yGFNn/RQE701EBB
+e+KzkcMtcPlQe5tjdb9ol7FMZd033ET9+n0nodb97F5p1ZqGWCF55jgllB/Tq48g
+uL0AiLI0BQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc4_40.der b/samples/dsa/pkcs8v1_dsa_sha1_rc4_40.der
new file mode 100644
index 0000000..e49f3da
Binary files /dev/null and b/samples/dsa/pkcs8v1_dsa_sha1_rc4_40.der differ
diff --git a/samples/dsa/pkcs8v1_dsa_sha1_rc4_40.pem b/samples/dsa/pkcs8v1_dsa_sha1_rc4_40.pem
new file mode 100644
index 0000000..af91ca4
--- /dev/null
+++ b/samples/dsa/pkcs8v1_dsa_sha1_rc4_40.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICczAcBgoqhkiG9w0BDAECMA4ECE2PR4rrfglfAgIIAASCAlFpGatgV+VXUbs9
+VnqsgAgPIVvDn8FYT3rPeK4qMfNjJ2u9bt8cP51QPsJReeUFUxVMY4T0jG4NQjuc
+sw3M4jc9ukerdZoSDpF/HwWfI79gAqh7ekIziCTO7ZTiXKmS2SfQdEjpU7dHI4+8
+Zvk4iUskMgXayVYg+yaP/nZlBjVQB08TSvl7kxIo4dlay8J33Fj7JDqZNYEaymCD
+U0CVUvvfCw8ZqxVYbLIEGChu0w+Vjy2TvTm3C9iQ3vrGsYuSN5gyYwGXpOwCdG4z
+UfTZjUBu3nQQKDuD5Kh9c8aw7bgZbSVQFCW4yc8yzXa4nDqFOg9Akr3vBGhsrbBA
+ksi57crWE8pqa14D8L44Yb8bj1ceO2qPMQc1CI94NeZRiGsQ4XRr5fB4OT6+jd+E
+T2ceQkIVonN+808/jyInVmgCMwgx7mZ2NcNvrBFIABv1v5rkJwtXC/Or0r2nQgwR
+/SoMfreNBQhBe7Y/Qr9ayuQIels6omLP8pX7rd3ahR5SLPxRudjWNzaEzrHgRaiL
+nYeOtUqVEQoAr1CPylzWmd3xdhSXFNlPlCd+DzM8nkiy//qqHyob/DCwH4o/r18D
+kvg2q+HMCseuH/QbsZKLkTqAnjrSvp9CMEDyQ+XrCHrAq+YuWgjTCegIavD3LE67
+o2NKOV5GBoRCDWBIyjUY5fmS8To5S5qVWw5YDqk+O8L6iS+lLk8yiCaFiYM1D/Ys
+7VXSHCYfs3ZADRGqNUncVzQzsD1zNC0wdEXUYhvxkPUi9r2XIqDNN4Do0ztg34el
+AeTZ8rklcQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_cbc.der b/samples/dsa/pkcs8v2_dsa_aes128_cbc.der
new file mode 100644
index 0000000..6edf1a7
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes128_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_cbc.pem b/samples/dsa/pkcs8v2_dsa_aes128_cbc.pem
new file mode 100644
index 0000000..24c9ac8
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes128_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIVT9pRMUZAPwCAggA
+MB0GCWCGSAFlAwQBAgQQh2Ut0m0ZJC+riWEInObeSgSCAmAhqKgYzBa2hbJaNgrr
+K9xxqtZJeIOz6ZiRZOcSyaHLKmpS6FA0MBz6VDHNytKmZY69qzXYdspd8istAaJa
+1BzY85MFkShWheRo7aRc4fj1WZdbsElBfjUhUezZqqsFQqGblrPZZnJDyMNh5yQW
+r+9h+sGsbO8ZONckKHGIlQBoZmju+3IY17W7xCC1FLztUE3+OdUng9L97PSmIpnz
+2cYcFdQZa5f6Y3b78g+veS3XdEzHXETkpt7srpvSvIZy9HcCX9YDDseZBU/1Ny6u
+zNoGScH90K16oXCHoHzHmbJy4XsRcWiUnPqKIqS8AytoqD39IDCPzdoY4BTbgH6K
+zv+jQPzI3NaMtRJpEpOZ/546tDw5ysg4i6lE9KDg17ImA4hHlBHrSkVfhwhwDokm
+abONpmtFCCakNMggvVaiWAc1Mh2DceVIQVlDtItGtNZBOTfoGPXRrcb2+A8XljBO
+BRz2LEQIdtlbKdZqc5GxTWlyGz4lweIxRPu259oMuQr4dLGYx322wqT92o1VscQo
+NSG57GmH6lTEHASCuilvQq+n/6LfcaiQnF47Q7A9MFvgC3nJ6+LESuhXUz8EIn5t
+8xvxOgAVY7grbV0+ja+eBJXLl3PKdh8/CY0BGBF4QlmtTMczqWHIYUXygkA6E8By
+oR1uvNjtAT3h1VvbhFSo1cc91GnjPOPcaq7lFSuaKY/2rxphBb0OoRxp5pVjbf/i
+VpWP6bMiw9yrY2yJGcjDairL/BE5p30BnKXzeOtbaDHdmZ1JYvfqgWgqilNEEdlO
+Nyqb+J5VE5CT+fCVpchlGcPMDQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_cfb.der b/samples/dsa/pkcs8v2_dsa_aes128_cfb.der
new file mode 100644
index 0000000..1e68bae
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes128_cfb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_cfb.pem b/samples/dsa/pkcs8v2_dsa_aes128_cfb.pem
new file mode 100644
index 0000000..be7f84e
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes128_cfb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoDBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI8gVAKqHLSqUCAggA
+MB0GCWCGSAFlAwQBBAQQyXjtzzM4bHUQb2p2D9nT9ASCAlGaMXLjbDixyccz3TFC
+MOeSV3CmZ9RzfYFdZ01CrGPqXGyElfWhG/cEfH6DMmiAqtYTuEoYH4SkwJbvFmZJ
+J8dEGPAnHzpi0JBHsoxllJnoost8wgF4V5V/yAsklbts/EC7ZWVjekoAT/0o+Xxr
+La+pAYH3TAJQBYi2+mXTCsnRWMcUVQyzCCU5wJxAjoqmW9FFe6Jc5ej+eCkIYmCm
+569VwpinVhN+scLNOCc8DF3tn22ARz3ca1QyeJ74Y4hv4MCuNJXTJVBpeg6kzwAV
+ovB1hfRIoK7A2f4O0iT7/7NeFvXoUXTwQMWh0RpTN+V8EIsVaNF2fdTadj0GDnRz
+g5em0MTLuln9/4aZPQsyDqNdMTzo5mzXpdQk3tfGJT28kJG8IKYGkx1OcaDNN6HP
+uSjvqgfV4ZyEQm0spzWccyPevnrAUqwFjG9fBmbObLMwdMooSt9/Q4PkoCfft97k
+XwPVN+S5J5QvBxdTsn/nFXDUMIpfAxVfkSlcmUBemu1TQyuM035khznhdUkoRQvk
+fQiEMGx/r9RI3XfiNjIzQxjdg5TG2g1n9TTDg85GPedEeGpvQS/eRzfcTyhxnuHe
+rNWmkCEgqt6AsJS40ZcT5Y3wiDIlBjO/A/oItQq90Es+lblizBzrFgT4Lw3Pp0Aw
+DnTmpz+DfNNyFaHC/AOiNesKU1iK1SKwm36sjA3jQ2dpp4AwSYqFY1G8xgcHFoch
+2Ftg6igz2//TRhEFdyv4Odgtrqp17n3yqYel9YNjFSm8Ox1Rvgy9JioKqTwiq0mA
+FEHptQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_ecb.der b/samples/dsa/pkcs8v2_dsa_aes128_ecb.der
new file mode 100644
index 0000000..bf07867
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes128_ecb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_ecb.pem b/samples/dsa/pkcs8v2_dsa_aes128_ecb.pem
new file mode 100644
index 0000000..0ef40bb
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes128_ecb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIaU8h+/kZXn8CAggA
+MB0GCWCGSAFlAwQBAQQQAAAAAAAAAAAAAAAAAAAAAASCAmCh2crl4UYag/ZgKQO9
+P4M9uFFmCcrNaVkEihHZobQ65/H3ouOk5SY8y4A04i16Gt2v3cHuT+uj9JkU/6mL
+debfDvGDAHO9/9vxQkSqZzvYorc3CV8SSsQdtJNB7QVkzGGuSz50AG3OqUYCRUIY
+5xrFjwkgO/p1eTraXU/ZLdS79rFNq5Y9xpg5xLKONEIrOhNIoCfApW/fMiZ7mNo3
+p+eaqFwu0qYm5ah+ssLIsN5IJS4uX/TBi5QENJMlCGSCQP96f+SM/BNUN8he3Y0d
+SEj9lLaxk7x0fIEbkm2v7cgpTO07wGVwgrF5hduPswEz0vpR9hI8FjaYRGWTN9Ws
+nhCPTpDHKIpYTcWtfa0JyYhcQ2xGIh8oWKa31v8vIpey+f7g3CUmV5ehFANII8FP
+2DVl8JWkCG5Y1ti0B3yKY2m3b8OVFGlgN2OykmqNHmaW33VDS/L6C6qvP1myArnp
+5MJRjUTKL2HGwJNyG9gykpECp+DG9W8uHWNWhQsvQp69T3tDY7+V2ZBct92dXWFo
+4URUr0/6JnhSjY8c60dHYjRnMZHVtCpGNCiWEHohrKURtqV+SJBTOagGdl0Itef1
+kYQ78PN+rnjy+dvNCR4FZL72nhwMY1ESibDnqcelYePYH1nCCoXCCZf+u4lNJX+/
+3axj0xAMpbyA5D5NbWXJ2OFCAsMhFitWJ5TOcfRyNMlRPdGqZAsw7I40Qw8+GGjf
+a/G5DC/Y121Vp/MlzgXkPQCs3/C/Z/itof6NvVpHL0HA54FIKglQvryybBq0oiq3
+PK7Td42p1YOJ8Ehi62QJnVFd9w==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_ofb.der b/samples/dsa/pkcs8v2_dsa_aes128_ofb.der
new file mode 100644
index 0000000..e70eca8
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes128_ofb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes128_ofb.pem b/samples/dsa/pkcs8v2_dsa_aes128_ofb.pem
new file mode 100644
index 0000000..2efac45
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes128_ofb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoDBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIrZNAt1U6TfcCAggA
+MB0GCWCGSAFlAwQBAwQQidHP60HVqIm9iweIcXnC1wSCAlFyQKlM4PNky2ejPLFE
+GBoZZwMY8rK0RYx4SjloG1k67xZpzb2uTa/W8TSirQnUkpWJIk0fICCH/39OJ7lC
+OQ/XdwcvL/6dgEE7U7kK3snAfy2DuAJx8eMVOxjUCnM6T6aQML1vFJRgXoZRTgA3
+ua1OL+ilWXUia0MHmctnoEkgHQql0n1fK6U/mvZh4T9faaIwPwtRmhqVufkcIkvu
+64mijzWCldhyGZLBCrN7KhUnPRcfYLEb535+PvktSIW3LTtskDchZQ3RUneAf++w
+DZau4eCAjD3I7YJCPxLxoMpvzlJvMbeOQR14XxnkH+Nfh+KTeTYRDW75Qh/liXs+
+FVZpc9V8c2+1tRH6Biwt7WK9Yusbuvn8dKzGtNsxtJq8obLDbmfC0+JRsPRM7fXn
+3gAIAn8VSBFSN1Zftxyhz9Xt/Jm4dFUR6h2Xp/1QObfO35OFnbPD2T3L1/37SDxg
+SeQrDejyM0Hm3RL1MAAyFs0wXIoL5IGTCeMWSZUSiiq2Cuw3Z9AgljjhtF23CXTM
+FFH0N3926GQInmHFJfw5BHokY0uiz5T53getE7sbHYmPOgFG8yufJz517Jhebm4s
+kNr6pkvbbTFk4k+TEopkmPOjIRJqE4l8XBfCXBnQGpeIR8DEeAc9eWPuansD2+Rb
+q0S1k5Wa1BnpNmnlt+zpDmf8xbL4y4BSNqk/U0Jnil54xX/RcSeX86TkREwpcz2r
+urnox8sM666j3gEVBU9y8whnjOMEKYrwNQOiC1b9v5HyWDXHCG6SDS8Xxxj4L9Jl
+LxHgeQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_cbc.der b/samples/dsa/pkcs8v2_dsa_aes192_cbc.der
new file mode 100644
index 0000000..b6d73a8
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes192_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_cbc.pem b/samples/dsa/pkcs8v2_dsa_aes192_cbc.pem
new file mode 100644
index 0000000..e27d863
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes192_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIZmGICQBO0F4CAggA
+MB0GCWCGSAFlAwQBFgQQlmyTdrgzQmqR+VD8QdAHogSCAmDXl0vqwCjNFFHE9op+
+3sr+aRGYFeTFbwvh06ENmlxiW2FVZMaJM2BaZ9W6VkSrEUs6j5m1uDLloEsGalzp
+FFbgSUG0KeqaTflaZHdjHKtB0CoBzR88Ee8o0hcRazs4w1sh9QVx9PAOzUKPSpOw
+0og7ACKAk0q1doUu6PoNRURshI9nCM2/ON99YbdjeMPMPoFth7PEGdXiFzeWl88m
+kCb6s+u6XHUIrAynUNM6btpjNYeMqRlejXqPdEacTWLlxhiZim5hHcTIj7uihQax
+qP0BJVoiv4sfm7ktrszIfwdIIajSwaiekB9MM45pe7vp6RvYxKvd4Geny/bSLVvm
+dt505dXBD5S5Km7oz68vJIzYUcXY7NEi2VRbNzM2WwtO9rDQchiz4i1zvomtLs6E
+MqEZfhml9ay1bEn/fLNCJuTtxB8d5JWqZSOkd1Mtrz5ZgdpIMiuoGEM6VrdIU/PZ
+5oVU1tPxym3kNH/R07ne8+ILfp4UBJFqwKGiqKEoYeJPotmxZ02Kx3PUbGds6xSG
+DRkVfZj8/I9Hb3M75btFKAEqAYOQp/2kJsbqyC+Cr/0OCirrsc5jUmtiYQR5PRqG
+I0IWLwyT/uZS+MFQc+kxjNv92ciDaXDDN1CF43cC6CKIa28cCs1Ryk0DgE591MFM
+vbefGteomOi1BkIFjGOM5XHZrZPUnf/YFoKs1GTrE3szMXTisx7CndsBNh32Xoeg
+PO3ljMt8CtX+qtBwBnp39PKcVz7Gjehav5AbQM3cuVDNl7EWcBqYHpSHntZua2hH
+MnQADADRgaNknIy8LOSQ5pVD6g==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_cfb.der b/samples/dsa/pkcs8v2_dsa_aes192_cfb.der
new file mode 100644
index 0000000..7577516
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes192_cfb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_cfb.pem b/samples/dsa/pkcs8v2_dsa_aes192_cfb.pem
new file mode 100644
index 0000000..f6092d8
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes192_cfb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoDBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQItU3Io6IcujwCAggA
+MB0GCWCGSAFlAwQBGAQQv9xQKusfF5mrGHGN5+nlywSCAlHBOOksXFxcOKg8f5hg
+0mlb8qbw/vzLjMD5Qiz9Aenv9vMArtF9GNUxiBWl1bnJjEsgREuA794NhfDeShAS
+jcD0YwQLVZ9lPoL7Loi+icp1hu0gKHhfNxmwfQt+UKkmwHxP1NYOLX550xTdcQiD
+Cax+CFUIhu/7iBJR8CLHKXWFt7Wss1YdQQy489smzCKReZmeedSWTpDpXSAz+lYz
++RURI6jhV6peuO1ChDLJGvtHwWl327CqBfcthegv1OA/E8sGYXy21/8iLMOEdJHH
+sJbrO90HI/txx7trwz+9XcXVbemwkW7jfF21CIPUXVCdnjdaRMY1jBaNj0s9jvSM
+db8+9D4r7QWz9Co2KOx+2QoqUMorq6Z2tdsw+uM6hJI/3qUHG+/F5oRi0yx6sz8y
+NWSsahJW5+0QE6MeAJZElYDokSRx6154kRbYO3BPQfEkgs7BQ4PPmyJWAs155Df8
+E+D7XDbT51kaQwYGhzHJwCT+3DghkSd+5ZxEWVpoEfjrtq12cl0MTHmL3sX4DRKM
+y8INcE5ndxjCKekTdbEvNyK7yjwktkjwgJW5QF+n9TWn+zPFxvDHi5zhMkfpOhPZ
+jlu4Ci8LcksqiYf0C5mb00RDY8JWkDI1HzNNw+9cZLsjmlLs4IDQaSshGI4D7f16
+uhqoJP6p98BhnAE114iM60lW0E1bpguDYqVF5iDTWWpjed27+CzO9RBej4F2c95O
+/LlziWkRdxajvcvyBlR1E/AbF15NnDzFsy07jI3zpEndc3tYbYZ8RG7Y2PLW7N9O
+TZScPg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_ecb.der b/samples/dsa/pkcs8v2_dsa_aes192_ecb.der
new file mode 100644
index 0000000..772bf00
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes192_ecb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_ecb.pem b/samples/dsa/pkcs8v2_dsa_aes192_ecb.pem
new file mode 100644
index 0000000..a237a1b
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes192_ecb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI4eXCz1GJbssCAggA
+MB0GCWCGSAFlAwQBFQQQAAAAAAAAAAAAAAAAAAAAAASCAmAToI3InDEJNaUCgY1E
++sf2a+o0LCMAokx7yJNU59t1BoIQk8sP28lznNCRRE5mudPR+RbYcB0nqw6lYqHK
+e6uZ4TbrAgMd3cxV0PRS9nzyvy9VDfbZGjTcZQjQy5I4yf4NoXLu9+GXZ9ND20bX
+fODHItoQaYbOStB78DQ8ZPvKcv3h+YcDRmfulQEyNjEMfShjyE2wxJsAXyVOBC7v
+uDLUlXzYU2SufDg7n/vMbQuJgWWcXL9OIf/Fhxu0sfyh3hiw7WkojP07lyFdhPQ7
+QY8a5vL3MdVnYMlmkBumvwRkoHLZmwvSzgz39i5qFTd5E8cr/uJ7OoFLE+xQxBgU
+OOLGXXnMf6zpadqTol5jENvvW6YvzMLxPsZE+vbl7DP+XzlXpnEcfgOFJnXWyxFu
+NMdOOqbk5JNQ4mNc3WO5LtTyS4amDLhmnk6+g7d5daDV7CZjT6PvGBGX/M9UYTWn
+SttVV8cnljB+KLIN+s9n07v2OH1MLxyyHrIjHIIx4XC4o75tfJfqwGqJT9m9nna3
+OugtsIGnPMDfuSsFaFWpBo9HvJr9vfzkjuBeOzokzXDwdq2bQflDOnMZ+BcpF70c
+6qnYDGj/duvrYOD8JDcr0sJQYAgF7dTDtGdE72XB6tyYN6q4DtUV9M0JUwBxFBSR
+pq/J8N6vquQ9oDcXqw3NJKe39FQOTiGtEvYpf/Aa+BKybjRwouwhjeqOTTf6P0Pe
+GGUPjDmXe3lKiU4lqPZ8YgMyb9JplYwH5gx5cFhbjQBCWCAaJQGZgE42+x6vLLpi
+Jz139T6ggaLBNb1Z2sfhWoeozQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_ofb.der b/samples/dsa/pkcs8v2_dsa_aes192_ofb.der
new file mode 100644
index 0000000..e3f3000
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes192_ofb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes192_ofb.pem b/samples/dsa/pkcs8v2_dsa_aes192_ofb.pem
new file mode 100644
index 0000000..e10fe62
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes192_ofb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoDBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIyro6EoodcAsCAggA
+MB0GCWCGSAFlAwQBFwQQago17Qje81NeNh6Lb9K1JQSCAlEuFmc2phK7H+1Fl7cM
+a8bP4EFCg3cgwUOmqGZLj0IYwfHib4x+xVTc1xVjQMV0QdCru73o0+8+MpKb3Tvr
+WQS+kN4D3sw8WkOeTqB0zXQ6lHwZ0BVkGqRduLu/8nL0q5MCsmCSHDY6kd79Nnk8
+ClPTGONEiZOHy9Kv1nLWTClQCvtrtSNDqVd61Jg91s54L4Xjn7k2B4rLrp4dORM5
+Nfcz5rbQXcVv0wF2NZWHaZUDxp4Ca+xabwju0TV9YVMzu3PCUAWhwLMgNZ9pyyer
+iK+EXCtirmkDqpRCajLdJ+1WAY5lSm3hOXIijL4UEypVY1d/aJk6IBly/KdCXlR2
+gOqzYcKsM7kI5VM2DoCNMVxuafzxi/pqInXn6TUhcwZeTY5eXE7FjN0Ih9vqo4+m
+78ixBCFbovyTOBknEo2ly6EKPra2Y2UpE+I5ay+ZmFZ0JTrl99IsV8WIFHEtA3fU
++g0KRHxKDE1e8mdDHqeR4OJlJs5uhudRL5eo8X8rW+syFUvLk06fOHenr0M+o1Wq
+XaINGg8Vxfr4IDQf/JOGc543IhcYCJHTUKPRqW/FLGUHzqllAHYnvkP7ExvWYgwG
+XQSsSv9H5pZ9morvt8ymLc1ujON6Xmcn1AGgqG/OVuTpiSJ9/RYS3I/l4ezkECwt
+EY4g1ZCvtLj/2lg7GKVPPjCXEU8Np0ek0lv4U0URCFD/clTkMl2xMkwDwyH4dK7X
+FEtNU1HQc5OshjXzoyBQ0e9xrNw7qVhBgYlumfSvPuU0ucwYT2374M1Lg7uvTIRl
+S+tjhg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_cbc.der b/samples/dsa/pkcs8v2_dsa_aes256_cbc.der
new file mode 100644
index 0000000..71f2441
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes256_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_cbc.pem b/samples/dsa/pkcs8v2_dsa_aes256_cbc.pem
new file mode 100644
index 0000000..c685f88
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes256_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIYf686YwXqLcCAggA
+MB0GCWCGSAFlAwQBKgQQri4tfjkmhqskQWKEZGvMnwSCAmBbHumpuZoaypjiOxGS
+HgMHZqnUxR0C/BiVnEcC66rBPjlCjlyAQ9I98i0e/01Wb1pHay6F9vsm+Vj+hzB1
+GuM9TahBuXAQAjleUHjik34gKzewSWeRYEIAN/ywNYHHLJJ3+ogoI3fgCNLnXXb8
+9orQCgkZHCY+cffL/yR4jrFcOIQJmhvsNDmP7IaKZCH00H4mgWC4dI04KnhmTczq
+XX5xqcoNll1viTehM0OEpocsRm1OOwBIO5O2d6iOwxuo+4I5FtTHELsnVP5yii7m
+oIzOa2Tg+v8uVgrAxFsJ3eLkuBJx6dvS3iM9aRJvDPX8jxcR+Fb5cepsEmNydT7l
+diDtMil/QKWSZWVRnPCVD2KClA5nVG/BzX5jJPDj55ryvlYUFdEqrTPXrZ8Vvkkc
+AFqPc6+IHBXEeaVYh/lRfTmVS2MU2tIpW6QPIIUA0WSSFm0CxxzDEE24txL9+D+M
+jjtPu6yTeYDTlQUo0eNzOE6A7xGUT2dI4IopBvyrcgnmUSdsVNifAPoL1uO43aku
+8kKsZHy9cKs4l7J30m8xXUBkBrqpA0T+TRB0YPdJZ69okBv8J3BHuARSeQNxF/l9
+ANTy58CDjaoubtP7izw5AVpcljXTnM4cMvFRnimCpugx85o80bmZ5VNPWlhdDZF9
+oS5fsgfuonv4UNgyXKQIMiY+W3n8DKfdkoHSlqjn/D7ANda6rwovtKhSkg+4Z1dE
+7YF6aV/6Mkd/5/LyNmc8rP33ORUN2anHCATbn1zeEno8+A3GYB/5a5ZvAsX7+Lx3
+z/Z9Np/PFhy7wIN39oUFc4aaGg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_cfb.der b/samples/dsa/pkcs8v2_dsa_aes256_cfb.der
new file mode 100644
index 0000000..967c799
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes256_cfb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_cfb.pem b/samples/dsa/pkcs8v2_dsa_aes256_cfb.pem
new file mode 100644
index 0000000..dd625a4
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes256_cfb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoDBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQItCbXuFZgB00CAggA
+MB0GCWCGSAFlAwQBLAQQ6YyWngfQjfCH/nPHx16UAQSCAlHHhF7hJaPcC0sG9rBA
+3btgv+iuZZcISp9gpSAUioVRNRjrukDGLGv99njCbDZUSSplpj9vubQXAHk0Ugwn
+D3SkXkFpt0bll/AZ4ZloXSLXO5Y1d+UijXb80N5re20GKrN4V99yuS/dtc/kerAO
+mv+l9T5cIWPwamO9xzFScB74f1d54Cg+DBxt+afV0NHGwBhUZXtGsKmah+xgSO2s
+cN9EJyhFAFWI43wugkUCJsyIZA/2mX8KI04hroiPf1yKk78siOIPHf/yDdef/Y81
+cBFAiaaMAar2o5iKzbc/7CYwXVLwCr+gk/Tq+rmk/qphG1sKonhaGs+akBUt5qca
+VtKcQio9BMGRhwZlJF5QEzoGif6HuKVsRpSBDdAiVn+tgmv+ubtjc3yodfmw5C75
+tpToo24TdnZ7gYFOH1bKRavF/UuM+2EBMzgJH7s1CI8Jrlt8uTwumXYwo9/VumiB
+MZvU8Ky4qO3qIslY2nkLs+OBSVgdcbVwltJDcePL9uEY+UoAWZnDcUIbKqKvfTKb
+8gl6P31tp+MRokgy8Xw0oOy0jhDY++68COhuv2i9Tq6mcUYTwCybif0pqqX4xIIX
+ND/MJMT9Na4JYv4KR7w3nBCyDrkNws7d13zopl2Cpti9FJB2XZA8oo3avl6YJJ3j
+wLQoqGxADC00ffXDKjSw9B30iDhUYKRcbwKo5YxJKY66x0MY/rfZQcX8SQbBB0zT
+ph1BpRh+PQUIHHoArCRsYYZo17R+tAbnxn99dSlP3ZESkfYIlOyUoED2+AaKDTQj
+N8u2og==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_ecb.der b/samples/dsa/pkcs8v2_dsa_aes256_ecb.der
new file mode 100644
index 0000000..675254a
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes256_ecb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_ecb.pem b/samples/dsa/pkcs8v2_dsa_aes256_ecb.pem
new file mode 100644
index 0000000..f63bbe1
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes256_ecb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIPDwBoMog+vgCAggA
+MB0GCWCGSAFlAwQBKQQQAAAAAAAAAAAAAAAAAAAAAASCAmB+CKtEXun0FkPeuzre
+HWHD3lD1neK8YpJLPWgI7pJAui2mYiZcbAW2HOsC9NGXZYMuv5/eWsAwrbU+SV2Z
+gkNx0wDi3bOt+mW4ng4svXWedTRchW2MHIE2xOVWT1ETA8i2mLg1/xbflWrpGNPV
+ZqzwvDUW6SY9P9PRebTp2ssggRQ59s6XvzVHRO8/O6rTf9WkE8bzeWXTD5YVsLeQ
+QNoNCfa3dMflOCY3PgpJ9Kfye5JTP5MV90gGL3iUrXR8I7kbNh5UlnZgWuvB7bbG
+Fe4jAxDL1iYjdTOwfNk2kb/q9674wXzeUK9/D9EFTs29qM78IyWXnxG8MvzFCCrY
+xAGbNU9C+41Zylf2hDeOcW3vsaAwJwZkS+297E7LtweXlz8zaQiYEO324StKCBES
+J5UCEm1L77zTYYXPhby988ZkWgQ/qHU8Cv3j0F0HaWwkGo1VvchLwUj3MvE2RDjO
+13yy4DIjT36kEA39iZeF33qSB0cPN3pUsOFKB3OR8DoLMGidnN4ErMndKtMTPGyn
+ppSPGZhZgnoXYXTNll1okBqUcPRY87sN2HLyMDPNehxUzBnEK1JMNXbQWqzOqWCN
+QSbRJnaRLQxec6EfTsfmC2taCJlLdUdTsJgGkH/Zk0ZHNV4izG6gP1nztirpX3YG
+JPQgG0QTFxW6sCm3I8H1XBBVB9mOuGw1Nrb+rk0cjNQnJpTnaEerbdMgmIxhsmBX
+50eMTa6XlwtEiZA6B+/f5huBv8l64v/JrWRkLYsQW1s8iBSOTZgY56Lfj9gmlPhQ
+PMP9BS3aytaYhLEfkSl59/OExA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_ofb.der b/samples/dsa/pkcs8v2_dsa_aes256_ofb.der
new file mode 100644
index 0000000..d32080b
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_aes256_ofb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_aes256_ofb.pem b/samples/dsa/pkcs8v2_dsa_aes256_ofb.pem
new file mode 100644
index 0000000..4ba3f46
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_aes256_ofb.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoDBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIejP9qnm498ACAggA
+MB0GCWCGSAFlAwQBKwQQcaXLlr9tbaJT/ZMRwZfdgASCAlFlUGkJFPwG6DNpnm4X
+YGNe08E49EI7XJoTecIqOaAwcozx2uXyo8+6KdsPkUG3xfEmZyiPijSAThvL5vQo
+IYpnQPjI0KUSzFhYwRwU2o45V4rmPfkyr/ghqbArU6fHSeSfHZ8TLaAPkfF4YUSE
+MYwdG9Hh/sRjaEgAxNsnqMA4ahAWv5grKLYa+h5LnvVDqU+Ub4wL9x23V7/aB8Y9
+BuKT3b8dD7b5v6RXsgT5wuv7yGOAtuHRBkf40dbznFfsyso2a222plvvkzkorisX
+1W7zCVI4LRumSVkOc67yl2HknxM02R+iACQ1EhM7qC0YmglqZlLzBUuX9EHzOvJg
+cP+CqFw66TtGl44dlipffySfs7naPvXPLlf4n5ZwQ4JeoPbNKXpIXO+btw4BOISs
+BS6ipHbfnYDUy2WR3fYhP7rjTP6YJc67ObAy0SWCb8MxOYLb/Bx0pzFX4VykX1Hj
+Zu8OHdnFbcecPgDXgK3ka+6pSiLNSR8+momRZIq6NL5h+lYQkt9oKasf5qspGvAl
+rC3jSgRmQ39jaPTrZPaQYrTbUYwKZHKPb2rB1KYaCewgVu1UXIEZwk+5sL0wcWC/
+HhlGRiF8aRNHpwvJOaXRarXBrqe7un3KbFhp65zQ6WgOA/QUNT1XA5EfQPGFE6HQ
+fWMStgkLWIWtoMuaxQqPE/BOMjwOxQo4FmtqMnUywck0nglxRz7mkSt8tY/Igcka
+2tJUgwe7faG11YEW0nuFW9JgR8nMn1BoY0rKHiRroEYvmwA2B3InhJ7Y6qgMmj6+
+jJTrvg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_blowfish_cbc.der b/samples/dsa/pkcs8v2_dsa_blowfish_cbc.der
new file mode 100644
index 0000000..544b2e0
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_blowfish_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_blowfish_cbc.pem b/samples/dsa/pkcs8v2_dsa_blowfish_cbc.pem
new file mode 100644
index 0000000..73edf17
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_blowfish_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICnzBBBgkqhkiG9w0BBQ0wNDAbBgkqhkiG9w0BBQwwDgQIO8fmVZptTFUCAggA
+MBUGCSsGAQQBl1UBAgQIpmZqVdyl28MEggJYFaMnV7GvxdtOL0oduTx2NT99aQ39
+isC7W3/7Looumt14SGXLmB/B5lpU7CpkhQdKflKnh+kUw8b35snYq9DUpXKmwKQ8
+OLG6osiPkNbeX+UXqRZ1KB2n45oUTmkeiws1lXovwElqDLlqDRxve/Ks0/Y1WBSN
+mR1lZealI2Ut1E+1KjJFBi/1zJIIFaH+Mvau4R6/vab0Lh/XR7XfakmMrweOH8Zj
+1/bRLUnuYPo8R1MGFGbWRipxgQ1bvxsIAreuewTkdC2S2PYHvGnAdCC8hcLV8mJ0
+/q9tf030ho/M50VIXa7cNS6N/beLXye9L/wBozi8ZzmI4LlEC8nR8OVgkPgKfS82
+mGY5wWVkXiRBx9nMuTjBKRV8MpAjzYz48BpX21UXr/LZEsJ/PKfmy0OYN0TiPNhn
+WAZtHhe84abP3vMfMbNlfHgakfbH31HGAVVWHysSRTeeY6NZqah0CxtlLTPU6+R9
+88cZKG7v0HP6YoW+0Jyh8vmSzrepbcSDWSB/1ToHCjOiNaLcF+SOwyP477bZiAOf
+2AFzu33iFZUo5VaNYAfKiwUkwo3MMs3jxZH6hP07/GJIDPU06N8Phiw5K5R/riv0
+ZKrayJBVMXhnCsf70Q1YWd6UFrGFgGsZyhr97FDiQLjOpT1kGTPFDCgMoWX2AbNO
+gH+kTQGXyRp/FoWFG4stuzMoMbpfH3TrG1b3CG5DloG6PEvyqbXjtKJp3eMer1+S
+JNwu3qwn+/+jRpV/wWaxFYfbidO6QVNypbJu/zLxNwPj+g8fwDU4V6FpNmQRu4xM
+bBzR
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_des1_cbc.der b/samples/dsa/pkcs8v2_dsa_des1_cbc.der
new file mode 100644
index 0000000..8facb1c
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_des1_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_des1_cbc.pem b/samples/dsa/pkcs8v2_dsa_des1_cbc.pem
new file mode 100644
index 0000000..081b384
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_des1_cbc.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICmzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIvknMDSuj5Y0CAggA
+MBEGBSsOAwIHBAh7q0KSczfiTgSCAlgdfxa+tG7vg2LymyI6rl/+npMdBxHn3iX2
+a9AsFbqctw7kCE/SzhwWnEl4IHOvHYVZ0vBCYHbwMm+deZUZLFIR9cExVSOX9lOl
+9sf3s/RocdapAQTHPlLMTn3lMHYYQKywRHdbdyYFOGGZJNMVwZ4O1yZ0AZaAbFqi
+JglfKzRrRuE8u+/byHZbGq/2xaV80l2O4FenDWcOi3GxZW7DmKVcLRqFeYZ0ZyGL
+5ta3sz37XOpFL7q62GPsG7F9Es9Z49DkPDMwyseidK7bFHVkp+WFpsdA0+/V52X4
+m3r0Y35XBeD18CGAqE5l2BlUot+ddh6wjNp8+VJx+f7fgRKKNCgbcgcTwAilFJfv
+DP83G2vHO1i5MV65CiK/cCbEMeme7e4uW5IFO+PyvY9VWgudw/uo8HRKMUMlvz4B
+btG8Zuwr95o57E1C0VyOYHceqa521y7KxiUdD/CM/ktYp5BB7l0cfnnVI7NHHxil
+DViqjtRGWAfdgseG2lkgy9ke5cbD/P3p+lt/pma94/wEJEFSD7d17+Wp65rj+64w
+9HdEvwyN9AlluBPraciWZPzaf0xGqqQ5s8MQYOvm1XLIgupWGlFL8bR3oOrcq7Ea
+O+6TTEAgJYTxQMQKTscZsXFNtBjwiiVOdPOydYiC2qIKSKEIowsZbkDJp7D7ZF9+
+H2olIK+BB3EAe+98QBsEPICwc/40lKxU3y4L8usgEulvE5sgLnYZrX6BsyWqTKeT
+P/Hish6ijo2wQ2wVtPINOqrT+NhGI3zYOtLMMUlRyZU6YCg1Jzw/ajjcnJxXbAU=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_des1_cfb.der b/samples/dsa/pkcs8v2_dsa_des1_cfb.der
new file mode 100644
index 0000000..93f00ad
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_des1_cfb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_des1_cfb.pem b/samples/dsa/pkcs8v2_dsa_des1_cfb.pem
new file mode 100644
index 0000000..7df7a52
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_des1_cfb.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIClDA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIT8vKpxOwlw0CAggA
+MBEGBSsOAwIJBAgpDzkbHIm/IASCAlHxdvd6wK/40oaT73deAeXNns9WnYDRNiOh
+rCc7PoUfz7nXhhHJ+4eniHbsP9C0h89zL9MFuNZxtD0GQdAQu+w1Awu+IX7RxPc7
+wernjf/9zM6Zrz2Fj4p/EjqVi5NJHGjpCgUQOtgaipRyUZwRLUeRtZZAozTmBRcN
+2+oJGSnJ1kLMwbM+j/0Q/FVuelhGGR15yh6kFOY94UauxSWX11M09d8LlduGM/9t
+bx5jArxuM/t0gFfkLrQsZ+0TPhinor3HNE0k9KhzhxcgGA7g2RcvJRXL/XQTig56
+J6ykHhXLi+dxMBx2bHXKJNTZ/1xNFankGDhJesynjoWAOD5oowTB+5KMEWmihdlG
+IQBkJmqxENNdguG5bylwtqg/iEPOKrggqUuZ9wAR/NOi2Dnp+Oe3Dt5jLem6XHLv
+sgZrouIc8pG+nKMwxANfBZ+XcGQE0QHtE3LS5W5AHa6hkSw6VVHg3JJE3heVYdNE
+lNg/lZolldR9dMQ3rEQvayUqelhDQfxy3di29cw2nsVaaBgQyl2XeFhUeWskEICA
+rYXz4bV6aR1F4CxjmliX3Vsj369Y0x7lJxoyk6d/urUVgEdNUaELoCQ6bXs4VD1D
+5h4aN2iVRHRxPCxNIINzwHK6QDM1jlp2W1Tqk7UQvQwxmTXkpqREby8DOvJsBP+D
+kPk+bGcKLPeCb4f9q2sJhkCSDamENtQ4KB2QmahFlplKZr9tdBnSRIIDA9MLpAfk
+rnp8hD5KFVl/FB8oonI0KphoZ7hyQG5MttDfJidlOH+pPvJuazUMDA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_des1_ecb.der b/samples/dsa/pkcs8v2_dsa_des1_ecb.der
new file mode 100644
index 0000000..0cd9962
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_des1_ecb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_des1_ecb.pem b/samples/dsa/pkcs8v2_dsa_des1_ecb.pem
new file mode 100644
index 0000000..8f4a03d
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_des1_ecb.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICmzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIJN51OJttWjkCAggA
+MBEGBSsOAwIGBAgAAAAAAAAAAASCAljQ3CT/RuzXtjbAq0BFhInN/gljOnYT6mHA
+MecNI+QRyXgjjipIQ0G3uqrAL2aMzQYZbNd31zcpI7+F7yy0PKWlr6kl/mU/P/zt
+zTzjAFEVWLY/cG1mscejYg1aru7OChzP8OSq2qV4cr4RFdxt8Jgkq1gwmQ/IsQsA
+KefKbeQdcj5y+27A32L/aK4R0hTEkLpVh3rwFaUcOXXnQnww3m/dGxVZfCG+RFKY
+cyhgFlKlHKkv51fOYnLShzTNbSOIdkx1Sim9rOuIuUT4nI+enom9NlLynKH5Mc11
+HY93RRX62/Yepd/+g0RDE4wuAXjK5YCgGtPaQxhz5WQvpq50c0WXAonFhYKoojza
+D5dB7qn2bfhgVam/lmnqantsafvy5sQFJAlnDT/gn7P9QYrYZWqSc78Ln27OQF10
+VTr/mjAQyUnxAGrZj/2LoLouFkw/K1ryahH/nFzbaChyhZ7EnsO2gNT12cp915sa
+5sw60r1L9G4YUxapILD3xJMVMH75yR1kHwGJvQjfmEyM62LLFenWQA7hxBp08AMj
+dMcUambSKhl0Mzj01vEk6JAyxp5oX+/vVEaxKO8sLb53d3p/9AxPrmT1oQbANs+F
+Ju003wwarcq3hez8C/Q/01jaXJJOjv7wmAHH4/2SDajFGyobgGSiHsJspD24uNED
+dhZZrYtSsodAPSBU/enpHxH8oc62E3897nlUOtc5FtVZPoh/AGJPUzwCdDwwsAoO
+jYUrUKNdEvTrjwwjAt0PWTbVVDq6IoxBUHbk1BbIoQqHcPzyQFIm3ciVKS5SeiM=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_des1_ofb.der b/samples/dsa/pkcs8v2_dsa_des1_ofb.der
new file mode 100644
index 0000000..7ea4251
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_des1_ofb.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_des1_ofb.pem b/samples/dsa/pkcs8v2_dsa_des1_ofb.pem
new file mode 100644
index 0000000..116c352
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_des1_ofb.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIClDA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQImwccDkLMI1cCAggA
+MBEGBSsOAwIIBAihhtOLmLYIYgSCAlGnW7biQAKuL4Ypqr0RCpHdKfU3YxUgFJCr
+rEuxTEV1ttS3u58Adj7ldaFgUpFIfsaGbpsPeEw+nxHRnZ76xrck6l3MvFxW+WPM
+osKcaITYCNg7TSyzqR33CxMzkdH4FmEVr55nyR1ir2JcQ8QG7/nBN8YTNBpACJIR
+F3kzP3BGz1aAS8ef7v22BcMYkVNb0DJ38z5SUryTqEOwUPWPpNiKaA0chE6nrwjD
+8xlaMPowUjE97bcj+eIQM9hm7Gcwcv5Z4qHPd6NiwRstg0X9GL00wyFjukCV4GJp
+CRK41XwTmyrb6mYGLS6TFRg96R+VyYmB6DL5rCGFuT5oeVIh1FP1TdflOMK8z/sU
+Qftz6Y3ILLbKMGXUVQG6rrXxSD017sBlqK4iPntANH/Ogh6WN2VGeAsRw82ty2YY
+1jJIlEJa7kMFJRZgvboFZf9jsePd8crxMHvyefAGbJcoHvSEku3wZQ2Nil1ddW++
+IvNq6xyNUiYVgCOUtA/7bB0kP6mUpG2tU3MS+C8SknS8lLxcS+Et6yjj1Z+2gEN/
+R1Se9nrhfyUdI/boPmwfmwcVlPnCPI0HlcqHy04oSJVDJlOlOpSkw4cPZCgBIMmq
+N2KgtLYXK6xQQKwVM1RGyqBXEOkngXkddNdwl1PcG5UUxsliw6cDtgZUuv5D6Xht
+9IlxB1eRN+w4kVLRsh+cZCFIUdqiTky3VEBGtO2ohSkBw5Hz6gaqIDZbUqFfal3V
+rS/MLKUOCUwxKUBr8mvwjRUm17caIGnHZVuXUhJtt3MDB+Su107+Eg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.der b/samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.der
new file mode 100644
index 0000000..7005d4c
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.pem b/samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.pem
new file mode 100644
index 0000000..e98e115
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_des2_ecb_SEEMS_WRONG.pem
@@ -0,0 +1,16 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICmzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIz6I345rIqbYCAggA
+MBEGBSsOAwIRBAgAAAAAAAAAAASCAlha7ykjKoRo9RdbHoFnA8gTksfk//hKNzBi
+tdl0MKBYMlDbzG1p548W0hO6OlU5oO1KE27x3hRmKfi+RMGq83MqHbME6OB2bOQL
+QL0xDMI6kpRi4adH8JgOAA46YQFEj5zRDcZg2XOfrGGJOu/fF6Ne4ALrXkewcMIv
+iaFib19vpCHqe5E9ixvDyX/RQRxN2r12II7UctmZyZhqNEHJtp7ZuOROm3M83HuQ
+bMEMLAeNgHslXBDPhrx/ByXi6LmhJJPXk3wAySNwSKCF7bpTtIb51SUDAE2pRaw4
+PrshVZ4hnt9s+xEPz3a7Rs56F06HRyXT4YgXsJsVm6Fmg1DqQwC18aV0ioTEeJ80
+h92btKTg9wJ1+Av/FWIf0scIUnhBmzAC6A0h4mRueSC9xbcQvBb4QquFeDYhxiA6
+MtFS5MtZ4guYyMJlKpKF97c5gfheglxDA/iWrb3TN4dz+eM2D7uBQjfzugF0zQRI
+2VGSO+hRyLlF9/ooozjJ0OO/gVEKz0j8ks6fZ7Ol5ctryT/tGYxhfVR5YPpEW8hk
+iSiEh7QluPGGhjrC955IZBXkfmFqN67X1L9UlExuePj7sPtQjznaLs7rK3fZ9vRm
+9x0JILZOis+I5MOfeoVqDzEtUNI51rpJl8bpt/BOlM0jdnohAIjPPICFZMeBfEzQ
+RmH6VuPWwMhV1KjMQPcoZT5BPl5fxUcpqpLeY86bsCdSHfYJVBBxo1iet8+mC3VK
+mGXwucHoDMh1oGNkPToCCD7x34zMBBDvm9oKyjy51ub9kztWUUctnkDrb0IyEFs=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_des3_cbc.der b/samples/dsa/pkcs8v2_dsa_des3_cbc.der
new file mode 100644
index 0000000..57ec533
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_des3_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_des3_cbc.pem b/samples/dsa/pkcs8v2_dsa_des3_cbc.pem
new file mode 100644
index 0000000..33e7665
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_des3_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICnjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIsclhoXWd7bkCAggA
+MBQGCCqGSIb3DQMHBAgsjKjs6xPhKwSCAlgtME7PW1sMaRjbUecyCKazv2QgvwUn
+Z4s2J5pNf8ORBuBdil5lNu+T/9GvdiEGo4R1uA866403Nc2KA8ZpfgOwNPSUn/wb
+iMdCg5S18mvgFT+1Mh1Mz1EUp+RfnVYRI0MlpvKoQf/vFqmEbUVSuQJsq6aBXs/R
+2cJqC6pBGoSAZ0kQza2P1RJ4cTvgf+1OJj4aL8+OMK1rMmYLLkrl0qF+2pppj/nn
+b3djuBPYCN1WbM7Alk8/pxttZxlPnsywBzFAnEYAyAsDAvsAcnx6MeVSnlT6Z91r
+T88AqXREN8c6N+QP9S93K8nBhJ3VSAFRwnqWYG9S/M5itBl636Lna8fwIWmYuOAe
+9+pDA8Ki+aqLDMsz4Aqw1LJ1cOtnjr4Y9ebReo90/hpGVWrASfmQ/Vq+lboz5bSM
+385UyoA+jyiveHVsFctN4rQJLQeIwNWL74jy4RaFRbnoFqlR3HwjLANcnVK3Yx1M
+Hvkvayd+ozj8LsqMjQei5uaxZjet9EhFLJhIMeRq4AnbE+5t2O8MVUhirlq7kENQ
+ZJW9hZF6KARC0dPRIL3Cr0TRYt3Cxci+ZvQOxmcRNUf4rXIe0ySHNVoiYETJ6m2a
+HwQlY3fIDkmGPylTVlp9yax0SWn8ySdVXPFEUiMLZWme8BMeCyWoBrMTwHQESNke
+dUCA30SeNXuDVlY5KX3EsxESNOd427P6SEqEtZAAsiIvXwGUdsKlIPCTs3xG/aP8
+uQzl0E/LoHrT4QuXzDm1IIJlAM6MIV/fYThJ+KRBXegx2YxBY8LgsOlcqvrdjfg+
+zko=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_rc2_128_cbc.der b/samples/dsa/pkcs8v2_dsa_rc2_128_cbc.der
new file mode 100644
index 0000000..fe6a921
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_rc2_128_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_rc2_128_cbc.pem b/samples/dsa/pkcs8v2_dsa_rc2_128_cbc.pem
new file mode 100644
index 0000000..8bc30f7
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_rc2_128_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICpjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIQKUAK0PkWtsCAggA
+AgEQMBkGCCqGSIb3DQMCMA0CAToECNtxT/+Pqog1BIICWIY6YcTRO+YYTzYH6AW+
+ST1mb7WaW1MPFF1Fgmr59u2pm1OvH9Cq1ylcSZUJ7xYHcpBC5iigjitcJIo7KrIP
+PdOh5ZMhebNYVREjWL5drrlUEQpM+R5MFsYo8t3Solz9tgujZhYBBNO5b9xMdKu1
+iddJAerTssjJNonHzh0M54wHJ8DthO1hHuF0ljUitIXSKDwQQiKu6nGMdQejgxcM
+RZ+jmm2RwgDBlTnQumR3FUInRjUDdsfC2u7EPyJOKCBEi+V1Knz8dnvfgbwr6yVC
+ka9kjm3zDqbijs2si6tnRdNxXPob8Yld0jwfKuhzoNPQTSLDTm8jtnu8Jlj2WOk9
++pCJPMfPECH1eE0DlVAQEjIDmrQIw5ZEpdMpkOfReaHujT8AiyvcjmxqcgFgNosR
+q757fi/LhQlYi59gpNAKxhAV9rB+5iANDF2ILg9KtIWxg1cFuls6ll4oT13YR+oM
+5+iiTAWwUoVLlKwNAAuUyyvofTHV7oRDnl9p27ZnsBI7DWYKBRirMBcYfatBxWub
+/AeFhXFtCA+LptKuPXepvYbtr4A/A/1bFW9cbKSGNDJ5mxQLofKXeQ0R2oOxbFxN
+F5OJNeg3y1K/GPFw2SMRaf+kPK0K2pm4jkLASM48hwOnfEu0X/lgBVRHIqqekdYq
+pVcGaR1yTBycviabU1grfI49mUbj2EbmUAaIPevN6SFg/gscMOObxZCFiddX38yT
+Pmx13vDnPpKIDh1qrWsDh3ShvjC0y0vVG89ZSDsSph7JSQsT9lKfJZovKkOIoxty
+e/CYyA30P+jUJA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_rc2_40_cbc.der b/samples/dsa/pkcs8v2_dsa_rc2_40_cbc.der
new file mode 100644
index 0000000..fa93428
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_rc2_40_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_rc2_40_cbc.pem b/samples/dsa/pkcs8v2_dsa_rc2_40_cbc.pem
new file mode 100644
index 0000000..551357b
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_rc2_40_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICpzBJBgkqhkiG9w0BBQ0wPDAeBgkqhkiG9w0BBQwwEQQIlYIY7do+vY8CAggA
+AgEFMBoGCCqGSIb3DQMCMA4CAgCgBAiYdTRbZ4lQVASCAljYj8mWvuSo7R5pG4RC
+sakmf8knGoSCAKWX4IkyVrOT1tglQpj/TATeNqmykOmF7x96QedoTbTQSFJCDhFR
+ieIyiGYdJYJOOZ0PbwrRKzFJe9RPMC0HxNOSYWq8Ghq801r5SpMgB0GuKsXQIawj
+OazhGWkzKD7G8khfM/AFS3DivxV4gAV7e3PcGeEpXDipDW8wFmGpnva0rUSiQj87
+j5AGeo9R/5QFAhf4KvKLdKeT9BcU4N1lVToibTAImoTNMp9eJdUU43Jf0JWOp18M
+Ws4eP3Cs8xreo8qyB9T4AJ95UFSuPQRCLe2SwjNOgguwzdc0s1nbrFj4bMhphT6+
+ic2aQDXQbTtzahqZz5/UvbzuC3FJ/8AFCrTcxKCRaqKKm3vx2mRGjps1dQaxdq7f
+ePRK+kvThzv6A061rv1PnJF2oi+GOjLzFix7rJjXFvZ79btV7qbb1k1qrAuJzmN4
+rC+iurxT6Nx303PzsSHxr1Rzi9wn3SznFqIRz9K0brhGbG3CqeVsoFnI79K7bB0b
+Rm79vsm9P9zCyJamYYhcQ5fMtXhzvRAfmh0rZjUE+QsPbr60U2JamjYUj28BW/2y
+FPdidr/hFC0Ol/AfQkQJjLG2QGiorFN5QxrBHjeQMAi5AES0/RjW7SH9y6mLKr4+
+vjBEf0adW+kR7PC9Q8An7IVqeQ9vC8FP888fmAbwtxXaQKCp7p1bCLpgg9rlkCdu
+F+WN87Cf9lhR1/ElicLueEryOAlmRWvZwXV4OC6WNQ/meE2EUfkoC0tJXe/2Dw6z
+XXW4BLa4C32ynWQ=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa/pkcs8v2_dsa_rc2_64_cbc.der b/samples/dsa/pkcs8v2_dsa_rc2_64_cbc.der
new file mode 100644
index 0000000..861d040
Binary files /dev/null and b/samples/dsa/pkcs8v2_dsa_rc2_64_cbc.der differ
diff --git a/samples/dsa/pkcs8v2_dsa_rc2_64_cbc.pem b/samples/dsa/pkcs8v2_dsa_rc2_64_cbc.pem
new file mode 100644
index 0000000..aabe3ab
--- /dev/null
+++ b/samples/dsa/pkcs8v2_dsa_rc2_64_cbc.pem
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICpjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQI9j+oZ2rYhkYCAggA
+AgEIMBkGCCqGSIb3DQMCMA0CAXgECBbPri4fuLQqBIICWMCy6hNMdpB/4DhIM67V
+cr4F7cZuXn4nIxpKa9B/Z7EaHJnwVShwECCrz7wOVsP0M5uZYrfZ7NXCbz2ESXI8
+B7jCwcMf8/8U2uSlTtyWmJLTrukBifvPtzy4hPYUCiNobtcEipOB/DnLE/c8w7kC
+UR3o6wuHvsaqKcSNminUY0VfyfRWJ+orTBqK1cGQtrtg+6bMYZbJQeKgJeM6BuvJ
+0/yxw4jGMfX/bqqqjPl8PtSchOtSqLCDfMjHQu5IlQUxRYzrqde7KAxWztmBRSHw
+VtWsUKHizEZuOWTC8ZF4LLHHLOpuRr4ChIRihKYjtLp0xgj464RMyvT26gUtSmKS
+v7iPJInt08oOwTxABU9TIgEG7aVp/PHuLwofR6gHJO+vEvdygMpcL38VYp/6E9iL
+NRDr7oGc5IqS65H5pPrwXmtej4A128N9deVzbHJ2v9jEmpfZlFg/FhH5hPccy9Lt
+6dC5xAK18zK4QQ8GWKpa2WJaTiTHWdpd06KHKaisNBUVY48etslcsGSo/XZRlDE1
+aOXGyOY8GKWnhWKfHVDw0Wlg1nIROhm0TvHXWH/IwdaaCAWQL+9o3ObNc7pLPQ+j
+4kpebB4DnbwBZuNAA2QqzjyPPk7s2S0kVWrgf6X3PBd+Tt44GtyMR/jgdLoVzPka
+aPgJLAHYl5/X8h/VuUOnOI+vCfr6E+cyRbs03GOXDv8/Ugeb6QQMKTfU/czidNSB
+9aINJZslQnuHLxlFbmO4VQ0uVUvNWlp1fBzf+MDFeXY3WFNo7YDpclCjQwf1gd6T
+T4qym0e+jm9iYg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/dsa_result.html b/samples/dsa_result.html
new file mode 100644
index 0000000..c618ea0
--- /dev/null
+++ b/samples/dsa_result.html
@@ -0,0 +1,38 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - Decrypting DSA Private Keys in Java</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+.nav span.hl a { color: white; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="../index.html">main</a> |
+<a href="../ssl.html">ssl</a> |
+<span class="hl"><a href="../pkcs8.html">pkcs8</a></span> |
+<a href="../pbe.html">pbe</a> |
+<a href="../rmi.html">rmi</a> |
+<a href="../utilities.html">utilities</a> |
+<a href="../source.html">source</a> |
+<a href="../javadocs/">javadocs</a> |
+<a href="../download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Decrypting DSA Private Keys in Java</h2>
+<p>Don't forget to install your JVM's <a href="http://java.sun.com/javase/downloads/">Unlimited Strength Jurisdiction Policy Files</a>
+if you want the AES-192 and AES-256 tests to pass.</p>
+<!--#include virtual="dsa.html" -->
+</body>
+</html>
diff --git a/samples/pbe.tests b/samples/pbe.tests
new file mode 100644
index 0000000..046ec46
--- /dev/null
+++ b/samples/pbe.tests
@@ -0,0 +1,45 @@
+target=/home/julius/dev/commons-ssl/samples/pbe/java
+
+aes-128
+aes-192
+aes-256
+bf
+camellia-128
+camellia-192
+camellia-256
+cast5
+des
+des-ede
+des-ede3
+idea
+rc2
+rc4
+rc5
+
+# Naming variations:
+aes128
+aes192
+aes256
+blowfish
+camellia128
+camellia192
+camellia256
+des2
+des3
+gost
+rc2-40
+rc2-64
+rc4-40
+rijndael
+
+
+# OpenSSL doesn't support these yet:
+cast6
+gost28147
+rc6
+seed
+serpent
+skipjack
+tea
+twofish
+xtea
diff --git a/samples/pbe/README.txt b/samples/pbe/README.txt
new file mode 100644
index 0000000..c1bb157
--- /dev/null
+++ b/samples/pbe/README.txt
@@ -0,0 +1,36 @@
+
+not-yet-commons-ssl PBE tests
+=====================================
+by Julius Davies
+July 4th, 2007
+
+
+README
+-------------------------------------
+
+Underneath this directory are 500+ small files used for testing
+commons-ssl's ability to interop with OpenSSL's password-based
+symmetric encryption (see OpenSSL's 'enc' command).
+
+Each file is encrypted using the cipher in its filename.  The
+password is always "changeit", and every file decrypts to the
+phrase "Hello World!" in UTF-8 with no trailing line-feed.
+
+The files underneath "pbe/java/" were created using commons-ssl's
+org.apache.commons.ssl.PBETestCreate utility, along with
+samples/pbe.tests as the single command-line argument.  These
+files were created using pure java.  It is useful to see whether
+commons-ssl can decrypt files it created itself, as well as to see
+if OpenSSL can also decrypt them.
+
+The files underneath "pbe/openssl/" were created using OpenSSL.
+Take a look at the "samples/createPBESamples.sh" shell script
+to see how these were created.  You'll probably need to build
+your own version of OpenSSL from source to use some of the
+ciphers (idea, rc5, for example).
+
+org.apache.commons.ssl.OpenSSLTest tries to decrypt both the
+"pbe/java/" and the "pbe/openssl/" files, and reports on any
+failures.
+
+
diff --git a/samples/pbe/java/aes-128-cbc.base64 b/samples/pbe/java/aes-128-cbc.base64
new file mode 100644
index 0000000..854990a
--- /dev/null
+++ b/samples/pbe/java/aes-128-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18tgSw33f+3SBISyYVeIkFpwZ/7fyE6IGA=
diff --git a/samples/pbe/java/aes-128-cbc.raw b/samples/pbe/java/aes-128-cbc.raw
new file mode 100644
index 0000000..f7fc29f
--- /dev/null
+++ b/samples/pbe/java/aes-128-cbc.raw
@@ -0,0 +1 @@
+Salted__ь�ͻ��S��|^�bzԏG�a3}�
\ No newline at end of file
diff --git a/samples/pbe/java/aes-128-cfb.base64 b/samples/pbe/java/aes-128-cfb.base64
new file mode 100644
index 0000000..c949990
--- /dev/null
+++ b/samples/pbe/java/aes-128-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+aEXYNHZXWHd599zBpykFGRkhdvw==
diff --git a/samples/pbe/java/aes-128-cfb.raw b/samples/pbe/java/aes-128-cfb.raw
new file mode 100644
index 0000000..feee3a4
--- /dev/null
+++ b/samples/pbe/java/aes-128-cfb.raw
@@ -0,0 +1 @@
+Salted__��Y$5��[�=Q>)�"�_�	
\ No newline at end of file
diff --git a/samples/pbe/java/aes-128-cfb8.base64 b/samples/pbe/java/aes-128-cfb8.base64
new file mode 100644
index 0000000..024bab6
--- /dev/null
+++ b/samples/pbe/java/aes-128-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+LUWFrYVLxL7Ig+S+sGlA2HXQFnw==
diff --git a/samples/pbe/java/aes-128-cfb8.raw b/samples/pbe/java/aes-128-cfb8.raw
new file mode 100644
index 0000000..229db5d
--- /dev/null
+++ b/samples/pbe/java/aes-128-cfb8.raw
@@ -0,0 +1 @@
+Salted__q����b�ӥ!��B_���
\ No newline at end of file
diff --git a/samples/pbe/java/aes-128-ecb.base64 b/samples/pbe/java/aes-128-ecb.base64
new file mode 100644
index 0000000..9146001
--- /dev/null
+++ b/samples/pbe/java/aes-128-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+2C1jR9HIDttUbQ5if/FugiwJWHnvw9nE=
diff --git a/samples/pbe/java/aes-128-ecb.raw b/samples/pbe/java/aes-128-ecb.raw
new file mode 100644
index 0000000..1065ef4
--- /dev/null
+++ b/samples/pbe/java/aes-128-ecb.raw
@@ -0,0 +1 @@
+Salted__�$U�ƽ!�
8�	'Mi��q�r
\ No newline at end of file
diff --git a/samples/pbe/java/aes-128-ofb.base64 b/samples/pbe/java/aes-128-ofb.base64
new file mode 100644
index 0000000..f7459a0
--- /dev/null
+++ b/samples/pbe/java/aes-128-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19aJ6WDYWY7FPQIkpp/6FgjhHrxHQ==
diff --git a/samples/pbe/java/aes-128-ofb.raw b/samples/pbe/java/aes-128-ofb.raw
new file mode 100644
index 0000000..f475a8b
--- /dev/null
+++ b/samples/pbe/java/aes-128-ofb.raw
@@ -0,0 +1 @@
+Salted__
-H4I�Ȗ	�fzV��j�l�
\ No newline at end of file
diff --git a/samples/pbe/java/aes-128.base64 b/samples/pbe/java/aes-128.base64
new file mode 100644
index 0000000..4cb1703
--- /dev/null
+++ b/samples/pbe/java/aes-128.base64
@@ -0,0 +1 @@
+U2FsdGVkX18FP9Ocup5k311G9zgGlCnh9zas3Xdj0tU=
diff --git a/samples/pbe/java/aes-128.raw b/samples/pbe/java/aes-128.raw
new file mode 100644
index 0000000..0a36280
--- /dev/null
+++ b/samples/pbe/java/aes-128.raw
@@ -0,0 +1 @@
+Salted__��.�}���*=*<�G�]���
\ No newline at end of file
diff --git a/samples/pbe/java/aes-192-cbc.base64 b/samples/pbe/java/aes-192-cbc.base64
new file mode 100644
index 0000000..d402ec3
--- /dev/null
+++ b/samples/pbe/java/aes-192-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/Pw8ptccG+s6ZDELJSrvJ2ZctgWQGJFAA=
diff --git a/samples/pbe/java/aes-192-cbc.raw b/samples/pbe/java/aes-192-cbc.raw
new file mode 100644
index 0000000..09d5789
--- /dev/null
+++ b/samples/pbe/java/aes-192-cbc.raw
@@ -0,0 +1 @@
+Salted__�Y��$�����?a�ByF����;�
\ No newline at end of file
diff --git a/samples/pbe/java/aes-192-cfb.base64 b/samples/pbe/java/aes-192-cfb.base64
new file mode 100644
index 0000000..fa4e9b4
--- /dev/null
+++ b/samples/pbe/java/aes-192-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18f1Q3JHkC82JVsgDi+mCM9dsLoDw==
diff --git a/samples/pbe/java/aes-192-cfb.raw b/samples/pbe/java/aes-192-cfb.raw
new file mode 100644
index 0000000..f569c15
--- /dev/null
+++ b/samples/pbe/java/aes-192-cfb.raw
@@ -0,0 +1 @@
+Salted__�����6���W]�ntD4�N$
\ No newline at end of file
diff --git a/samples/pbe/java/aes-192-cfb8.base64 b/samples/pbe/java/aes-192-cfb8.base64
new file mode 100644
index 0000000..d51d5dd
--- /dev/null
+++ b/samples/pbe/java/aes-192-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19ly+xGnMtLS9cfR8LfWky7HRNtnQ==
diff --git a/samples/pbe/java/aes-192-cfb8.raw b/samples/pbe/java/aes-192-cfb8.raw
new file mode 100644
index 0000000..96e1460
--- /dev/null
+++ b/samples/pbe/java/aes-192-cfb8.raw
@@ -0,0 +1 @@
+Salted__����?��l6-
(nu��uI
\ No newline at end of file
diff --git a/samples/pbe/java/aes-192-ecb.base64 b/samples/pbe/java/aes-192-ecb.base64
new file mode 100644
index 0000000..a401033
--- /dev/null
+++ b/samples/pbe/java/aes-192-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+2N1TfkuHLaGKTV8UbxAQ4q6Zq2yPyI0s=
diff --git a/samples/pbe/java/aes-192-ecb.raw b/samples/pbe/java/aes-192-ecb.raw
new file mode 100644
index 0000000..85fc440
--- /dev/null
+++ b/samples/pbe/java/aes-192-ecb.raw
@@ -0,0 +1,2 @@
+Salted__�^$D�>5�51g�,z�ۍ
+�!�
\ No newline at end of file
diff --git a/samples/pbe/java/aes-192-ofb.base64 b/samples/pbe/java/aes-192-ofb.base64
new file mode 100644
index 0000000..73a53e9
--- /dev/null
+++ b/samples/pbe/java/aes-192-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/Amis2JdWVZwzVHM396jtsZbIEJw==
diff --git a/samples/pbe/java/aes-192-ofb.raw b/samples/pbe/java/aes-192-ofb.raw
new file mode 100644
index 0000000..510475f
--- /dev/null
+++ b/samples/pbe/java/aes-192-ofb.raw
@@ -0,0 +1 @@
+Salted__�IH��x�J��
�����!(
\ No newline at end of file
diff --git a/samples/pbe/java/aes-192.base64 b/samples/pbe/java/aes-192.base64
new file mode 100644
index 0000000..c8236dc
--- /dev/null
+++ b/samples/pbe/java/aes-192.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+fyoUNT8WlenheACOWMcd++BG67BrAVZY=
diff --git a/samples/pbe/java/aes-192.raw b/samples/pbe/java/aes-192.raw
new file mode 100644
index 0000000..3a0bb76
--- /dev/null
+++ b/samples/pbe/java/aes-192.raw
@@ -0,0 +1 @@
+Salted__n����4�m�_m�q��Q��F�
\ No newline at end of file
diff --git a/samples/pbe/java/aes-256-cbc.base64 b/samples/pbe/java/aes-256-cbc.base64
new file mode 100644
index 0000000..5d2c32f
--- /dev/null
+++ b/samples/pbe/java/aes-256-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+83KKHWiQjV2cPLD4vnvX7jB9nzF7KSr4=
diff --git a/samples/pbe/java/aes-256-cbc.raw b/samples/pbe/java/aes-256-cbc.raw
new file mode 100644
index 0000000..4c4b343
--- /dev/null
+++ b/samples/pbe/java/aes-256-cbc.raw
@@ -0,0 +1 @@
+Salted__w����+
V�I���o��Bc�c�k"
\ No newline at end of file
diff --git a/samples/pbe/java/aes-256-cfb.base64 b/samples/pbe/java/aes-256-cfb.base64
new file mode 100644
index 0000000..b0b632f
--- /dev/null
+++ b/samples/pbe/java/aes-256-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/r2qI9504wQdQk+10DnjuZx74VWA==
diff --git a/samples/pbe/java/aes-256-cfb.raw b/samples/pbe/java/aes-256-cfb.raw
new file mode 100644
index 0000000..16db14d
--- /dev/null
+++ b/samples/pbe/java/aes-256-cfb.raw
@@ -0,0 +1 @@
+Salted__W����R�V�d}����	
\ No newline at end of file
diff --git a/samples/pbe/java/aes-256-cfb8.base64 b/samples/pbe/java/aes-256-cfb8.base64
new file mode 100644
index 0000000..f8a92e2
--- /dev/null
+++ b/samples/pbe/java/aes-256-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18OrQNbniV4S+jfRZg7flFPHiT5MA==
diff --git a/samples/pbe/java/aes-256-cfb8.raw b/samples/pbe/java/aes-256-cfb8.raw
new file mode 100644
index 0000000..0b3431f
--- /dev/null
+++ b/samples/pbe/java/aes-256-cfb8.raw
@@ -0,0 +1 @@
+Salted__�
j�����(�&!��W��
\ No newline at end of file
diff --git a/samples/pbe/java/aes-256-ecb.base64 b/samples/pbe/java/aes-256-ecb.base64
new file mode 100644
index 0000000..8e754c1
--- /dev/null
+++ b/samples/pbe/java/aes-256-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19UgKG5AJSnofrockP9DOx0X0UEIRrcpwI=
diff --git a/samples/pbe/java/aes-256-ecb.raw b/samples/pbe/java/aes-256-ecb.raw
new file mode 100644
index 0000000..3805337
--- /dev/null
+++ b/samples/pbe/java/aes-256-ecb.raw
@@ -0,0 +1 @@
+Salted__��H���"
E|�9m@��#��ϖ�m
\ No newline at end of file
diff --git a/samples/pbe/java/aes-256-ofb.base64 b/samples/pbe/java/aes-256-ofb.base64
new file mode 100644
index 0000000..143a65a
--- /dev/null
+++ b/samples/pbe/java/aes-256-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18MFvQbl2SXe0fhKwTF9mjNmN9f4A==
diff --git a/samples/pbe/java/aes-256-ofb.raw b/samples/pbe/java/aes-256-ofb.raw
new file mode 100644
index 0000000..44d53ef
--- /dev/null
+++ b/samples/pbe/java/aes-256-ofb.raw
@@ -0,0 +1 @@
+Salted__ުqۮ�
?R�8�El���
\ No newline at end of file
diff --git a/samples/pbe/java/aes-256.base64 b/samples/pbe/java/aes-256.base64
new file mode 100644
index 0000000..8f901f5
--- /dev/null
+++ b/samples/pbe/java/aes-256.base64
@@ -0,0 +1 @@
+U2FsdGVkX19M77p3hPsAsk2LeJM6zIQBMmTpmjGdaHY=
diff --git a/samples/pbe/java/aes-256.raw b/samples/pbe/java/aes-256.raw
new file mode 100644
index 0000000..e64d1e0
--- /dev/null
+++ b/samples/pbe/java/aes-256.raw
@@ -0,0 +1 @@
+Salted__�xA������s]��I�թ*S
\ No newline at end of file
diff --git a/samples/pbe/java/aes128-cbc.base64 b/samples/pbe/java/aes128-cbc.base64
new file mode 100644
index 0000000..f57f204
--- /dev/null
+++ b/samples/pbe/java/aes128-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+yeIg0SOvBDsjJmBCufP4ga2BB4rRsXio=
diff --git a/samples/pbe/java/aes128-cbc.raw b/samples/pbe/java/aes128-cbc.raw
new file mode 100644
index 0000000..bb10166
--- /dev/null
+++ b/samples/pbe/java/aes128-cbc.raw
@@ -0,0 +1 @@
+Salted__���p��
>3ο�h�VJ�{)�H�}v
\ No newline at end of file
diff --git a/samples/pbe/java/aes128-cfb.base64 b/samples/pbe/java/aes128-cfb.base64
new file mode 100644
index 0000000..93ce4ab
--- /dev/null
+++ b/samples/pbe/java/aes128-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19tWJZmJ48v/XfHfnB2w1e//fdR8Q==
diff --git a/samples/pbe/java/aes128-cfb.raw b/samples/pbe/java/aes128-cfb.raw
new file mode 100644
index 0000000..735aba0
--- /dev/null
+++ b/samples/pbe/java/aes128-cfb.raw
@@ -0,0 +1 @@
+Salted__g����1[碤���
\ No newline at end of file
diff --git a/samples/pbe/java/aes128-cfb8.base64 b/samples/pbe/java/aes128-cfb8.base64
new file mode 100644
index 0000000..d85ad96
--- /dev/null
+++ b/samples/pbe/java/aes128-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+XyvFXsj5UFwtv8gyG1oIXvve+oQ==
diff --git a/samples/pbe/java/aes128-cfb8.raw b/samples/pbe/java/aes128-cfb8.raw
new file mode 100644
index 0000000..1fe531f
--- /dev/null
+++ b/samples/pbe/java/aes128-cfb8.raw
@@ -0,0 +1 @@
+Salted__d?�ٗ�5�ד��������
\ No newline at end of file
diff --git a/samples/pbe/java/aes128-ecb.base64 b/samples/pbe/java/aes128-ecb.base64
new file mode 100644
index 0000000..5b43322
--- /dev/null
+++ b/samples/pbe/java/aes128-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/UoGJhhyX4cVn2rw/7X7fgdqhhgiWlp7M=
diff --git a/samples/pbe/java/aes128-ecb.raw b/samples/pbe/java/aes128-ecb.raw
new file mode 100644
index 0000000..50dffdc
--- /dev/null
+++ b/samples/pbe/java/aes128-ecb.raw
@@ -0,0 +1 @@
+Salted__iќW�gS�k�+>��7�?�
\ No newline at end of file
diff --git a/samples/pbe/java/aes128-ofb.base64 b/samples/pbe/java/aes128-ofb.base64
new file mode 100644
index 0000000..8b8a266
--- /dev/null
+++ b/samples/pbe/java/aes128-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/lTN4sZ1doqxbZpX0IC10FLDCaUA==
diff --git a/samples/pbe/java/aes128-ofb.raw b/samples/pbe/java/aes128-ofb.raw
new file mode 100644
index 0000000..61ca060
--- /dev/null
+++ b/samples/pbe/java/aes128-ofb.raw
@@ -0,0 +1 @@
+Salted__<��Y��s�xq�U؏��D
\ No newline at end of file
diff --git a/samples/pbe/java/aes128.base64 b/samples/pbe/java/aes128.base64
new file mode 100644
index 0000000..203a047
--- /dev/null
+++ b/samples/pbe/java/aes128.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/1UuVXOj3RtEMceVcMua7qDQw0530YPTU=
diff --git a/samples/pbe/java/aes128.raw b/samples/pbe/java/aes128.raw
new file mode 100644
index 0000000..d533a8b
--- /dev/null
+++ b/samples/pbe/java/aes128.raw
@@ -0,0 +1 @@
+Salted__��Os��u�dS��	J$�ik{�
\ No newline at end of file
diff --git a/samples/pbe/java/aes192-cbc.base64 b/samples/pbe/java/aes192-cbc.base64
new file mode 100644
index 0000000..85a50be
--- /dev/null
+++ b/samples/pbe/java/aes192-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Gp+yjlyN/zD/rgggvOVVFY4SmgOZCmRM=
diff --git a/samples/pbe/java/aes192-cbc.raw b/samples/pbe/java/aes192-cbc.raw
new file mode 100644
index 0000000..7ac614e
Binary files /dev/null and b/samples/pbe/java/aes192-cbc.raw differ
diff --git a/samples/pbe/java/aes192-cfb.base64 b/samples/pbe/java/aes192-cfb.base64
new file mode 100644
index 0000000..c70e576
--- /dev/null
+++ b/samples/pbe/java/aes192-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/im+oIYCd9d7VAJxwuyTKpXnatBA==
diff --git a/samples/pbe/java/aes192-cfb.raw b/samples/pbe/java/aes192-cfb.raw
new file mode 100644
index 0000000..926bbdc
--- /dev/null
+++ b/samples/pbe/java/aes192-cfb.raw
@@ -0,0 +1,2 @@
+Salted__
+�]WW�aM�+`��o�
\ No newline at end of file
diff --git a/samples/pbe/java/aes192-cfb8.base64 b/samples/pbe/java/aes192-cfb8.base64
new file mode 100644
index 0000000..e968571
--- /dev/null
+++ b/samples/pbe/java/aes192-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX186iw+KCu0VBo9RdYAKHo9vNfDSFQ==
diff --git a/samples/pbe/java/aes192-cfb8.raw b/samples/pbe/java/aes192-cfb8.raw
new file mode 100644
index 0000000..a71a670
--- /dev/null
+++ b/samples/pbe/java/aes192-cfb8.raw
@@ -0,0 +1 @@
+Salted__��N��{��a��
�
\ No newline at end of file
diff --git a/samples/pbe/java/aes192-ecb.base64 b/samples/pbe/java/aes192-ecb.base64
new file mode 100644
index 0000000..eaa6ef9
--- /dev/null
+++ b/samples/pbe/java/aes192-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1++cAjnHEiPvcYEXga2MZ/nPphLkC9FDpI=
diff --git a/samples/pbe/java/aes192-ecb.raw b/samples/pbe/java/aes192-ecb.raw
new file mode 100644
index 0000000..f59bb04
--- /dev/null
+++ b/samples/pbe/java/aes192-ecb.raw
@@ -0,0 +1 @@
+Salted__8��X?V�
���
�c�T��є�B��
\ No newline at end of file
diff --git a/samples/pbe/java/aes192-ofb.base64 b/samples/pbe/java/aes192-ofb.base64
new file mode 100644
index 0000000..2055b4f
--- /dev/null
+++ b/samples/pbe/java/aes192-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+tB5EoA+99EgMjaRsrhrIdu+4MgA==
diff --git a/samples/pbe/java/aes192-ofb.raw b/samples/pbe/java/aes192-ofb.raw
new file mode 100644
index 0000000..c13e590
--- /dev/null
+++ b/samples/pbe/java/aes192-ofb.raw
@@ -0,0 +1 @@
+Salted__AQ(��h1�!�a�U�$C7�
\ No newline at end of file
diff --git a/samples/pbe/java/aes192.base64 b/samples/pbe/java/aes192.base64
new file mode 100644
index 0000000..709506b
--- /dev/null
+++ b/samples/pbe/java/aes192.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/FEWgPPq4v5tSeC0JqBLLTmnm3mZyVQy8=
diff --git a/samples/pbe/java/aes192.raw b/samples/pbe/java/aes192.raw
new file mode 100644
index 0000000..efbca29
--- /dev/null
+++ b/samples/pbe/java/aes192.raw
@@ -0,0 +1 @@
+Salted__hJ�~~�
�G8#��WcQҠ���
\ No newline at end of file
diff --git a/samples/pbe/java/aes256-cbc.base64 b/samples/pbe/java/aes256-cbc.base64
new file mode 100644
index 0000000..38172a2
--- /dev/null
+++ b/samples/pbe/java/aes256-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+1PFX6yjmLx//GKR/kI0JcI4BvOsFo54U=
diff --git a/samples/pbe/java/aes256-cbc.raw b/samples/pbe/java/aes256-cbc.raw
new file mode 100644
index 0000000..2536117
--- /dev/null
+++ b/samples/pbe/java/aes256-cbc.raw
@@ -0,0 +1 @@
+Salted__1w����?�X2rϡ�)\�I֦%+
\ No newline at end of file
diff --git a/samples/pbe/java/aes256-cfb.base64 b/samples/pbe/java/aes256-cfb.base64
new file mode 100644
index 0000000..dadb997
--- /dev/null
+++ b/samples/pbe/java/aes256-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX183eIcxGvreiWgqXZzCXPTHbs9t1w==
diff --git a/samples/pbe/java/aes256-cfb.raw b/samples/pbe/java/aes256-cfb.raw
new file mode 100644
index 0000000..7ab062b
--- /dev/null
+++ b/samples/pbe/java/aes256-cfb.raw
@@ -0,0 +1,2 @@
+Salted__�T��qS
+KeU�!����$�
\ No newline at end of file
diff --git a/samples/pbe/java/aes256-cfb8.base64 b/samples/pbe/java/aes256-cfb8.base64
new file mode 100644
index 0000000..44b6c5d
--- /dev/null
+++ b/samples/pbe/java/aes256-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19seCs2x8/p8t0Dzsg0jG5HJpiyug==
diff --git a/samples/pbe/java/aes256-cfb8.raw b/samples/pbe/java/aes256-cfb8.raw
new file mode 100644
index 0000000..f40fb94
--- /dev/null
+++ b/samples/pbe/java/aes256-cfb8.raw
@@ -0,0 +1 @@
+Salted___�oU�����6
����
\ No newline at end of file
diff --git a/samples/pbe/java/aes256-ecb.base64 b/samples/pbe/java/aes256-ecb.base64
new file mode 100644
index 0000000..1c42841
--- /dev/null
+++ b/samples/pbe/java/aes256-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+CklO63OMjBE7V60TyZdccAvOZSoHvdoY=
diff --git a/samples/pbe/java/aes256-ecb.raw b/samples/pbe/java/aes256-ecb.raw
new file mode 100644
index 0000000..9feac0e
--- /dev/null
+++ b/samples/pbe/java/aes256-ecb.raw
@@ -0,0 +1 @@
+Salted__���8�gs����_pT�ù���I7�
\ No newline at end of file
diff --git a/samples/pbe/java/aes256-ofb.base64 b/samples/pbe/java/aes256-ofb.base64
new file mode 100644
index 0000000..dc623be
--- /dev/null
+++ b/samples/pbe/java/aes256-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18MiDOnBD5OkXH/C+Ua2qcjGnVsNQ==
diff --git a/samples/pbe/java/aes256-ofb.raw b/samples/pbe/java/aes256-ofb.raw
new file mode 100644
index 0000000..53e8bd6
--- /dev/null
+++ b/samples/pbe/java/aes256-ofb.raw
@@ -0,0 +1 @@
+Salted__����Ł(�z�����	�|
\ No newline at end of file
diff --git a/samples/pbe/java/aes256.base64 b/samples/pbe/java/aes256.base64
new file mode 100644
index 0000000..2370b34
--- /dev/null
+++ b/samples/pbe/java/aes256.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/qurIuLg/OPdk3l+HU2cYuOfjbKPyU2IQ=
diff --git a/samples/pbe/java/aes256.raw b/samples/pbe/java/aes256.raw
new file mode 100644
index 0000000..30b0252
--- /dev/null
+++ b/samples/pbe/java/aes256.raw
@@ -0,0 +1 @@
+Salted__4��'Tx��񭙏8%kJ"F3�Q
\ No newline at end of file
diff --git a/samples/pbe/java/bf-cbc.base64 b/samples/pbe/java/bf-cbc.base64
new file mode 100644
index 0000000..ded04a6
--- /dev/null
+++ b/samples/pbe/java/bf-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18ezFO/IyruCLWgSXb8ub3xpSJ7ZKoGI+8=
diff --git a/samples/pbe/java/bf-cbc.raw b/samples/pbe/java/bf-cbc.raw
new file mode 100644
index 0000000..db3a502
--- /dev/null
+++ b/samples/pbe/java/bf-cbc.raw
@@ -0,0 +1 @@
+Salted__�>�K���g���9���;S�s���
\ No newline at end of file
diff --git a/samples/pbe/java/bf-cfb.base64 b/samples/pbe/java/bf-cfb.base64
new file mode 100644
index 0000000..135cdad
--- /dev/null
+++ b/samples/pbe/java/bf-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+yi+2LyrXPbswy1jL1yAnXX+MjPA==
diff --git a/samples/pbe/java/bf-cfb.raw b/samples/pbe/java/bf-cfb.raw
new file mode 100644
index 0000000..6784823
--- /dev/null
+++ b/samples/pbe/java/bf-cfb.raw
@@ -0,0 +1 @@
+Salted__�#5�P���Es�ҿ��
\ No newline at end of file
diff --git a/samples/pbe/java/bf-cfb8.base64 b/samples/pbe/java/bf-cfb8.base64
new file mode 100644
index 0000000..622299b
--- /dev/null
+++ b/samples/pbe/java/bf-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Uyb5uwUSF5vlUwT8sTYUUUquHwA==
diff --git a/samples/pbe/java/bf-cfb8.raw b/samples/pbe/java/bf-cfb8.raw
new file mode 100644
index 0000000..00c7c39
--- /dev/null
+++ b/samples/pbe/java/bf-cfb8.raw
@@ -0,0 +1 @@
+Salted__V:�&'3)�T���_��ŕ�5
\ No newline at end of file
diff --git a/samples/pbe/java/bf-ecb.base64 b/samples/pbe/java/bf-ecb.base64
new file mode 100644
index 0000000..fc5d780
--- /dev/null
+++ b/samples/pbe/java/bf-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX181gpdrxNUzjZWSJrri+XaHTk8J2BiwgiY=
diff --git a/samples/pbe/java/bf-ecb.raw b/samples/pbe/java/bf-ecb.raw
new file mode 100644
index 0000000..8ed9cf4
--- /dev/null
+++ b/samples/pbe/java/bf-ecb.raw
@@ -0,0 +1 @@
+Salted__�76�f���{Ou�PXJ�R��:A�
\ No newline at end of file
diff --git a/samples/pbe/java/bf-ofb.base64 b/samples/pbe/java/bf-ofb.base64
new file mode 100644
index 0000000..e86bec9
--- /dev/null
+++ b/samples/pbe/java/bf-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/Lzlz4ROS2VIJm3BDuISIlhXyqIA==
diff --git a/samples/pbe/java/bf-ofb.raw b/samples/pbe/java/bf-ofb.raw
new file mode 100644
index 0000000..2c55382
--- /dev/null
+++ b/samples/pbe/java/bf-ofb.raw
@@ -0,0 +1 @@
+Salted__T�<���H�F��>�U���B
\ No newline at end of file
diff --git a/samples/pbe/java/bf.base64 b/samples/pbe/java/bf.base64
new file mode 100644
index 0000000..8d02877
--- /dev/null
+++ b/samples/pbe/java/bf.base64
@@ -0,0 +1 @@
+U2FsdGVkX19e7ErlyQFrRuAvkXC+RpF8qq4NUNtwP0Y=
diff --git a/samples/pbe/java/bf.raw b/samples/pbe/java/bf.raw
new file mode 100644
index 0000000..5368738
--- /dev/null
+++ b/samples/pbe/java/bf.raw
@@ -0,0 +1 @@
+Salted__m
O�T5
T�ؾ��!���Zw|6�
\ No newline at end of file
diff --git a/samples/pbe/java/blowfish-cbc.base64 b/samples/pbe/java/blowfish-cbc.base64
new file mode 100644
index 0000000..4a9bc76
--- /dev/null
+++ b/samples/pbe/java/blowfish-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/X9q7FxWKC+Nt4r1Tbx9Lq8iGgpYLA9VU=
diff --git a/samples/pbe/java/blowfish-cbc.raw b/samples/pbe/java/blowfish-cbc.raw
new file mode 100644
index 0000000..cbb2039
--- /dev/null
+++ b/samples/pbe/java/blowfish-cbc.raw
@@ -0,0 +1 @@
+Salted__B�uk��$2�6+d.�����'�H
\ No newline at end of file
diff --git a/samples/pbe/java/blowfish-cfb.base64 b/samples/pbe/java/blowfish-cfb.base64
new file mode 100644
index 0000000..e5cd0bf
--- /dev/null
+++ b/samples/pbe/java/blowfish-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+BMJfwsI5pN/TlN21qZpmkKZ+ZCQ==
diff --git a/samples/pbe/java/blowfish-cfb.raw b/samples/pbe/java/blowfish-cfb.raw
new file mode 100644
index 0000000..760e562
--- /dev/null
+++ b/samples/pbe/java/blowfish-cfb.raw
@@ -0,0 +1 @@
+Salted__�F��<A�A�	�j�c+��z	
\ No newline at end of file
diff --git a/samples/pbe/java/blowfish-cfb8.base64 b/samples/pbe/java/blowfish-cfb8.base64
new file mode 100644
index 0000000..06efdcf
--- /dev/null
+++ b/samples/pbe/java/blowfish-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19QNGPN4Mb7Bj9fdwfr2ICVZxIqyw==
diff --git a/samples/pbe/java/blowfish-cfb8.raw b/samples/pbe/java/blowfish-cfb8.raw
new file mode 100644
index 0000000..e13828b
--- /dev/null
+++ b/samples/pbe/java/blowfish-cfb8.raw
@@ -0,0 +1 @@
+Salted__K��

T�ݬ
F{$L/�
\ No newline at end of file
diff --git a/samples/pbe/java/blowfish-ecb.base64 b/samples/pbe/java/blowfish-ecb.base64
new file mode 100644
index 0000000..28b6573
--- /dev/null
+++ b/samples/pbe/java/blowfish-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/n+y1mOrx0j2A70eSTKaG7xu+WCNzzEkI=
diff --git a/samples/pbe/java/blowfish-ecb.raw b/samples/pbe/java/blowfish-ecb.raw
new file mode 100644
index 0000000..6ed74b3
--- /dev/null
+++ b/samples/pbe/java/blowfish-ecb.raw
@@ -0,0 +1 @@
+Salted__�̍3�s2X����Ϗy
���o�
\ No newline at end of file
diff --git a/samples/pbe/java/blowfish-ofb.base64 b/samples/pbe/java/blowfish-ofb.base64
new file mode 100644
index 0000000..2f02531
--- /dev/null
+++ b/samples/pbe/java/blowfish-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18skzs84vkC6FRTjlxDau6lzgx3Jg==
diff --git a/samples/pbe/java/blowfish-ofb.raw b/samples/pbe/java/blowfish-ofb.raw
new file mode 100644
index 0000000..754bf21
--- /dev/null
+++ b/samples/pbe/java/blowfish-ofb.raw
@@ -0,0 +1,2 @@
+Salted__���
+郖0`�񗔃�]��
\ No newline at end of file
diff --git a/samples/pbe/java/blowfish.base64 b/samples/pbe/java/blowfish.base64
new file mode 100644
index 0000000..a490a9c
--- /dev/null
+++ b/samples/pbe/java/blowfish.base64
@@ -0,0 +1 @@
+U2FsdGVkX18wu3hD9dgyO87j8nRXmczPqDItEunKLUQ=
diff --git a/samples/pbe/java/blowfish.raw b/samples/pbe/java/blowfish.raw
new file mode 100644
index 0000000..fe880fe
--- /dev/null
+++ b/samples/pbe/java/blowfish.raw
@@ -0,0 +1 @@
+Salted__�E�
�rW1��އ�#�R�@�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-128-cbc.base64 b/samples/pbe/java/camellia-128-cbc.base64
new file mode 100644
index 0000000..8985e91
--- /dev/null
+++ b/samples/pbe/java/camellia-128-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18UUwHvDEACb8VSquyKXfA9Ht7vMiGa/Sc=
diff --git a/samples/pbe/java/camellia-128-cbc.raw b/samples/pbe/java/camellia-128-cbc.raw
new file mode 100644
index 0000000..7f72b0a
--- /dev/null
+++ b/samples/pbe/java/camellia-128-cbc.raw
@@ -0,0 +1 @@
+Salted__�fF�kP{vJ �Bݐ1���|=�͑
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-128-cfb.base64 b/samples/pbe/java/camellia-128-cfb.base64
new file mode 100644
index 0000000..0a86dab
--- /dev/null
+++ b/samples/pbe/java/camellia-128-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/Q+yrw31FhRJYcii+47v+ekN09bg==
diff --git a/samples/pbe/java/camellia-128-cfb.raw b/samples/pbe/java/camellia-128-cfb.raw
new file mode 100644
index 0000000..f574d0f
Binary files /dev/null and b/samples/pbe/java/camellia-128-cfb.raw differ
diff --git a/samples/pbe/java/camellia-128-cfb8.base64 b/samples/pbe/java/camellia-128-cfb8.base64
new file mode 100644
index 0000000..b259ca7
--- /dev/null
+++ b/samples/pbe/java/camellia-128-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18/hQSHjwmpABUe/TaPQPR3gockqw==
diff --git a/samples/pbe/java/camellia-128-cfb8.raw b/samples/pbe/java/camellia-128-cfb8.raw
new file mode 100644
index 0000000..e0f16ea
--- /dev/null
+++ b/samples/pbe/java/camellia-128-cfb8.raw
@@ -0,0 +1 @@
+Salted__'1&{��v/U�$�N���
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-128-ecb.base64 b/samples/pbe/java/camellia-128-ecb.base64
new file mode 100644
index 0000000..be0e863
--- /dev/null
+++ b/samples/pbe/java/camellia-128-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19NFzHbs8FHT8Cv99Xgj1ZhPx5CY072tZA=
diff --git a/samples/pbe/java/camellia-128-ecb.raw b/samples/pbe/java/camellia-128-ecb.raw
new file mode 100644
index 0000000..adfafc5
--- /dev/null
+++ b/samples/pbe/java/camellia-128-ecb.raw
@@ -0,0 +1 @@
+Salted__����1�f0`8F��U
+PeE	�#
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-128-ofb.base64 b/samples/pbe/java/camellia-128-ofb.base64
new file mode 100644
index 0000000..4c35120
--- /dev/null
+++ b/samples/pbe/java/camellia-128-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Q5WKPCdvjapTYHjJhZQQuPBrkcA==
diff --git a/samples/pbe/java/camellia-128-ofb.raw b/samples/pbe/java/camellia-128-ofb.raw
new file mode 100644
index 0000000..529bc7d
--- /dev/null
+++ b/samples/pbe/java/camellia-128-ofb.raw
@@ -0,0 +1 @@
+Salted__#�A��=��ɷɭ.
�g��(
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-128.base64 b/samples/pbe/java/camellia-128.base64
new file mode 100644
index 0000000..09d8760
--- /dev/null
+++ b/samples/pbe/java/camellia-128.base64
@@ -0,0 +1 @@
+U2FsdGVkX18pM4u/Qtl2csttKUV+nu0wBwTi3joioNA=
diff --git a/samples/pbe/java/camellia-128.raw b/samples/pbe/java/camellia-128.raw
new file mode 100644
index 0000000..a9c64ac
--- /dev/null
+++ b/samples/pbe/java/camellia-128.raw
@@ -0,0 +1 @@
+Salted__e{yə;_f`c�5
3	E�q|�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-192-cbc.base64 b/samples/pbe/java/camellia-192-cbc.base64
new file mode 100644
index 0000000..4fab5d0
--- /dev/null
+++ b/samples/pbe/java/camellia-192-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19hH0OOcN4S/DJcOixmApLIQKyU1wgtpOQ=
diff --git a/samples/pbe/java/camellia-192-cbc.raw b/samples/pbe/java/camellia-192-cbc.raw
new file mode 100644
index 0000000..ac75809
--- /dev/null
+++ b/samples/pbe/java/camellia-192-cbc.raw
@@ -0,0 +1 @@
+Salted__�A�IY��v�-3��d����
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-192-cfb.base64 b/samples/pbe/java/camellia-192-cfb.base64
new file mode 100644
index 0000000..e3dee68
--- /dev/null
+++ b/samples/pbe/java/camellia-192-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+4PAXIOayucO/VkxrUWXLbch6StA==
diff --git a/samples/pbe/java/camellia-192-cfb.raw b/samples/pbe/java/camellia-192-cfb.raw
new file mode 100644
index 0000000..6a6c380
--- /dev/null
+++ b/samples/pbe/java/camellia-192-cfb.raw
@@ -0,0 +1,2 @@
+Salted__��
�)
D
+��f�SB�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-192-cfb8.base64 b/samples/pbe/java/camellia-192-cfb8.base64
new file mode 100644
index 0000000..625f35e
--- /dev/null
+++ b/samples/pbe/java/camellia-192-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+5lUexVeB0SO+iMPa6ZwZk66DKag==
diff --git a/samples/pbe/java/camellia-192-cfb8.raw b/samples/pbe/java/camellia-192-cfb8.raw
new file mode 100644
index 0000000..e8ecfa6
--- /dev/null
+++ b/samples/pbe/java/camellia-192-cfb8.raw
@@ -0,0 +1 @@
+Salted__�y�

6NӜ:!dVH
��
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-192-ecb.base64 b/samples/pbe/java/camellia-192-ecb.base64
new file mode 100644
index 0000000..97f32b5
--- /dev/null
+++ b/samples/pbe/java/camellia-192-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/fOdsaCQa26731P7m0VWbMA5c3Lhs3CjU=
diff --git a/samples/pbe/java/camellia-192-ecb.raw b/samples/pbe/java/camellia-192-ecb.raw
new file mode 100644
index 0000000..ebc6b97
--- /dev/null
+++ b/samples/pbe/java/camellia-192-ecb.raw
@@ -0,0 +1 @@
+Salted__�U��s{&^�s<��{4Z�Zr�b
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-192-ofb.base64 b/samples/pbe/java/camellia-192-ofb.base64
new file mode 100644
index 0000000..5959fa1
--- /dev/null
+++ b/samples/pbe/java/camellia-192-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+atqsl2Yfj4LlRabl6AlyTOUhm5Q==
diff --git a/samples/pbe/java/camellia-192-ofb.raw b/samples/pbe/java/camellia-192-ofb.raw
new file mode 100644
index 0000000..2a23190
--- /dev/null
+++ b/samples/pbe/java/camellia-192-ofb.raw
@@ -0,0 +1 @@
+Salted__�Ez@����{H�~͍���
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-192.base64 b/samples/pbe/java/camellia-192.base64
new file mode 100644
index 0000000..f3beeb2
--- /dev/null
+++ b/samples/pbe/java/camellia-192.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/XopevJykDpkmcOdCQ0WjGxvSOKCvrheI=
diff --git a/samples/pbe/java/camellia-192.raw b/samples/pbe/java/camellia-192.raw
new file mode 100644
index 0000000..0044d7f
--- /dev/null
+++ b/samples/pbe/java/camellia-192.raw
@@ -0,0 +1 @@
+Salted__OJ�)
O��z�1n��%Z�G�g
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-256-cbc.base64 b/samples/pbe/java/camellia-256-cbc.base64
new file mode 100644
index 0000000..0765452
--- /dev/null
+++ b/samples/pbe/java/camellia-256-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX192V/ik6+M1vv4ezzXSKP/mrjtXi1XFaFM=
diff --git a/samples/pbe/java/camellia-256-cbc.raw b/samples/pbe/java/camellia-256-cbc.raw
new file mode 100644
index 0000000..eaf4c12
--- /dev/null
+++ b/samples/pbe/java/camellia-256-cbc.raw
@@ -0,0 +1 @@
+Salted__�!�+���ܼn'>�x��T3���H�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-256-cfb.base64 b/samples/pbe/java/camellia-256-cfb.base64
new file mode 100644
index 0000000..5cb9834
--- /dev/null
+++ b/samples/pbe/java/camellia-256-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18uQkCC3dp9kV1C1HcQ+iR7DNDkNQ==
diff --git a/samples/pbe/java/camellia-256-cfb.raw b/samples/pbe/java/camellia-256-cfb.raw
new file mode 100644
index 0000000..19415b5
--- /dev/null
+++ b/samples/pbe/java/camellia-256-cfb.raw
@@ -0,0 +1 @@
+Salted___���\��{I����/Ɖ
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-256-cfb8.base64 b/samples/pbe/java/camellia-256-cfb8.base64
new file mode 100644
index 0000000..e9b247f
--- /dev/null
+++ b/samples/pbe/java/camellia-256-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/AjinqENb4F5Qz5UoLF4euYSUXtg==
diff --git a/samples/pbe/java/camellia-256-cfb8.raw b/samples/pbe/java/camellia-256-cfb8.raw
new file mode 100644
index 0000000..696b584
--- /dev/null
+++ b/samples/pbe/java/camellia-256-cfb8.raw
@@ -0,0 +1 @@
+Salted__I?k�x}�̀��Y��2��G
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-256-ecb.base64 b/samples/pbe/java/camellia-256-ecb.base64
new file mode 100644
index 0000000..fa856d9
--- /dev/null
+++ b/samples/pbe/java/camellia-256-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+LDceo9kKIBEFjQgELUkN7Kub52saETYE=
diff --git a/samples/pbe/java/camellia-256-ecb.raw b/samples/pbe/java/camellia-256-ecb.raw
new file mode 100644
index 0000000..ffbd183
--- /dev/null
+++ b/samples/pbe/java/camellia-256-ecb.raw
@@ -0,0 +1 @@
+Salted__<���aUA<�6��V�<�޳�B
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-256-ofb.base64 b/samples/pbe/java/camellia-256-ofb.base64
new file mode 100644
index 0000000..919b311
--- /dev/null
+++ b/samples/pbe/java/camellia-256-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+GkVrOLtvxbkF+hFDSsmAp6IIi/g==
diff --git a/samples/pbe/java/camellia-256-ofb.raw b/samples/pbe/java/camellia-256-ofb.raw
new file mode 100644
index 0000000..1102772
--- /dev/null
+++ b/samples/pbe/java/camellia-256-ofb.raw
@@ -0,0 +1 @@
+Salted__����5Y��Je��,�w�$
\ No newline at end of file
diff --git a/samples/pbe/java/camellia-256.base64 b/samples/pbe/java/camellia-256.base64
new file mode 100644
index 0000000..918ac17
--- /dev/null
+++ b/samples/pbe/java/camellia-256.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/j884tRPxO0F0El64xyT3n+W83Wb9Z9nc=
diff --git a/samples/pbe/java/camellia-256.raw b/samples/pbe/java/camellia-256.raw
new file mode 100644
index 0000000..50d7b8a
--- /dev/null
+++ b/samples/pbe/java/camellia-256.raw
@@ -0,0 +1 @@
+Salted__cvls6S��\�<{
��.�Wv,	��
\ No newline at end of file
diff --git a/samples/pbe/java/camellia128-cbc.base64 b/samples/pbe/java/camellia128-cbc.base64
new file mode 100644
index 0000000..2a964ad
--- /dev/null
+++ b/samples/pbe/java/camellia128-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+90QGejW9gW74l1S1eCmxQTa83xaYf5cg=
diff --git a/samples/pbe/java/camellia128-cbc.raw b/samples/pbe/java/camellia128-cbc.raw
new file mode 100644
index 0000000..428af0c
--- /dev/null
+++ b/samples/pbe/java/camellia128-cbc.raw
@@ -0,0 +1 @@
+Salted__wT�ػ��-zp��R�;^�P��õT
\ No newline at end of file
diff --git a/samples/pbe/java/camellia128-cfb.base64 b/samples/pbe/java/camellia128-cfb.base64
new file mode 100644
index 0000000..07fc3cd
--- /dev/null
+++ b/samples/pbe/java/camellia128-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18OWnOuxyR4YO6FGRH/7yqDm3CmLQ==
diff --git a/samples/pbe/java/camellia128-cfb.raw b/samples/pbe/java/camellia128-cfb.raw
new file mode 100644
index 0000000..c3f0470
--- /dev/null
+++ b/samples/pbe/java/camellia128-cfb.raw
@@ -0,0 +1 @@
+Salted__
睍_T�K�/^a�{�CՕ�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia128-cfb8.base64 b/samples/pbe/java/camellia128-cfb8.base64
new file mode 100644
index 0000000..8362065
--- /dev/null
+++ b/samples/pbe/java/camellia128-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18DU/8DbLesx+kp1xFyVzbL0oOGGw==
diff --git a/samples/pbe/java/camellia128-cfb8.raw b/samples/pbe/java/camellia128-cfb8.raw
new file mode 100644
index 0000000..1a9483e
--- /dev/null
+++ b/samples/pbe/java/camellia128-cfb8.raw
@@ -0,0 +1 @@
+Salted__{��<����@w���Cc�~T
\ No newline at end of file
diff --git a/samples/pbe/java/camellia128-ecb.base64 b/samples/pbe/java/camellia128-ecb.base64
new file mode 100644
index 0000000..9556b3b
--- /dev/null
+++ b/samples/pbe/java/camellia128-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+1iqH8lq6+SuZgeWxcbUoZ4dBYxTjVQ1I=
diff --git a/samples/pbe/java/camellia128-ecb.raw b/samples/pbe/java/camellia128-ecb.raw
new file mode 100644
index 0000000..fde676e
--- /dev/null
+++ b/samples/pbe/java/camellia128-ecb.raw
@@ -0,0 +1 @@
+Salted__j�q/3��i��l1!���\5
d�`�

\ No newline at end of file
diff --git a/samples/pbe/java/camellia128-ofb.base64 b/samples/pbe/java/camellia128-ofb.base64
new file mode 100644
index 0000000..89f0255
--- /dev/null
+++ b/samples/pbe/java/camellia128-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX189RpQrEO2Xy/3zDHr7Or6Tg0c/AQ==
diff --git a/samples/pbe/java/camellia128-ofb.raw b/samples/pbe/java/camellia128-ofb.raw
new file mode 100644
index 0000000..37caed2
--- /dev/null
+++ b/samples/pbe/java/camellia128-ofb.raw
@@ -0,0 +1 @@
+Salted__
kr���^�����2f��D
\ No newline at end of file
diff --git a/samples/pbe/java/camellia128.base64 b/samples/pbe/java/camellia128.base64
new file mode 100644
index 0000000..66c6feb
--- /dev/null
+++ b/samples/pbe/java/camellia128.base64
@@ -0,0 +1 @@
+U2FsdGVkX19fNMlxVQ+gfD1AF55ct5dna+5gIcFnHMI=
diff --git a/samples/pbe/java/camellia128.raw b/samples/pbe/java/camellia128.raw
new file mode 100644
index 0000000..e6f4e0a
--- /dev/null
+++ b/samples/pbe/java/camellia128.raw
@@ -0,0 +1 @@
+Salted__?A���//��YE�WA���C�V
\ No newline at end of file
diff --git a/samples/pbe/java/camellia192-cbc.base64 b/samples/pbe/java/camellia192-cbc.base64
new file mode 100644
index 0000000..41f445b
--- /dev/null
+++ b/samples/pbe/java/camellia192-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/bDUbd0pqAOeDb1gNIpKqi3DK4iwO7YoA=
diff --git a/samples/pbe/java/camellia192-cbc.raw b/samples/pbe/java/camellia192-cbc.raw
new file mode 100644
index 0000000..29212ab
--- /dev/null
+++ b/samples/pbe/java/camellia192-cbc.raw
@@ -0,0 +1 @@
+Salted__+2!�ԭ�G
I)Ѿ��[�oRZ�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia192-cfb.base64 b/samples/pbe/java/camellia192-cfb.base64
new file mode 100644
index 0000000..615f4b3
--- /dev/null
+++ b/samples/pbe/java/camellia192-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/jPapheHbcuHbq060VPb/lVaN60Q==
diff --git a/samples/pbe/java/camellia192-cfb.raw b/samples/pbe/java/camellia192-cfb.raw
new file mode 100644
index 0000000..bba9f78
--- /dev/null
+++ b/samples/pbe/java/camellia192-cfb.raw
@@ -0,0 +1 @@
+Salted__�̱�*oV��&`����t�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia192-cfb8.base64 b/samples/pbe/java/camellia192-cfb8.base64
new file mode 100644
index 0000000..7c5829d
--- /dev/null
+++ b/samples/pbe/java/camellia192-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/L73xES8AWci9th/emGwI9bSXU0A==
diff --git a/samples/pbe/java/camellia192-cfb8.raw b/samples/pbe/java/camellia192-cfb8.raw
new file mode 100644
index 0000000..dd34c2d
--- /dev/null
+++ b/samples/pbe/java/camellia192-cfb8.raw
@@ -0,0 +1 @@
+Salted__���h"��..�����.v?�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia192-ecb.base64 b/samples/pbe/java/camellia192-ecb.base64
new file mode 100644
index 0000000..0313532
--- /dev/null
+++ b/samples/pbe/java/camellia192-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+THzBGYxZA+1R9rza4Lv9SrWl/sPmmkso=
diff --git a/samples/pbe/java/camellia192-ecb.raw b/samples/pbe/java/camellia192-ecb.raw
new file mode 100644
index 0000000..76ffb51
--- /dev/null
+++ b/samples/pbe/java/camellia192-ecb.raw
@@ -0,0 +1 @@
+Salted__VX$����H(g����FO

yE�ā
\ No newline at end of file
diff --git a/samples/pbe/java/camellia192-ofb.base64 b/samples/pbe/java/camellia192-ofb.base64
new file mode 100644
index 0000000..f0a66bf
--- /dev/null
+++ b/samples/pbe/java/camellia192-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+fbFYKjBd8c3PMWewNTe+qTHYxjw==
diff --git a/samples/pbe/java/camellia192-ofb.raw b/samples/pbe/java/camellia192-ofb.raw
new file mode 100644
index 0000000..a9806c8
--- /dev/null
+++ b/samples/pbe/java/camellia192-ofb.raw
@@ -0,0 +1 @@
+Salted__�t��%T�PK||ACi�º�=
\ No newline at end of file
diff --git a/samples/pbe/java/camellia192.base64 b/samples/pbe/java/camellia192.base64
new file mode 100644
index 0000000..3adc735
--- /dev/null
+++ b/samples/pbe/java/camellia192.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/7J6aNaQ3OKgOvbscFo5no/fy72MJk5Fc=
diff --git a/samples/pbe/java/camellia192.raw b/samples/pbe/java/camellia192.raw
new file mode 100644
index 0000000..4546f6d
--- /dev/null
+++ b/samples/pbe/java/camellia192.raw
@@ -0,0 +1 @@
+Salted__�opD�ƌ�u)۷�c�0d���T
\ No newline at end of file
diff --git a/samples/pbe/java/camellia256-cbc.base64 b/samples/pbe/java/camellia256-cbc.base64
new file mode 100644
index 0000000..20369ea
--- /dev/null
+++ b/samples/pbe/java/camellia256-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+l901jK4fyHQe8zTyOALNfuKuDLDNjNpI=
diff --git a/samples/pbe/java/camellia256-cbc.raw b/samples/pbe/java/camellia256-cbc.raw
new file mode 100644
index 0000000..4d58a2f
--- /dev/null
+++ b/samples/pbe/java/camellia256-cbc.raw
@@ -0,0 +1 @@
+Salted__�.�F'��
�
R.oRe ���#p�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia256-cfb.base64 b/samples/pbe/java/camellia256-cfb.base64
new file mode 100644
index 0000000..aeed858
--- /dev/null
+++ b/samples/pbe/java/camellia256-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX197NNyKW2xVNRjtMbyMbMKc89L68w==
diff --git a/samples/pbe/java/camellia256-cfb.raw b/samples/pbe/java/camellia256-cfb.raw
new file mode 100644
index 0000000..3678157
--- /dev/null
+++ b/samples/pbe/java/camellia256-cfb.raw
@@ -0,0 +1 @@
+Salted__g�gA�Z��h�Q�<>7��
\ No newline at end of file
diff --git a/samples/pbe/java/camellia256-cfb8.base64 b/samples/pbe/java/camellia256-cfb8.base64
new file mode 100644
index 0000000..cedb3d3
--- /dev/null
+++ b/samples/pbe/java/camellia256-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/zIoOUOwApRSAN5J0Sr/j+Swe5nw==
diff --git a/samples/pbe/java/camellia256-cfb8.raw b/samples/pbe/java/camellia256-cfb8.raw
new file mode 100644
index 0000000..688f31e
--- /dev/null
+++ b/samples/pbe/java/camellia256-cfb8.raw
@@ -0,0 +1 @@
+Salted__(�]��ò~i�����,�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia256-ecb.base64 b/samples/pbe/java/camellia256-ecb.base64
new file mode 100644
index 0000000..c8bd5c5
--- /dev/null
+++ b/samples/pbe/java/camellia256-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Tln+csf9eJsEYdZC45soI+sOC4dMfd4c=
diff --git a/samples/pbe/java/camellia256-ecb.raw b/samples/pbe/java/camellia256-ecb.raw
new file mode 100644
index 0000000..27cf65b
--- /dev/null
+++ b/samples/pbe/java/camellia256-ecb.raw
@@ -0,0 +1 @@
+Salted__�0.�0'/������K�d!qX�MP�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia256-ofb.base64 b/samples/pbe/java/camellia256-ofb.base64
new file mode 100644
index 0000000..593bd2b
--- /dev/null
+++ b/samples/pbe/java/camellia256-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1896Yqjj8AfXnc0eFYKai5KxoCXzQ==
diff --git a/samples/pbe/java/camellia256-ofb.raw b/samples/pbe/java/camellia256-ofb.raw
new file mode 100644
index 0000000..d49ef81
--- /dev/null
+++ b/samples/pbe/java/camellia256-ofb.raw
@@ -0,0 +1 @@
+Salted__���U�Ԟ��*+C�g2�Tl�
\ No newline at end of file
diff --git a/samples/pbe/java/camellia256.base64 b/samples/pbe/java/camellia256.base64
new file mode 100644
index 0000000..990ca5c
--- /dev/null
+++ b/samples/pbe/java/camellia256.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+oGF8zlK3aSF//rgeWimAvobywbD+PD0g=
diff --git a/samples/pbe/java/camellia256.raw b/samples/pbe/java/camellia256.raw
new file mode 100644
index 0000000..83f0ac5
--- /dev/null
+++ b/samples/pbe/java/camellia256.raw
@@ -0,0 +1 @@
+Salted__x���
�i������.�	��A
\ No newline at end of file
diff --git a/samples/pbe/java/cast5-cbc.base64 b/samples/pbe/java/cast5-cbc.base64
new file mode 100644
index 0000000..3a217bc
--- /dev/null
+++ b/samples/pbe/java/cast5-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/aeco/gkhE72hth3Mn74hFGnCdFZfi3Q4=
diff --git a/samples/pbe/java/cast5-cbc.raw b/samples/pbe/java/cast5-cbc.raw
new file mode 100644
index 0000000..429fb3a
--- /dev/null
+++ b/samples/pbe/java/cast5-cbc.raw
@@ -0,0 +1 @@
+Salted__���%�cQL�
�O�Ŋ7�6�F*C
\ No newline at end of file
diff --git a/samples/pbe/java/cast5-cfb.base64 b/samples/pbe/java/cast5-cfb.base64
new file mode 100644
index 0000000..cc97783
--- /dev/null
+++ b/samples/pbe/java/cast5-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+EbjjSoQ/tSg0b+dJNWWAkSFlARQ==
diff --git a/samples/pbe/java/cast5-cfb.raw b/samples/pbe/java/cast5-cfb.raw
new file mode 100644
index 0000000..ae2cbbb
--- /dev/null
+++ b/samples/pbe/java/cast5-cfb.raw
@@ -0,0 +1 @@
+Salted__��ˉ
z�B�x%	
��j
\ No newline at end of file
diff --git a/samples/pbe/java/cast5-cfb8.base64 b/samples/pbe/java/cast5-cfb8.base64
new file mode 100644
index 0000000..fc3803e
--- /dev/null
+++ b/samples/pbe/java/cast5-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18+YZ72SS+beeJ0eEqzEUWLKoBz+g==
diff --git a/samples/pbe/java/cast5-cfb8.raw b/samples/pbe/java/cast5-cfb8.raw
new file mode 100644
index 0000000..f24154d
--- /dev/null
+++ b/samples/pbe/java/cast5-cfb8.raw
@@ -0,0 +1 @@
+Salted__$/��+1
�؀�����3�>�
\ No newline at end of file
diff --git a/samples/pbe/java/cast5-ecb.base64 b/samples/pbe/java/cast5-ecb.base64
new file mode 100644
index 0000000..448937a
--- /dev/null
+++ b/samples/pbe/java/cast5-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1++7eyxWebJMaj41x5xlLEDODwl+wrhRaI=
diff --git a/samples/pbe/java/cast5-ecb.raw b/samples/pbe/java/cast5-ecb.raw
new file mode 100644
index 0000000..a94ff03
--- /dev/null
+++ b/samples/pbe/java/cast5-ecb.raw
@@ -0,0 +1 @@
+Salted__�
.�ݷG"���{�d
8غ*v
\ No newline at end of file
diff --git a/samples/pbe/java/cast5-ofb.base64 b/samples/pbe/java/cast5-ofb.base64
new file mode 100644
index 0000000..22dddf4
--- /dev/null
+++ b/samples/pbe/java/cast5-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19hCVMpUfZQxakwK4dFKSTQuguAUw==
diff --git a/samples/pbe/java/cast5-ofb.raw b/samples/pbe/java/cast5-ofb.raw
new file mode 100644
index 0000000..e20f9fe
--- /dev/null
+++ b/samples/pbe/java/cast5-ofb.raw
@@ -0,0 +1 @@
+Salted__��cr�f��aO^��q�.�
\ No newline at end of file
diff --git a/samples/pbe/java/cast5.base64 b/samples/pbe/java/cast5.base64
new file mode 100644
index 0000000..44daae6
--- /dev/null
+++ b/samples/pbe/java/cast5.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+ezI1ZQcPD4e1zE7jkWZlGFmScgZFucHY=
diff --git a/samples/pbe/java/cast5.raw b/samples/pbe/java/cast5.raw
new file mode 100644
index 0000000..dfbaaff
--- /dev/null
+++ b/samples/pbe/java/cast5.raw
@@ -0,0 +1,2 @@
+Salted__
+;�yl�����WI��^���˯�Y
\ No newline at end of file
diff --git a/samples/pbe/java/cast6-cbc.base64 b/samples/pbe/java/cast6-cbc.base64
new file mode 100644
index 0000000..3608069
--- /dev/null
+++ b/samples/pbe/java/cast6-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/a8L9HYZcz3S1WhQ3o0R0ebahweJnv+IU=
diff --git a/samples/pbe/java/cast6-cbc.raw b/samples/pbe/java/cast6-cbc.raw
new file mode 100644
index 0000000..6bf7b34
--- /dev/null
+++ b/samples/pbe/java/cast6-cbc.raw
@@ -0,0 +1 @@
+Salted__��Nۥ�뼫��Ԓ�;z!"��
P}
\ No newline at end of file
diff --git a/samples/pbe/java/cast6-cfb.base64 b/samples/pbe/java/cast6-cfb.base64
new file mode 100644
index 0000000..adcf160
--- /dev/null
+++ b/samples/pbe/java/cast6-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+YfAvrxD0wSn/fpojGN9tJkg9DgA==
diff --git a/samples/pbe/java/cast6-cfb.raw b/samples/pbe/java/cast6-cfb.raw
new file mode 100644
index 0000000..8846469
--- /dev/null
+++ b/samples/pbe/java/cast6-cfb.raw
@@ -0,0 +1 @@
+Salted__���v91�^@7xRw�)R���
\ No newline at end of file
diff --git a/samples/pbe/java/cast6-cfb8.base64 b/samples/pbe/java/cast6-cfb8.base64
new file mode 100644
index 0000000..11bfab4
--- /dev/null
+++ b/samples/pbe/java/cast6-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+LpuG379U9ZMFOh0FUkcWovxPSqA==
diff --git a/samples/pbe/java/cast6-cfb8.raw b/samples/pbe/java/cast6-cfb8.raw
new file mode 100644
index 0000000..0522ed0
--- /dev/null
+++ b/samples/pbe/java/cast6-cfb8.raw
@@ -0,0 +1 @@
+Salted__�1�Ku�SvZo��Hvl
\ No newline at end of file
diff --git a/samples/pbe/java/cast6-ecb.base64 b/samples/pbe/java/cast6-ecb.base64
new file mode 100644
index 0000000..603266d
--- /dev/null
+++ b/samples/pbe/java/cast6-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX192UiTkDb8gI6sTTfy7VGsbT30KNWOT02M=
diff --git a/samples/pbe/java/cast6-ecb.raw b/samples/pbe/java/cast6-ecb.raw
new file mode 100644
index 0000000..44148b7
--- /dev/null
+++ b/samples/pbe/java/cast6-ecb.raw
@@ -0,0 +1 @@
+Salted__g0�@|��
��U��8Y�(j/�

\ No newline at end of file
diff --git a/samples/pbe/java/cast6-ofb.base64 b/samples/pbe/java/cast6-ofb.base64
new file mode 100644
index 0000000..08722f1
--- /dev/null
+++ b/samples/pbe/java/cast6-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Y0QSZwFfDFhEAflkjtX4PXaaifQ==
diff --git a/samples/pbe/java/cast6-ofb.raw b/samples/pbe/java/cast6-ofb.raw
new file mode 100644
index 0000000..42ce837
--- /dev/null
+++ b/samples/pbe/java/cast6-ofb.raw
@@ -0,0 +1 @@
+Salted__]�!�ɽ��“L��,_�h�
\ No newline at end of file
diff --git a/samples/pbe/java/cast6.base64 b/samples/pbe/java/cast6.base64
new file mode 100644
index 0000000..cee1c7a
--- /dev/null
+++ b/samples/pbe/java/cast6.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+QGJCVEnV4Fw5TlflsQhmEM67/RwhUcLY=
diff --git a/samples/pbe/java/cast6.raw b/samples/pbe/java/cast6.raw
new file mode 100644
index 0000000..b4c8ce3
--- /dev/null
+++ b/samples/pbe/java/cast6.raw
@@ -0,0 +1 @@
+Salted__��*�P}C�������b�.B�/�
\ No newline at end of file
diff --git a/samples/pbe/java/des-cbc.base64 b/samples/pbe/java/des-cbc.base64
new file mode 100644
index 0000000..69c2e01
--- /dev/null
+++ b/samples/pbe/java/des-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+qcAmoytN0qF45xG/KHt6ANo7zZXDN4L4=
diff --git a/samples/pbe/java/des-cbc.raw b/samples/pbe/java/des-cbc.raw
new file mode 100644
index 0000000..941dbdd
--- /dev/null
+++ b/samples/pbe/java/des-cbc.raw
@@ -0,0 +1 @@
+Salted__Bg�e�g�uنヌ�y׶
�Q��"
\ No newline at end of file
diff --git a/samples/pbe/java/des-cfb.base64 b/samples/pbe/java/des-cfb.base64
new file mode 100644
index 0000000..8da3e5c
--- /dev/null
+++ b/samples/pbe/java/des-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+f4Sv6TZeWD5LH6tNPJJgMk4LuRQ==
diff --git a/samples/pbe/java/des-cfb.raw b/samples/pbe/java/des-cfb.raw
new file mode 100644
index 0000000..b11801f
--- /dev/null
+++ b/samples/pbe/java/des-cfb.raw
@@ -0,0 +1 @@
+Salted__��
�Bj�fz	O���zl�R�
\ No newline at end of file
diff --git a/samples/pbe/java/des-cfb8.base64 b/samples/pbe/java/des-cfb8.base64
new file mode 100644
index 0000000..bd26500
--- /dev/null
+++ b/samples/pbe/java/des-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18oeqMoo7b5vmE3Z5rV+qaIXfMqPg==
diff --git a/samples/pbe/java/des-cfb8.raw b/samples/pbe/java/des-cfb8.raw
new file mode 100644
index 0000000..4735615
--- /dev/null
+++ b/samples/pbe/java/des-cfb8.raw
@@ -0,0 +1 @@
+Salted__R�xBk+ɏ�� �YR�5��
\ No newline at end of file
diff --git a/samples/pbe/java/des-ecb.base64 b/samples/pbe/java/des-ecb.base64
new file mode 100644
index 0000000..6f88f13
--- /dev/null
+++ b/samples/pbe/java/des-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+pxNg2EC2+QBrrWM5OKERPVnMbHzxo1RE=
diff --git a/samples/pbe/java/des-ecb.raw b/samples/pbe/java/des-ecb.raw
new file mode 100644
index 0000000..ccfe47e
--- /dev/null
+++ b/samples/pbe/java/des-ecb.raw
@@ -0,0 +1 @@
+Salted__��r���5��C�n�3�"y*]h
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede-cbc.base64 b/samples/pbe/java/des-ede-cbc.base64
new file mode 100644
index 0000000..58f7b77
--- /dev/null
+++ b/samples/pbe/java/des-ede-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/y6JQizURIjWY6ofYIXeNloyn5rmiqFTs=
diff --git a/samples/pbe/java/des-ede-cbc.raw b/samples/pbe/java/des-ede-cbc.raw
new file mode 100644
index 0000000..e410264
--- /dev/null
+++ b/samples/pbe/java/des-ede-cbc.raw
@@ -0,0 +1 @@
+Salted__ޞjcg�P��j�Cipk���eJ��
Y
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede-cfb.base64 b/samples/pbe/java/des-ede-cfb.base64
new file mode 100644
index 0000000..5fc132f
--- /dev/null
+++ b/samples/pbe/java/des-ede-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19f4EqhjsuGrFvzsLFuUFAF7Bcr4Q==
diff --git a/samples/pbe/java/des-ede-cfb.raw b/samples/pbe/java/des-ede-cfb.raw
new file mode 100644
index 0000000..2489621
Binary files /dev/null and b/samples/pbe/java/des-ede-cfb.raw differ
diff --git a/samples/pbe/java/des-ede-cfb8.base64 b/samples/pbe/java/des-ede-cfb8.base64
new file mode 100644
index 0000000..5e8deb6
--- /dev/null
+++ b/samples/pbe/java/des-ede-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/VT6B35AlNLqWnVLQ9idrEG9x1eA==
diff --git a/samples/pbe/java/des-ede-cfb8.raw b/samples/pbe/java/des-ede-cfb8.raw
new file mode 100644
index 0000000..7398675
--- /dev/null
+++ b/samples/pbe/java/des-ede-cfb8.raw
@@ -0,0 +1 @@
+Salted__.w�{�SX��{j���M(�d�
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede-ecb.base64 b/samples/pbe/java/des-ede-ecb.base64
new file mode 100644
index 0000000..0033fee
--- /dev/null
+++ b/samples/pbe/java/des-ede-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+Vfd7fjmNvFt3xWsYqPqTanguapFpJA+g=
diff --git a/samples/pbe/java/des-ede-ecb.raw b/samples/pbe/java/des-ede-ecb.raw
new file mode 100644
index 0000000..d99acfb
--- /dev/null
+++ b/samples/pbe/java/des-ede-ecb.raw
@@ -0,0 +1 @@
+Salted__��%�`�����a:�H��)
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede-ofb.base64 b/samples/pbe/java/des-ede-ofb.base64
new file mode 100644
index 0000000..50a8747
--- /dev/null
+++ b/samples/pbe/java/des-ede-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19ZQ1NUWofkQ1zmOoujP13zEGJvJw==
diff --git a/samples/pbe/java/des-ede-ofb.raw b/samples/pbe/java/des-ede-ofb.raw
new file mode 100644
index 0000000..9c7e058
--- /dev/null
+++ b/samples/pbe/java/des-ede-ofb.raw
@@ -0,0 +1 @@
+Salted__�t%�
���d��1���d���
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede.base64 b/samples/pbe/java/des-ede.base64
new file mode 100644
index 0000000..f404eaa
--- /dev/null
+++ b/samples/pbe/java/des-ede.base64
@@ -0,0 +1 @@
+U2FsdGVkX19E2uLiiey3EfQKaOsj6LBxjGMvHXxlpWY=
diff --git a/samples/pbe/java/des-ede.raw b/samples/pbe/java/des-ede.raw
new file mode 100644
index 0000000..623a797
Binary files /dev/null and b/samples/pbe/java/des-ede.raw differ
diff --git a/samples/pbe/java/des-ede3-cbc.base64 b/samples/pbe/java/des-ede3-cbc.base64
new file mode 100644
index 0000000..5dab2c3
--- /dev/null
+++ b/samples/pbe/java/des-ede3-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/O0qdSWL/hUKtdgqExwqh+KXFQet9g8BI=
diff --git a/samples/pbe/java/des-ede3-cbc.raw b/samples/pbe/java/des-ede3-cbc.raw
new file mode 100644
index 0000000..185f518
--- /dev/null
+++ b/samples/pbe/java/des-ede3-cbc.raw
@@ -0,0 +1 @@
+Salted__��q��D�Y# �
w���$ٝ�T�y
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede3-cfb.base64 b/samples/pbe/java/des-ede3-cfb.base64
new file mode 100644
index 0000000..05e05e3
--- /dev/null
+++ b/samples/pbe/java/des-ede3-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19BwdOPwBsmzE/cH0yaVKBZhS/Icg==
diff --git a/samples/pbe/java/des-ede3-cfb.raw b/samples/pbe/java/des-ede3-cfb.raw
new file mode 100644
index 0000000..0df9165
--- /dev/null
+++ b/samples/pbe/java/des-ede3-cfb.raw
@@ -0,0 +1 @@
+Salted__�61�T&{„�`ӭa
:\ No newline at end of file
diff --git a/samples/pbe/java/des-ede3-cfb8.base64 b/samples/pbe/java/des-ede3-cfb8.base64
new file mode 100644
index 0000000..f6e8818
--- /dev/null
+++ b/samples/pbe/java/des-ede3-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18dDuhVBwLJsMxfDYa/MTjTruLYQg==
diff --git a/samples/pbe/java/des-ede3-cfb8.raw b/samples/pbe/java/des-ede3-cfb8.raw
new file mode 100644
index 0000000..21e3b70
--- /dev/null
+++ b/samples/pbe/java/des-ede3-cfb8.raw
@@ -0,0 +1 @@
+Salted__��E�S�z�ԑjC�uBW��o
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede3-ecb.base64 b/samples/pbe/java/des-ede3-ecb.base64
new file mode 100644
index 0000000..7e5e36e
--- /dev/null
+++ b/samples/pbe/java/des-ede3-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+WHqIW/MnLOisXHvYhVw3lxReySmIMF+E=
diff --git a/samples/pbe/java/des-ede3-ecb.raw b/samples/pbe/java/des-ede3-ecb.raw
new file mode 100644
index 0000000..b0d3e54
--- /dev/null
+++ b/samples/pbe/java/des-ede3-ecb.raw
@@ -0,0 +1 @@
+Salted__,K���M�PN{�$+����[@&��
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede3-ofb.base64 b/samples/pbe/java/des-ede3-ofb.base64
new file mode 100644
index 0000000..1b70a4d
--- /dev/null
+++ b/samples/pbe/java/des-ede3-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19dgoM0LLrk/zilPkGQ5k1KVeUK2A==
diff --git a/samples/pbe/java/des-ede3-ofb.raw b/samples/pbe/java/des-ede3-ofb.raw
new file mode 100644
index 0000000..e1a45f0
--- /dev/null
+++ b/samples/pbe/java/des-ede3-ofb.raw
@@ -0,0 +1 @@
+Salted__�'o�$�ό{�D��U�3�
\ No newline at end of file
diff --git a/samples/pbe/java/des-ede3.base64 b/samples/pbe/java/des-ede3.base64
new file mode 100644
index 0000000..99dd748
--- /dev/null
+++ b/samples/pbe/java/des-ede3.base64
@@ -0,0 +1 @@
+U2FsdGVkX19yAldtM0VmBsI9Ytjp5QsU6Mzz6K5Cx6k=
diff --git a/samples/pbe/java/des-ede3.raw b/samples/pbe/java/des-ede3.raw
new file mode 100644
index 0000000..53f40c5
Binary files /dev/null and b/samples/pbe/java/des-ede3.raw differ
diff --git a/samples/pbe/java/des-ofb.base64 b/samples/pbe/java/des-ofb.base64
new file mode 100644
index 0000000..828218d
--- /dev/null
+++ b/samples/pbe/java/des-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+XADd70ffqUEeA1VFhMGkpmHOvUA==
diff --git a/samples/pbe/java/des-ofb.raw b/samples/pbe/java/des-ofb.raw
new file mode 100644
index 0000000..abff396
--- /dev/null
+++ b/samples/pbe/java/des-ofb.raw
@@ -0,0 +1 @@
+Salted__(<�-���e'�
"��j�i��
\ No newline at end of file
diff --git a/samples/pbe/java/des.base64 b/samples/pbe/java/des.base64
new file mode 100644
index 0000000..0e222ab
--- /dev/null
+++ b/samples/pbe/java/des.base64
@@ -0,0 +1 @@
+U2FsdGVkX18lyzI2kQJMPmBsJbfD/qTe1glRDiV+eg8=
diff --git a/samples/pbe/java/des.raw b/samples/pbe/java/des.raw
new file mode 100644
index 0000000..de71e30
--- /dev/null
+++ b/samples/pbe/java/des.raw
@@ -0,0 +1 @@
+Salted__�F��5�9tj
��>3o�M061�
\ No newline at end of file
diff --git a/samples/pbe/java/des2-cbc.base64 b/samples/pbe/java/des2-cbc.base64
new file mode 100644
index 0000000..93206dd
--- /dev/null
+++ b/samples/pbe/java/des2-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19xx1chMmdJ8eFZxjVhq1fhRhtsaysJZK8=
diff --git a/samples/pbe/java/des2-cbc.raw b/samples/pbe/java/des2-cbc.raw
new file mode 100644
index 0000000..b02ab71
--- /dev/null
+++ b/samples/pbe/java/des2-cbc.raw
@@ -0,0 +1 @@
+Salted___����S�"�{b�UD�ߜ�LA
\ No newline at end of file
diff --git a/samples/pbe/java/des2-cfb.base64 b/samples/pbe/java/des2-cfb.base64
new file mode 100644
index 0000000..8ccc633
--- /dev/null
+++ b/samples/pbe/java/des2-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19CzdoZuqHCDLC8y4aOcB27o896yA==
diff --git a/samples/pbe/java/des2-cfb.raw b/samples/pbe/java/des2-cfb.raw
new file mode 100644
index 0000000..2bf1f0f
--- /dev/null
+++ b/samples/pbe/java/des2-cfb.raw
@@ -0,0 +1 @@
+Salted__	5��&|7F8�f�L��F��
\ No newline at end of file
diff --git a/samples/pbe/java/des2-cfb8.base64 b/samples/pbe/java/des2-cfb8.base64
new file mode 100644
index 0000000..3aa1ec4
--- /dev/null
+++ b/samples/pbe/java/des2-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+1JccDxVEzyR2M1fq0siQ30vISew==
diff --git a/samples/pbe/java/des2-cfb8.raw b/samples/pbe/java/des2-cfb8.raw
new file mode 100644
index 0000000..1f8b413
--- /dev/null
+++ b/samples/pbe/java/des2-cfb8.raw
@@ -0,0 +1 @@
+Salted__0�h}C�F�O�W
=�n�
\ No newline at end of file
diff --git a/samples/pbe/java/des2-ecb.base64 b/samples/pbe/java/des2-ecb.base64
new file mode 100644
index 0000000..f7a2dfe
--- /dev/null
+++ b/samples/pbe/java/des2-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+jiXx0gK6/kNCYTrQp3coct+4/tool1DI=
diff --git a/samples/pbe/java/des2-ecb.raw b/samples/pbe/java/des2-ecb.raw
new file mode 100644
index 0000000..acfb9ad
Binary files /dev/null and b/samples/pbe/java/des2-ecb.raw differ
diff --git a/samples/pbe/java/des2-ofb.base64 b/samples/pbe/java/des2-ofb.base64
new file mode 100644
index 0000000..03ee845
--- /dev/null
+++ b/samples/pbe/java/des2-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19e9Hf5gd5q/jxs4KvuQAFaqdvqDw==
diff --git a/samples/pbe/java/des2-ofb.raw b/samples/pbe/java/des2-ofb.raw
new file mode 100644
index 0000000..23a4da2
--- /dev/null
+++ b/samples/pbe/java/des2-ofb.raw
@@ -0,0 +1 @@
+Salted__��e��Q��g���1
'�s
\ No newline at end of file
diff --git a/samples/pbe/java/des2.base64 b/samples/pbe/java/des2.base64
new file mode 100644
index 0000000..e303ade
--- /dev/null
+++ b/samples/pbe/java/des2.base64
@@ -0,0 +1 @@
+U2FsdGVkX19r7Ho+1z5PhaPFqGv1u9oS5pbEQTcSdSM=
diff --git a/samples/pbe/java/des2.raw b/samples/pbe/java/des2.raw
new file mode 100644
index 0000000..c7b83e7
--- /dev/null
+++ b/samples/pbe/java/des2.raw
@@ -0,0 +1 @@
+Salted__���0���ӶB��ʲ��I��	;
\ No newline at end of file
diff --git a/samples/pbe/java/des3-cbc.base64 b/samples/pbe/java/des3-cbc.base64
new file mode 100644
index 0000000..213899d
--- /dev/null
+++ b/samples/pbe/java/des3-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18FEUvYvCXnt3hL0NJYuxBUDTYkJs46F3I=
diff --git a/samples/pbe/java/des3-cbc.raw b/samples/pbe/java/des3-cbc.raw
new file mode 100644
index 0000000..cf578c5
--- /dev/null
+++ b/samples/pbe/java/des3-cbc.raw
@@ -0,0 +1 @@
+Salted__A+��@ZUi
s�7M�o
+�
�n
\ No newline at end of file
diff --git a/samples/pbe/java/des3-cfb.base64 b/samples/pbe/java/des3-cfb.base64
new file mode 100644
index 0000000..3ca902b
--- /dev/null
+++ b/samples/pbe/java/des3-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+uL6LyO88LVW6JSU1QggtMqXcJhA==
diff --git a/samples/pbe/java/des3-cfb.raw b/samples/pbe/java/des3-cfb.raw
new file mode 100644
index 0000000..3db917d
--- /dev/null
+++ b/samples/pbe/java/des3-cfb.raw
@@ -0,0 +1 @@
+Salted__xC�l��%�7�y[��=�@��
\ No newline at end of file
diff --git a/samples/pbe/java/des3-cfb8.base64 b/samples/pbe/java/des3-cfb8.base64
new file mode 100644
index 0000000..1706aae
--- /dev/null
+++ b/samples/pbe/java/des3-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+UVIXNkusZ2L9LJETZrgLvYQLx2Q==
diff --git a/samples/pbe/java/des3-cfb8.raw b/samples/pbe/java/des3-cfb8.raw
new file mode 100644
index 0000000..35ef3a9
--- /dev/null
+++ b/samples/pbe/java/des3-cfb8.raw
@@ -0,0 +1 @@
+Salted__5b��bA����r��;=ܨ
\ No newline at end of file
diff --git a/samples/pbe/java/des3-ecb.base64 b/samples/pbe/java/des3-ecb.base64
new file mode 100644
index 0000000..b196590
--- /dev/null
+++ b/samples/pbe/java/des3-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/AmsUU5AMZi+SKgNJLzbdL7ksOeW4C2Gs=
diff --git a/samples/pbe/java/des3-ecb.raw b/samples/pbe/java/des3-ecb.raw
new file mode 100644
index 0000000..d6a2aec
--- /dev/null
+++ b/samples/pbe/java/des3-ecb.raw
@@ -0,0 +1 @@
+Salted__���2ɱF�xi]�
����p��`�
\ No newline at end of file
diff --git a/samples/pbe/java/des3-ofb.base64 b/samples/pbe/java/des3-ofb.base64
new file mode 100644
index 0000000..ed5b9f6
--- /dev/null
+++ b/samples/pbe/java/des3-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+EdDdizgXHrefX3aa7etL0mlBz4A==
diff --git a/samples/pbe/java/des3-ofb.raw b/samples/pbe/java/des3-ofb.raw
new file mode 100644
index 0000000..863bb04
--- /dev/null
+++ b/samples/pbe/java/des3-ofb.raw
@@ -0,0 +1 @@
+Salted__���h
�Up֍"X��]
\ No newline at end of file
diff --git a/samples/pbe/java/des3.base64 b/samples/pbe/java/des3.base64
new file mode 100644
index 0000000..dd14563
--- /dev/null
+++ b/samples/pbe/java/des3.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/VhtA8kn/sl5vKUPdn26Y2HJ9GqS0yIO4=
diff --git a/samples/pbe/java/des3.raw b/samples/pbe/java/des3.raw
new file mode 100644
index 0000000..c6c0603
--- /dev/null
+++ b/samples/pbe/java/des3.raw
@@ -0,0 +1 @@
+Salted__r�*���k'�2ڼ_�yd1���O
\ No newline at end of file
diff --git a/samples/pbe/java/gost-cbc.base64 b/samples/pbe/java/gost-cbc.base64
new file mode 100644
index 0000000..99379d5
--- /dev/null
+++ b/samples/pbe/java/gost-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19CcOxqNCX3h+qaxYPx4f/RSMkfhfcg3+U=
diff --git a/samples/pbe/java/gost-cbc.raw b/samples/pbe/java/gost-cbc.raw
new file mode 100644
index 0000000..5f2ca5c
--- /dev/null
+++ b/samples/pbe/java/gost-cbc.raw
@@ -0,0 +1 @@
+Salted__X&{�ʱ@+;���p�Òs����YL
\ No newline at end of file
diff --git a/samples/pbe/java/gost-cfb.base64 b/samples/pbe/java/gost-cfb.base64
new file mode 100644
index 0000000..34568e6
--- /dev/null
+++ b/samples/pbe/java/gost-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/UW5yNAn/CqR2XRuNBN7eL0fykgw==
diff --git a/samples/pbe/java/gost-cfb.raw b/samples/pbe/java/gost-cfb.raw
new file mode 100644
index 0000000..4feda43
--- /dev/null
+++ b/samples/pbe/java/gost-cfb.raw
@@ -0,0 +1 @@
+Salted__h�u}S1��KPf.h@�!

\ No newline at end of file
diff --git a/samples/pbe/java/gost-cfb8.base64 b/samples/pbe/java/gost-cfb8.base64
new file mode 100644
index 0000000..b2cd2ad
--- /dev/null
+++ b/samples/pbe/java/gost-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18ENqZkND8kNxny3GS40O7vA+01RA==
diff --git a/samples/pbe/java/gost-cfb8.raw b/samples/pbe/java/gost-cfb8.raw
new file mode 100644
index 0000000..5d0f56a
--- /dev/null
+++ b/samples/pbe/java/gost-cfb8.raw
@@ -0,0 +1 @@
+Salted__�H�4g	(�`tcC
"��
\ No newline at end of file
diff --git a/samples/pbe/java/gost-ecb.base64 b/samples/pbe/java/gost-ecb.base64
new file mode 100644
index 0000000..c3d8b5b
--- /dev/null
+++ b/samples/pbe/java/gost-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18SHI4bsA0ISfwzG74m3pq8LYHueA4kHX8=
diff --git a/samples/pbe/java/gost-ecb.raw b/samples/pbe/java/gost-ecb.raw
new file mode 100644
index 0000000..4f52e3e
--- /dev/null
+++ b/samples/pbe/java/gost-ecb.raw
@@ -0,0 +1 @@
+Salted__<x�hwtf�]��e{��߱��
�
\ No newline at end of file
diff --git a/samples/pbe/java/gost-ofb.base64 b/samples/pbe/java/gost-ofb.base64
new file mode 100644
index 0000000..74d3d7f
--- /dev/null
+++ b/samples/pbe/java/gost-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/9caqCTHUYTMBXGcmTvpbwc1hFYQ==
diff --git a/samples/pbe/java/gost-ofb.raw b/samples/pbe/java/gost-ofb.raw
new file mode 100644
index 0000000..f302d1b
--- /dev/null
+++ b/samples/pbe/java/gost-ofb.raw
@@ -0,0 +1 @@
+Salted__�̩�Ԑ|��:������A7!�
\ No newline at end of file
diff --git a/samples/pbe/java/gost.base64 b/samples/pbe/java/gost.base64
new file mode 100644
index 0000000..7f608d4
--- /dev/null
+++ b/samples/pbe/java/gost.base64
@@ -0,0 +1 @@
+U2FsdGVkX19cp6LdmpT4Cy3MXExvnqpHAacdX1t49N8=
diff --git a/samples/pbe/java/gost.raw b/samples/pbe/java/gost.raw
new file mode 100644
index 0000000..b102fa1
--- /dev/null
+++ b/samples/pbe/java/gost.raw
@@ -0,0 +1,2 @@
+Salted__s�b	������n
����ʼ�
+��
\ No newline at end of file
diff --git a/samples/pbe/java/gost28147-cbc.base64 b/samples/pbe/java/gost28147-cbc.base64
new file mode 100644
index 0000000..a255c2b
--- /dev/null
+++ b/samples/pbe/java/gost28147-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+H27MlUg1vPsoZxpMW0YhUDsU83uBZto4=
diff --git a/samples/pbe/java/gost28147-cbc.raw b/samples/pbe/java/gost28147-cbc.raw
new file mode 100644
index 0000000..98ee138
--- /dev/null
+++ b/samples/pbe/java/gost28147-cbc.raw
@@ -0,0 +1 @@
+Salted__���.�
K�dظ��d��
���5 �
\ No newline at end of file
diff --git a/samples/pbe/java/gost28147-cfb.base64 b/samples/pbe/java/gost28147-cfb.base64
new file mode 100644
index 0000000..afb0b19
--- /dev/null
+++ b/samples/pbe/java/gost28147-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX193E/5JnaVMzKSTVGJnVoHkW//6UQ==
diff --git a/samples/pbe/java/gost28147-cfb.raw b/samples/pbe/java/gost28147-cfb.raw
new file mode 100644
index 0000000..50d10b4
--- /dev/null
+++ b/samples/pbe/java/gost28147-cfb.raw
@@ -0,0 +1 @@
+Salted__PI*�֍���N��
p����
\ No newline at end of file
diff --git a/samples/pbe/java/gost28147-cfb8.base64 b/samples/pbe/java/gost28147-cfb8.base64
new file mode 100644
index 0000000..8805e99
--- /dev/null
+++ b/samples/pbe/java/gost28147-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+z2bNQFuQbctEp67XJS/07x7y7Ug==
diff --git a/samples/pbe/java/gost28147-cfb8.raw b/samples/pbe/java/gost28147-cfb8.raw
new file mode 100644
index 0000000..3a077e2
--- /dev/null
+++ b/samples/pbe/java/gost28147-cfb8.raw
@@ -0,0 +1 @@
+Salted__W��J���yPQ��ЇQ�3��
\ No newline at end of file
diff --git a/samples/pbe/java/gost28147-ecb.base64 b/samples/pbe/java/gost28147-ecb.base64
new file mode 100644
index 0000000..d600b33
--- /dev/null
+++ b/samples/pbe/java/gost28147-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/3aDVY8d8z2yMpkDMJRMidVosy7139sZQ=
diff --git a/samples/pbe/java/gost28147-ecb.raw b/samples/pbe/java/gost28147-ecb.raw
new file mode 100644
index 0000000..95b75d5
--- /dev/null
+++ b/samples/pbe/java/gost28147-ecb.raw
@@ -0,0 +1 @@
+Salted__;����3����_	���Wf,�8�
\ No newline at end of file
diff --git a/samples/pbe/java/gost28147-ofb.base64 b/samples/pbe/java/gost28147-ofb.base64
new file mode 100644
index 0000000..0a10ee5
--- /dev/null
+++ b/samples/pbe/java/gost28147-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/SzYHi7r+5pJl69a2iG5kSddrZ7Q==
diff --git a/samples/pbe/java/gost28147-ofb.raw b/samples/pbe/java/gost28147-ofb.raw
new file mode 100644
index 0000000..31eecf6
--- /dev/null
+++ b/samples/pbe/java/gost28147-ofb.raw
@@ -0,0 +1 @@
+Salted__%����;G��
�=|`�ZS
\ No newline at end of file
diff --git a/samples/pbe/java/gost28147.base64 b/samples/pbe/java/gost28147.base64
new file mode 100644
index 0000000..fd0fbb5
--- /dev/null
+++ b/samples/pbe/java/gost28147.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+NdJZXG4amPV/2Bb1A+BwpJjIk0xIlfhc=
diff --git a/samples/pbe/java/gost28147.raw b/samples/pbe/java/gost28147.raw
new file mode 100644
index 0000000..55b3429
Binary files /dev/null and b/samples/pbe/java/gost28147.raw differ
diff --git a/samples/pbe/java/idea-cbc.base64 b/samples/pbe/java/idea-cbc.base64
new file mode 100644
index 0000000..c06ddfd
--- /dev/null
+++ b/samples/pbe/java/idea-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/OtjE6TFh2zaXkr8avX9DMGUMTVYdjgho=
diff --git a/samples/pbe/java/idea-cbc.raw b/samples/pbe/java/idea-cbc.raw
new file mode 100644
index 0000000..91c10c4
--- /dev/null
+++ b/samples/pbe/java/idea-cbc.raw
@@ -0,0 +1 @@
+Salted__�ϵ����ˤ¨����f�b��
\ No newline at end of file
diff --git a/samples/pbe/java/idea-cfb.base64 b/samples/pbe/java/idea-cfb.base64
new file mode 100644
index 0000000..504b806
--- /dev/null
+++ b/samples/pbe/java/idea-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19PDheUQ+fz6/gv42IkjuN4yxYh/A==
diff --git a/samples/pbe/java/idea-cfb.raw b/samples/pbe/java/idea-cfb.raw
new file mode 100644
index 0000000..2a3ad57
--- /dev/null
+++ b/samples/pbe/java/idea-cfb.raw
@@ -0,0 +1,2 @@
+Salted__��
+��XT
e
<��;��w~�
\ No newline at end of file
diff --git a/samples/pbe/java/idea-cfb8.base64 b/samples/pbe/java/idea-cfb8.base64
new file mode 100644
index 0000000..d0fd71a
--- /dev/null
+++ b/samples/pbe/java/idea-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18WT/xrbSMFJZRt2HoN8QG9ikk/iw==
diff --git a/samples/pbe/java/idea-cfb8.raw b/samples/pbe/java/idea-cfb8.raw
new file mode 100644
index 0000000..d4179bb
--- /dev/null
+++ b/samples/pbe/java/idea-cfb8.raw
@@ -0,0 +1 @@
+Salted__q�_�k��ÂW�djO���
\ No newline at end of file
diff --git a/samples/pbe/java/idea-ecb.base64 b/samples/pbe/java/idea-ecb.base64
new file mode 100644
index 0000000..c4d6ae2
--- /dev/null
+++ b/samples/pbe/java/idea-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/zs/wt9YPU+8vAh/1Qseii6vrmPoLMhGA=
diff --git a/samples/pbe/java/idea-ecb.raw b/samples/pbe/java/idea-ecb.raw
new file mode 100644
index 0000000..1de519d
--- /dev/null
+++ b/samples/pbe/java/idea-ecb.raw
@@ -0,0 +1,2 @@
+Salted__:���s>�l�k�hdV���
+DmQ�
\ No newline at end of file
diff --git a/samples/pbe/java/idea-ofb.base64 b/samples/pbe/java/idea-ofb.base64
new file mode 100644
index 0000000..55dd20a
--- /dev/null
+++ b/samples/pbe/java/idea-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+XANwaL1bEFrkxDddSGCleBTJQQg==
diff --git a/samples/pbe/java/idea-ofb.raw b/samples/pbe/java/idea-ofb.raw
new file mode 100644
index 0000000..f0a286c
--- /dev/null
+++ b/samples/pbe/java/idea-ofb.raw
@@ -0,0 +1 @@
+Salted__��U���b��;Co8Y
�QX
\ No newline at end of file
diff --git a/samples/pbe/java/idea.base64 b/samples/pbe/java/idea.base64
new file mode 100644
index 0000000..5fc1bb9
--- /dev/null
+++ b/samples/pbe/java/idea.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+MBtM2j7TXdcefSxcgR2yvj+OqX4pDZXk=
diff --git a/samples/pbe/java/idea.raw b/samples/pbe/java/idea.raw
new file mode 100644
index 0000000..7e71623
--- /dev/null
+++ b/samples/pbe/java/idea.raw
@@ -0,0 +1 @@
+Salted__��KI��}��<-�.ƾ���9
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-40-cbc.base64 b/samples/pbe/java/rc2-40-cbc.base64
new file mode 100644
index 0000000..31f33fa
--- /dev/null
+++ b/samples/pbe/java/rc2-40-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1890fJi9gA9RVpNI1DwMT1Vt51TkZmLyWs=
diff --git a/samples/pbe/java/rc2-40-cbc.raw b/samples/pbe/java/rc2-40-cbc.raw
new file mode 100644
index 0000000..25e5f9c
--- /dev/null
+++ b/samples/pbe/java/rc2-40-cbc.raw
@@ -0,0 +1 @@
+Salted__.	����b��y��6���[�Y9�I
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-40-cfb.base64 b/samples/pbe/java/rc2-40-cfb.base64
new file mode 100644
index 0000000..9f43934
--- /dev/null
+++ b/samples/pbe/java/rc2-40-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/9CTBQbekwaKie03cWICyZs3KtFg==
diff --git a/samples/pbe/java/rc2-40-cfb.raw b/samples/pbe/java/rc2-40-cfb.raw
new file mode 100644
index 0000000..34c84f6
--- /dev/null
+++ b/samples/pbe/java/rc2-40-cfb.raw
@@ -0,0 +1 @@
+Salted__�q�sqhT:�,@�%Ck��S
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-40-cfb8.base64 b/samples/pbe/java/rc2-40-cfb8.base64
new file mode 100644
index 0000000..dfd79ae
--- /dev/null
+++ b/samples/pbe/java/rc2-40-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19rhbzIzceTg9Ye5JJVdmxmGjzhDQ==
diff --git a/samples/pbe/java/rc2-40-cfb8.raw b/samples/pbe/java/rc2-40-cfb8.raw
new file mode 100644
index 0000000..abcd263
--- /dev/null
+++ b/samples/pbe/java/rc2-40-cfb8.raw
@@ -0,0 +1 @@
+Salted__H��H.����a���
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-40-ecb.base64 b/samples/pbe/java/rc2-40-ecb.base64
new file mode 100644
index 0000000..4bed16c
--- /dev/null
+++ b/samples/pbe/java/rc2-40-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19daAkC+zMJJplpf0zSowdMulhlBsFnUVs=
diff --git a/samples/pbe/java/rc2-40-ecb.raw b/samples/pbe/java/rc2-40-ecb.raw
new file mode 100644
index 0000000..1de429d
--- /dev/null
+++ b/samples/pbe/java/rc2-40-ecb.raw
@@ -0,0 +1 @@
+Salted__97����./����H%ˮ��A��7�
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-40-ofb.base64 b/samples/pbe/java/rc2-40-ofb.base64
new file mode 100644
index 0000000..2a2f8fb
--- /dev/null
+++ b/samples/pbe/java/rc2-40-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/19LIip0bg3xxQnKt+Kl0/34+i2A==
diff --git a/samples/pbe/java/rc2-40-ofb.raw b/samples/pbe/java/rc2-40-ofb.raw
new file mode 100644
index 0000000..a6a97aa
--- /dev/null
+++ b/samples/pbe/java/rc2-40-ofb.raw
@@ -0,0 +1 @@
+Salted__A��j�V�r���ˋ�G$��
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-40.base64 b/samples/pbe/java/rc2-40.base64
new file mode 100644
index 0000000..e9a220d
--- /dev/null
+++ b/samples/pbe/java/rc2-40.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/3SRnzRmiIg1wLwR1/h+fXX+1e/GY202U=
diff --git a/samples/pbe/java/rc2-40.raw b/samples/pbe/java/rc2-40.raw
new file mode 100644
index 0000000..9e5c6c7
--- /dev/null
+++ b/samples/pbe/java/rc2-40.raw
@@ -0,0 +1 @@
+Salted__kn��	�-�&�gLΰ�W��
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-64-cbc.base64 b/samples/pbe/java/rc2-64-cbc.base64
new file mode 100644
index 0000000..88c35c7
--- /dev/null
+++ b/samples/pbe/java/rc2-64-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19HgGgtz1lOzUsGkcd7YnWH7iB+t0TCPc4=
diff --git a/samples/pbe/java/rc2-64-cbc.raw b/samples/pbe/java/rc2-64-cbc.raw
new file mode 100644
index 0000000..ef12322
--- /dev/null
+++ b/samples/pbe/java/rc2-64-cbc.raw
@@ -0,0 +1 @@
+Salted__��)Y������L�ee
�?$���B�
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-64-cfb.base64 b/samples/pbe/java/rc2-64-cfb.base64
new file mode 100644
index 0000000..ce92402
--- /dev/null
+++ b/samples/pbe/java/rc2-64-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+jFsOQfhGb6EMTiO5PogMI/TDEVQ==
diff --git a/samples/pbe/java/rc2-64-cfb.raw b/samples/pbe/java/rc2-64-cfb.raw
new file mode 100644
index 0000000..092dbcb
--- /dev/null
+++ b/samples/pbe/java/rc2-64-cfb.raw
@@ -0,0 +1 @@
+Salted__W����$
X��]pR���
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-64-cfb8.base64 b/samples/pbe/java/rc2-64-cfb8.base64
new file mode 100644
index 0000000..9eff43f
--- /dev/null
+++ b/samples/pbe/java/rc2-64-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Vx4yMujZVjPpd9Fi1bSg/jF7Bxw==
diff --git a/samples/pbe/java/rc2-64-cfb8.raw b/samples/pbe/java/rc2-64-cfb8.raw
new file mode 100644
index 0000000..269c7cc
Binary files /dev/null and b/samples/pbe/java/rc2-64-cfb8.raw differ
diff --git a/samples/pbe/java/rc2-64-ecb.base64 b/samples/pbe/java/rc2-64-ecb.base64
new file mode 100644
index 0000000..6adf1b2
--- /dev/null
+++ b/samples/pbe/java/rc2-64-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19V5eWa4V73IGlV+5qb1zawiN+vnAiYmzY=
diff --git a/samples/pbe/java/rc2-64-ecb.raw b/samples/pbe/java/rc2-64-ecb.raw
new file mode 100644
index 0000000..936afba
--- /dev/null
+++ b/samples/pbe/java/rc2-64-ecb.raw
@@ -0,0 +1 @@
+Salted__B�.A�l����Mv:��c�X�\
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-64-ofb.base64 b/samples/pbe/java/rc2-64-ofb.base64
new file mode 100644
index 0000000..496a220
--- /dev/null
+++ b/samples/pbe/java/rc2-64-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19GOsgWvk8zkm+x4QV5m1s4fdPu5Q==
diff --git a/samples/pbe/java/rc2-64-ofb.raw b/samples/pbe/java/rc2-64-ofb.raw
new file mode 100644
index 0000000..2d0e2af
--- /dev/null
+++ b/samples/pbe/java/rc2-64-ofb.raw
@@ -0,0 +1 @@
+Salted__	LV㛖O����v1ġ6�t}
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-64.base64 b/samples/pbe/java/rc2-64.base64
new file mode 100644
index 0000000..ba7b424
--- /dev/null
+++ b/samples/pbe/java/rc2-64.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+t696swrI4UPV7oNFDYmU87F0CoP6Vb+Q=
diff --git a/samples/pbe/java/rc2-64.raw b/samples/pbe/java/rc2-64.raw
new file mode 100644
index 0000000..302cb49
--- /dev/null
+++ b/samples/pbe/java/rc2-64.raw
@@ -0,0 +1 @@
+Salted__�$�V��T����Gj0�>A�
���U
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-cbc.base64 b/samples/pbe/java/rc2-cbc.base64
new file mode 100644
index 0000000..eea5829
--- /dev/null
+++ b/samples/pbe/java/rc2-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19jUXYEywuyoP7NBdjrrZCqtJrFnXTPlaU=
diff --git a/samples/pbe/java/rc2-cbc.raw b/samples/pbe/java/rc2-cbc.raw
new file mode 100644
index 0000000..c2c1b61
Binary files /dev/null and b/samples/pbe/java/rc2-cbc.raw differ
diff --git a/samples/pbe/java/rc2-cfb.base64 b/samples/pbe/java/rc2-cfb.base64
new file mode 100644
index 0000000..6a25c21
--- /dev/null
+++ b/samples/pbe/java/rc2-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19N7VML8H7g1oM010jHxsI+4J3Eaw==
diff --git a/samples/pbe/java/rc2-cfb.raw b/samples/pbe/java/rc2-cfb.raw
new file mode 100644
index 0000000..c0cf0cd
--- /dev/null
+++ b/samples/pbe/java/rc2-cfb.raw
@@ -0,0 +1 @@
+Salted__
��9
�n�ܦ�w�L�E��
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-cfb8.base64 b/samples/pbe/java/rc2-cfb8.base64
new file mode 100644
index 0000000..4242b15
--- /dev/null
+++ b/samples/pbe/java/rc2-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Hc+EZIfLJzpgBhsT2O+8yMoQG+g==
diff --git a/samples/pbe/java/rc2-cfb8.raw b/samples/pbe/java/rc2-cfb8.raw
new file mode 100644
index 0000000..a6eeb8b
--- /dev/null
+++ b/samples/pbe/java/rc2-cfb8.raw
@@ -0,0 +1 @@
+Salted__X�z�S�ˊ���*M>H+�\
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-ecb.base64 b/samples/pbe/java/rc2-ecb.base64
new file mode 100644
index 0000000..626d757
--- /dev/null
+++ b/samples/pbe/java/rc2-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX180vh9QgndcQX7pLj7vY6mjoFKdPy4DKKU=
diff --git a/samples/pbe/java/rc2-ecb.raw b/samples/pbe/java/rc2-ecb.raw
new file mode 100644
index 0000000..1360879
--- /dev/null
+++ b/samples/pbe/java/rc2-ecb.raw
@@ -0,0 +1 @@
+Salted__!)��u���ti��7P�t�ü_�
\ No newline at end of file
diff --git a/samples/pbe/java/rc2-ofb.base64 b/samples/pbe/java/rc2-ofb.base64
new file mode 100644
index 0000000..313ae46
--- /dev/null
+++ b/samples/pbe/java/rc2-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/iYmfwemCc/BruXulvHyLEqbOOgA==
diff --git a/samples/pbe/java/rc2-ofb.raw b/samples/pbe/java/rc2-ofb.raw
new file mode 100644
index 0000000..6bd7cdb
--- /dev/null
+++ b/samples/pbe/java/rc2-ofb.raw
@@ -0,0 +1 @@
+Salted__�z�ޢ
�jV�����os��
\ No newline at end of file
diff --git a/samples/pbe/java/rc2.base64 b/samples/pbe/java/rc2.base64
new file mode 100644
index 0000000..82dd662
--- /dev/null
+++ b/samples/pbe/java/rc2.base64
@@ -0,0 +1 @@
+U2FsdGVkX19N6rCXehC+nOA5hSXpAYzwLaWrUbjVjOw=
diff --git a/samples/pbe/java/rc2.raw b/samples/pbe/java/rc2.raw
new file mode 100644
index 0000000..30ddfb1
--- /dev/null
+++ b/samples/pbe/java/rc2.raw
@@ -0,0 +1 @@
+Salted__
∎�-�����r~��g"��)�
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40-cbc.base64 b/samples/pbe/java/rc4-40-cbc.base64
new file mode 100644
index 0000000..fc22b6a
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX188GJJ5CN6i9uoi+gQ7MGXRI5hARw==
diff --git a/samples/pbe/java/rc4-40-cbc.raw b/samples/pbe/java/rc4-40-cbc.raw
new file mode 100644
index 0000000..7023417
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cbc.raw
@@ -0,0 +1 @@
+Salted__K�<�PGR�t�'�o
�=iA!
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40-cfb.base64 b/samples/pbe/java/rc4-40-cfb.base64
new file mode 100644
index 0000000..53c2751
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18odI9YC5G2YEXRbhdC4oAEZBoy8A==
diff --git a/samples/pbe/java/rc4-40-cfb.raw b/samples/pbe/java/rc4-40-cfb.raw
new file mode 100644
index 0000000..30a67c9
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cfb.raw
@@ -0,0 +1 @@
+Salted__
�$�Z�(*b"�| ����
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40-cfb1.base64 b/samples/pbe/java/rc4-40-cfb1.base64
new file mode 100644
index 0000000..a1aa595
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/CZmQzq0Vy8q9v/UuFyivWuzzy/A==
diff --git a/samples/pbe/java/rc4-40-cfb1.raw b/samples/pbe/java/rc4-40-cfb1.raw
new file mode 100644
index 0000000..89067c5
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cfb1.raw
@@ -0,0 +1 @@
+Salted__��3��!����������ʞ
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40-cfb8.base64 b/samples/pbe/java/rc4-40-cfb8.base64
new file mode 100644
index 0000000..596499d
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1941/BbLOytQil4JxUbYgHhVRVTPw==
diff --git a/samples/pbe/java/rc4-40-cfb8.raw b/samples/pbe/java/rc4-40-cfb8.raw
new file mode 100644
index 0000000..cc8ec48
--- /dev/null
+++ b/samples/pbe/java/rc4-40-cfb8.raw
@@ -0,0 +1 @@
+Salted__�
�A�;EK�9��G7{��
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40-ecb.base64 b/samples/pbe/java/rc4-40-ecb.base64
new file mode 100644
index 0000000..addd651
--- /dev/null
+++ b/samples/pbe/java/rc4-40-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/wRwxSIU9NSFlHZQri5prYSp2VBQ==
diff --git a/samples/pbe/java/rc4-40-ecb.raw b/samples/pbe/java/rc4-40-ecb.raw
new file mode 100644
index 0000000..d00c121
--- /dev/null
+++ b/samples/pbe/java/rc4-40-ecb.raw
@@ -0,0 +1 @@
+Salted__r�]�濷�S>>�3�p��#�
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40-ofb.base64 b/samples/pbe/java/rc4-40-ofb.base64
new file mode 100644
index 0000000..0d6cc65
--- /dev/null
+++ b/samples/pbe/java/rc4-40-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19CkHOXcKSEyr7u+cfZdee1OIHuzw==
diff --git a/samples/pbe/java/rc4-40-ofb.raw b/samples/pbe/java/rc4-40-ofb.raw
new file mode 100644
index 0000000..bcf956b
--- /dev/null
+++ b/samples/pbe/java/rc4-40-ofb.raw
@@ -0,0 +1 @@
+Salted__T�N�/��|�wN�9:v��`�
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-40.base64 b/samples/pbe/java/rc4-40.base64
new file mode 100644
index 0000000..12a7b89
--- /dev/null
+++ b/samples/pbe/java/rc4-40.base64
@@ -0,0 +1 @@
+U2FsdGVkX18EeGBBjdefS3HAHTqHfBG/3hCTAQ==
diff --git a/samples/pbe/java/rc4-40.raw b/samples/pbe/java/rc4-40.raw
new file mode 100644
index 0000000..a49d2fa
--- /dev/null
+++ b/samples/pbe/java/rc4-40.raw
@@ -0,0 +1 @@
+Salted__�Q��_����y)j4�^U[�W
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-cbc.base64 b/samples/pbe/java/rc4-cbc.base64
new file mode 100644
index 0000000..b57ddee
--- /dev/null
+++ b/samples/pbe/java/rc4-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19MH6/8ont1oCPgPGGrD07Uk2KFbw==
diff --git a/samples/pbe/java/rc4-cbc.raw b/samples/pbe/java/rc4-cbc.raw
new file mode 100644
index 0000000..58ad2d4
--- /dev/null
+++ b/samples/pbe/java/rc4-cbc.raw
@@ -0,0 +1 @@
+Salted__?f���U�P2eQ�E�@&�
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-cfb.base64 b/samples/pbe/java/rc4-cfb.base64
new file mode 100644
index 0000000..75b19e3
--- /dev/null
+++ b/samples/pbe/java/rc4-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+XwaTkDMWYpe00BhDb6r23ndwWcg==
diff --git a/samples/pbe/java/rc4-cfb.raw b/samples/pbe/java/rc4-cfb.raw
new file mode 100644
index 0000000..1763fa5
--- /dev/null
+++ b/samples/pbe/java/rc4-cfb.raw
@@ -0,0 +1 @@
+Salted__)TC_�̯�s|4#��|�ҭ�D
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-cfb1.base64 b/samples/pbe/java/rc4-cfb1.base64
new file mode 100644
index 0000000..3c075dc
--- /dev/null
+++ b/samples/pbe/java/rc4-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX19awuk1DmUWgwPY/aEmbOiOBEOl1A==
diff --git a/samples/pbe/java/rc4-cfb1.raw b/samples/pbe/java/rc4-cfb1.raw
new file mode 100644
index 0000000..ff8dc08
--- /dev/null
+++ b/samples/pbe/java/rc4-cfb1.raw
@@ -0,0 +1 @@
+Salted__�nh<۝�<���_����
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-cfb8.base64 b/samples/pbe/java/rc4-cfb8.base64
new file mode 100644
index 0000000..ccae1fb
--- /dev/null
+++ b/samples/pbe/java/rc4-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+5qdQ+OTXJaPidwUyxZIJ3poe4WA==
diff --git a/samples/pbe/java/rc4-cfb8.raw b/samples/pbe/java/rc4-cfb8.raw
new file mode 100644
index 0000000..d7297b4
--- /dev/null
+++ b/samples/pbe/java/rc4-cfb8.raw
@@ -0,0 +1 @@
+Salted__윰�])��-�s�
� ��|W�
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-ecb.base64 b/samples/pbe/java/rc4-ecb.base64
new file mode 100644
index 0000000..8bf1eaa
--- /dev/null
+++ b/samples/pbe/java/rc4-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1//ZrZ/vbEZ3DLSgWD+riJhXeUBmw==
diff --git a/samples/pbe/java/rc4-ecb.raw b/samples/pbe/java/rc4-ecb.raw
new file mode 100644
index 0000000..f002c75
--- /dev/null
+++ b/samples/pbe/java/rc4-ecb.raw
@@ -0,0 +1 @@
+Salted__"Q��|��`\I�E&���*w
\ No newline at end of file
diff --git a/samples/pbe/java/rc4-ofb.base64 b/samples/pbe/java/rc4-ofb.base64
new file mode 100644
index 0000000..84a89be
--- /dev/null
+++ b/samples/pbe/java/rc4-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Im3cQogwsf8Bmi3Putex1tcWQ3Q==
diff --git a/samples/pbe/java/rc4-ofb.raw b/samples/pbe/java/rc4-ofb.raw
new file mode 100644
index 0000000..3e40896
--- /dev/null
+++ b/samples/pbe/java/rc4-ofb.raw
@@ -0,0 +1 @@
+Salted__x��2S׿���#����]m��
\ No newline at end of file
diff --git a/samples/pbe/java/rc4.base64 b/samples/pbe/java/rc4.base64
new file mode 100644
index 0000000..020815e
--- /dev/null
+++ b/samples/pbe/java/rc4.base64
@@ -0,0 +1 @@
+U2FsdGVkX19dOFVejkLubJRxOAgiRXIhdtQjpg==
diff --git a/samples/pbe/java/rc4.raw b/samples/pbe/java/rc4.raw
new file mode 100644
index 0000000..3cd0f3d
Binary files /dev/null and b/samples/pbe/java/rc4.raw differ
diff --git a/samples/pbe/java/rc5-cbc.base64 b/samples/pbe/java/rc5-cbc.base64
new file mode 100644
index 0000000..efa9b01
--- /dev/null
+++ b/samples/pbe/java/rc5-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19KZE6NwDpGJggjEqCSssSdGBuqdMMS/ac=
diff --git a/samples/pbe/java/rc5-cbc.raw b/samples/pbe/java/rc5-cbc.raw
new file mode 100644
index 0000000..9ad3978
Binary files /dev/null and b/samples/pbe/java/rc5-cbc.raw differ
diff --git a/samples/pbe/java/rc5-cfb.base64 b/samples/pbe/java/rc5-cfb.base64
new file mode 100644
index 0000000..58d6a84
--- /dev/null
+++ b/samples/pbe/java/rc5-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/iYdy7fAxq6MgXfbbdhgpV0ZzMbA==
diff --git a/samples/pbe/java/rc5-cfb.raw b/samples/pbe/java/rc5-cfb.raw
new file mode 100644
index 0000000..2e140fc
--- /dev/null
+++ b/samples/pbe/java/rc5-cfb.raw
@@ -0,0 +1 @@
+Salted__-��7x�j�k�?�o��on�
\ No newline at end of file
diff --git a/samples/pbe/java/rc5-cfb8.base64 b/samples/pbe/java/rc5-cfb8.base64
new file mode 100644
index 0000000..5751c8d
--- /dev/null
+++ b/samples/pbe/java/rc5-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+QRrNDT8pf9MjdWWXbv9prbDMeLw==
diff --git a/samples/pbe/java/rc5-cfb8.raw b/samples/pbe/java/rc5-cfb8.raw
new file mode 100644
index 0000000..7e749c1
--- /dev/null
+++ b/samples/pbe/java/rc5-cfb8.raw
@@ -0,0 +1 @@
+Salted__���r��%����E��3�
\ No newline at end of file
diff --git a/samples/pbe/java/rc5-ecb.base64 b/samples/pbe/java/rc5-ecb.base64
new file mode 100644
index 0000000..37d8f49
--- /dev/null
+++ b/samples/pbe/java/rc5-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/9FfJfiaw3Io0Z0jxcNcn2z7/nwS5fW2U=
diff --git a/samples/pbe/java/rc5-ecb.raw b/samples/pbe/java/rc5-ecb.raw
new file mode 100644
index 0000000..6c71c4d
--- /dev/null
+++ b/samples/pbe/java/rc5-ecb.raw
@@ -0,0 +1 @@
+Salted__���SpH2����$��Q,E!�
�
\ No newline at end of file
diff --git a/samples/pbe/java/rc5-ofb.base64 b/samples/pbe/java/rc5-ofb.base64
new file mode 100644
index 0000000..e34064b
--- /dev/null
+++ b/samples/pbe/java/rc5-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Wu2kziJkCUV0k3gLs9ST+Khhj7A==
diff --git a/samples/pbe/java/rc5-ofb.raw b/samples/pbe/java/rc5-ofb.raw
new file mode 100644
index 0000000..5aeed79
--- /dev/null
+++ b/samples/pbe/java/rc5-ofb.raw
@@ -0,0 +1 @@
+Salted__��˿s���^"@�
���3
\ No newline at end of file
diff --git a/samples/pbe/java/rc5.base64 b/samples/pbe/java/rc5.base64
new file mode 100644
index 0000000..5be614d
--- /dev/null
+++ b/samples/pbe/java/rc5.base64
@@ -0,0 +1 @@
+U2FsdGVkX19OPlXT1mBB8+CHrhbv+wgMQQRO6W9JmNA=
diff --git a/samples/pbe/java/rc5.raw b/samples/pbe/java/rc5.raw
new file mode 100644
index 0000000..a477e0e
--- /dev/null
+++ b/samples/pbe/java/rc5.raw
@@ -0,0 +1,2 @@
+Salted__
+��1�T���9��m��;��,D:�c�
\ No newline at end of file
diff --git a/samples/pbe/java/rc6-cbc.base64 b/samples/pbe/java/rc6-cbc.base64
new file mode 100644
index 0000000..6c77177
--- /dev/null
+++ b/samples/pbe/java/rc6-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18zJfLwtPs3eGSOXxsDSLwxRwt88FMa8KQ=
diff --git a/samples/pbe/java/rc6-cbc.raw b/samples/pbe/java/rc6-cbc.raw
new file mode 100644
index 0000000..b8a9c69
--- /dev/null
+++ b/samples/pbe/java/rc6-cbc.raw
@@ -0,0 +1 @@
+Salted__~qy}ݜ�C4;��P#:�b�.
\ No newline at end of file
diff --git a/samples/pbe/java/rc6-cfb.base64 b/samples/pbe/java/rc6-cfb.base64
new file mode 100644
index 0000000..00b2115
--- /dev/null
+++ b/samples/pbe/java/rc6-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19+sI9PaxTdpflralMAgc1WiI0LxA==
diff --git a/samples/pbe/java/rc6-cfb.raw b/samples/pbe/java/rc6-cfb.raw
new file mode 100644
index 0000000..668db94
--- /dev/null
+++ b/samples/pbe/java/rc6-cfb.raw
@@ -0,0 +1 @@
+Salted__��VQ�3U2�Pr()+S菌¢
\ No newline at end of file
diff --git a/samples/pbe/java/rc6-cfb8.base64 b/samples/pbe/java/rc6-cfb8.base64
new file mode 100644
index 0000000..5967372
--- /dev/null
+++ b/samples/pbe/java/rc6-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19XSdlrGG6E+A5QqcShux77c0qGeg==
diff --git a/samples/pbe/java/rc6-cfb8.raw b/samples/pbe/java/rc6-cfb8.raw
new file mode 100644
index 0000000..8465eb0
--- /dev/null
+++ b/samples/pbe/java/rc6-cfb8.raw
@@ -0,0 +1 @@
+Salted__;>�0G�n��`w��u���
\ No newline at end of file
diff --git a/samples/pbe/java/rc6-ecb.base64 b/samples/pbe/java/rc6-ecb.base64
new file mode 100644
index 0000000..ba70f6b
--- /dev/null
+++ b/samples/pbe/java/rc6-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18hZXJjY4Ph0hTUfIl2u55YV6eJ6DTx23U=
diff --git a/samples/pbe/java/rc6-ecb.raw b/samples/pbe/java/rc6-ecb.raw
new file mode 100644
index 0000000..7ff49eb
--- /dev/null
+++ b/samples/pbe/java/rc6-ecb.raw
@@ -0,0 +1 @@
+Salted__�
�EX�ػ#�w\u7U�”\%�
\ No newline at end of file
diff --git a/samples/pbe/java/rc6-ofb.base64 b/samples/pbe/java/rc6-ofb.base64
new file mode 100644
index 0000000..5f7c88d
--- /dev/null
+++ b/samples/pbe/java/rc6-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18myTpYCRMSdywhJDrjGBHrXcT/qQ==
diff --git a/samples/pbe/java/rc6-ofb.raw b/samples/pbe/java/rc6-ofb.raw
new file mode 100644
index 0000000..a7ea4c1
--- /dev/null
+++ b/samples/pbe/java/rc6-ofb.raw
@@ -0,0 +1 @@
+Salted__�""]@�=z\��о�ʻ��
\ No newline at end of file
diff --git a/samples/pbe/java/rc6.base64 b/samples/pbe/java/rc6.base64
new file mode 100644
index 0000000..54fe771
--- /dev/null
+++ b/samples/pbe/java/rc6.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/rTycJEafQGVSXJ1+kU3PDaSyyaK7Tw1M=
diff --git a/samples/pbe/java/rc6.raw b/samples/pbe/java/rc6.raw
new file mode 100644
index 0000000..d053f09
--- /dev/null
+++ b/samples/pbe/java/rc6.raw
@@ -0,0 +1 @@
+Salted__iC��\�0?M���.�·
����
\ No newline at end of file
diff --git a/samples/pbe/java/rijndael-cbc.base64 b/samples/pbe/java/rijndael-cbc.base64
new file mode 100644
index 0000000..a85d699
--- /dev/null
+++ b/samples/pbe/java/rijndael-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+GLUqDaOBL1q65jZRVV94LQvz++bpKfrg=
diff --git a/samples/pbe/java/rijndael-cbc.raw b/samples/pbe/java/rijndael-cbc.raw
new file mode 100644
index 0000000..702ae5d
--- /dev/null
+++ b/samples/pbe/java/rijndael-cbc.raw
@@ -0,0 +1 @@
+Salted__�l��*�`=N� `
��#/��9u
\ No newline at end of file
diff --git a/samples/pbe/java/rijndael-cfb.base64 b/samples/pbe/java/rijndael-cfb.base64
new file mode 100644
index 0000000..112de2e
--- /dev/null
+++ b/samples/pbe/java/rijndael-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+w0kb82u6IyxyLvDdjN8TFhrKQnA==
diff --git a/samples/pbe/java/rijndael-cfb.raw b/samples/pbe/java/rijndael-cfb.raw
new file mode 100644
index 0000000..86a6b98
--- /dev/null
+++ b/samples/pbe/java/rijndael-cfb.raw
@@ -0,0 +1 @@
+Salted__�J��ff؃~��%Hi�;�
\ No newline at end of file
diff --git a/samples/pbe/java/rijndael-cfb8.base64 b/samples/pbe/java/rijndael-cfb8.base64
new file mode 100644
index 0000000..c24b2f8
--- /dev/null
+++ b/samples/pbe/java/rijndael-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/3OymmQVbiQVPgAZxjBlz0dH7cWQ==
diff --git a/samples/pbe/java/rijndael-cfb8.raw b/samples/pbe/java/rijndael-cfb8.raw
new file mode 100644
index 0000000..15427a6
--- /dev/null
+++ b/samples/pbe/java/rijndael-cfb8.raw
@@ -0,0 +1 @@
+Salted__
��P���@u(�s=yi
\ No newline at end of file
diff --git a/samples/pbe/java/rijndael-ecb.base64 b/samples/pbe/java/rijndael-ecb.base64
new file mode 100644
index 0000000..3ebeb0a
--- /dev/null
+++ b/samples/pbe/java/rijndael-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19AiEISrLHP341MAjkYJYdHL34x/fD3nfY=
diff --git a/samples/pbe/java/rijndael-ecb.raw b/samples/pbe/java/rijndael-ecb.raw
new file mode 100644
index 0000000..8567a88
--- /dev/null
+++ b/samples/pbe/java/rijndael-ecb.raw
@@ -0,0 +1 @@
+Salted__M��Ɇ�3�?�Uj�Է�f�i
\ No newline at end of file
diff --git a/samples/pbe/java/rijndael-ofb.base64 b/samples/pbe/java/rijndael-ofb.base64
new file mode 100644
index 0000000..8ec0178
--- /dev/null
+++ b/samples/pbe/java/rijndael-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+tQE34suS3sGO91eEI9xeZJnHbhg==
diff --git a/samples/pbe/java/rijndael-ofb.raw b/samples/pbe/java/rijndael-ofb.raw
new file mode 100644
index 0000000..2970b00
Binary files /dev/null and b/samples/pbe/java/rijndael-ofb.raw differ
diff --git a/samples/pbe/java/rijndael.base64 b/samples/pbe/java/rijndael.base64
new file mode 100644
index 0000000..60ff618
--- /dev/null
+++ b/samples/pbe/java/rijndael.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/eW6CyBkiyuzAXOEQZYQ5b5SJiCxzQz7U=
diff --git a/samples/pbe/java/rijndael.raw b/samples/pbe/java/rijndael.raw
new file mode 100644
index 0000000..7112d3c
--- /dev/null
+++ b/samples/pbe/java/rijndael.raw
@@ -0,0 +1 @@
+Salted__�T��#�㣚�������7X�e�
\ No newline at end of file
diff --git a/samples/pbe/java/seed-cbc.base64 b/samples/pbe/java/seed-cbc.base64
new file mode 100644
index 0000000..642f982
--- /dev/null
+++ b/samples/pbe/java/seed-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+Qg5j8oNBcizevw2S/9a304WcUojYHEb8=
diff --git a/samples/pbe/java/seed-cbc.raw b/samples/pbe/java/seed-cbc.raw
new file mode 100644
index 0000000..1e50ac5
--- /dev/null
+++ b/samples/pbe/java/seed-cbc.raw
@@ -0,0 +1 @@
+Salted__���񘿌�jt_�u��&�� K�
\ No newline at end of file
diff --git a/samples/pbe/java/seed-cfb.base64 b/samples/pbe/java/seed-cfb.base64
new file mode 100644
index 0000000..cf796db
--- /dev/null
+++ b/samples/pbe/java/seed-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19wAkjNdLumDxGUBRFnlpxxfBa+xw==
diff --git a/samples/pbe/java/seed-cfb.raw b/samples/pbe/java/seed-cfb.raw
new file mode 100644
index 0000000..1d9e9cd
--- /dev/null
+++ b/samples/pbe/java/seed-cfb.raw
@@ -0,0 +1 @@
+Salted__U��R.��G��I��F����
\ No newline at end of file
diff --git a/samples/pbe/java/seed-cfb8.base64 b/samples/pbe/java/seed-cfb8.base64
new file mode 100644
index 0000000..42bdb16
--- /dev/null
+++ b/samples/pbe/java/seed-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18MxdLUbBHz6J3ImvUkHx1Mi7HgeQ==
diff --git a/samples/pbe/java/seed-cfb8.raw b/samples/pbe/java/seed-cfb8.raw
new file mode 100644
index 0000000..19912d7
--- /dev/null
+++ b/samples/pbe/java/seed-cfb8.raw
@@ -0,0 +1 @@
+Salted__k��Evq�����3n��
\ No newline at end of file
diff --git a/samples/pbe/java/seed-ecb.base64 b/samples/pbe/java/seed-ecb.base64
new file mode 100644
index 0000000..9739df3
--- /dev/null
+++ b/samples/pbe/java/seed-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/o+GDLgPn9NGJaxPBdnMY6dWlgEGdICbk=
diff --git a/samples/pbe/java/seed-ecb.raw b/samples/pbe/java/seed-ecb.raw
new file mode 100644
index 0000000..9c44997
--- /dev/null
+++ b/samples/pbe/java/seed-ecb.raw
@@ -0,0 +1 @@
+Salted__kZ��E����w
�
�#?��~]�
\ No newline at end of file
diff --git a/samples/pbe/java/seed-ofb.base64 b/samples/pbe/java/seed-ofb.base64
new file mode 100644
index 0000000..8f090ec
--- /dev/null
+++ b/samples/pbe/java/seed-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+Sm91Ol7VDaRp3AkCLVd66x/Pkhw==
diff --git a/samples/pbe/java/seed-ofb.raw b/samples/pbe/java/seed-ofb.raw
new file mode 100644
index 0000000..73e4be8
Binary files /dev/null and b/samples/pbe/java/seed-ofb.raw differ
diff --git a/samples/pbe/java/seed.base64 b/samples/pbe/java/seed.base64
new file mode 100644
index 0000000..393dfd5
--- /dev/null
+++ b/samples/pbe/java/seed.base64
@@ -0,0 +1 @@
+U2FsdGVkX19j1iVitL5B8/SoJbot/q0ZoJCh/crgiaQ=
diff --git a/samples/pbe/java/seed.raw b/samples/pbe/java/seed.raw
new file mode 100644
index 0000000..4c27a0c
--- /dev/null
+++ b/samples/pbe/java/seed.raw
@@ -0,0 +1 @@
+Salted__�%�/�+G�dT�-uVL�w�'�k�
\ No newline at end of file
diff --git a/samples/pbe/java/serpent-cbc.base64 b/samples/pbe/java/serpent-cbc.base64
new file mode 100644
index 0000000..2b6cf49
--- /dev/null
+++ b/samples/pbe/java/serpent-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/Ruex6zZXcKY7UzTOEYf0rOS7jWiPN44E=
diff --git a/samples/pbe/java/serpent-cbc.raw b/samples/pbe/java/serpent-cbc.raw
new file mode 100644
index 0000000..19bd450
--- /dev/null
+++ b/samples/pbe/java/serpent-cbc.raw
@@ -0,0 +1 @@
+Salted__'���"�25�2G\ѝ5��%;`�'
\ No newline at end of file
diff --git a/samples/pbe/java/serpent-cfb.base64 b/samples/pbe/java/serpent-cfb.base64
new file mode 100644
index 0000000..26319af
--- /dev/null
+++ b/samples/pbe/java/serpent-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+XdD1519g75daA+/McW1GrmcrcsQ==
diff --git a/samples/pbe/java/serpent-cfb.raw b/samples/pbe/java/serpent-cfb.raw
new file mode 100644
index 0000000..227d506
Binary files /dev/null and b/samples/pbe/java/serpent-cfb.raw differ
diff --git a/samples/pbe/java/serpent-cfb8.base64 b/samples/pbe/java/serpent-cfb8.base64
new file mode 100644
index 0000000..e35a611
--- /dev/null
+++ b/samples/pbe/java/serpent-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX19rsyCIbjU+kC1yUp68/DYighdcZA==
diff --git a/samples/pbe/java/serpent-cfb8.raw b/samples/pbe/java/serpent-cfb8.raw
new file mode 100644
index 0000000..cfbdd0b
--- /dev/null
+++ b/samples/pbe/java/serpent-cfb8.raw
@@ -0,0 +1 @@
+Salted__�g��h��2v��髢L��
\ No newline at end of file
diff --git a/samples/pbe/java/serpent-ecb.base64 b/samples/pbe/java/serpent-ecb.base64
new file mode 100644
index 0000000..404db36
--- /dev/null
+++ b/samples/pbe/java/serpent-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1958euEvux9tp6qt8zLCDmYDyBVVSTjY88=
diff --git a/samples/pbe/java/serpent-ecb.raw b/samples/pbe/java/serpent-ecb.raw
new file mode 100644
index 0000000..ac78ceb
--- /dev/null
+++ b/samples/pbe/java/serpent-ecb.raw
@@ -0,0 +1 @@
+Salted__ņ��w��X��D]I�<a��S�x
\ No newline at end of file
diff --git a/samples/pbe/java/serpent-ofb.base64 b/samples/pbe/java/serpent-ofb.base64
new file mode 100644
index 0000000..cc9c2ae
--- /dev/null
+++ b/samples/pbe/java/serpent-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/s6i6U5jeXh15/PrVKKpyIRNbuIg==
diff --git a/samples/pbe/java/serpent-ofb.raw b/samples/pbe/java/serpent-ofb.raw
new file mode 100644
index 0000000..9c9db35
--- /dev/null
+++ b/samples/pbe/java/serpent-ofb.raw
@@ -0,0 +1 @@
+Salted__t�"���
����]�j�y��C
\ No newline at end of file
diff --git a/samples/pbe/java/serpent.base64 b/samples/pbe/java/serpent.base64
new file mode 100644
index 0000000..5a21227
--- /dev/null
+++ b/samples/pbe/java/serpent.base64
@@ -0,0 +1 @@
+U2FsdGVkX195qujaNzq14jxKvx+Lw8SHyaLJs4TQ8J0=
diff --git a/samples/pbe/java/serpent.raw b/samples/pbe/java/serpent.raw
new file mode 100644
index 0000000..7aea741
--- /dev/null
+++ b/samples/pbe/java/serpent.raw
@@ -0,0 +1,2 @@
+Salted__�:���܏7q�;
+����]cr�>
\ No newline at end of file
diff --git a/samples/pbe/java/skipjack-cbc.base64 b/samples/pbe/java/skipjack-cbc.base64
new file mode 100644
index 0000000..4adcdef
--- /dev/null
+++ b/samples/pbe/java/skipjack-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+zMjVYCvOD+ewdBROea+7dkdJFDQQwW0E=
diff --git a/samples/pbe/java/skipjack-cbc.raw b/samples/pbe/java/skipjack-cbc.raw
new file mode 100644
index 0000000..9f8a32c
--- /dev/null
+++ b/samples/pbe/java/skipjack-cbc.raw
@@ -0,0 +1 @@
+Salted__���YN�[��y!�>O�#ذ��Dw
\ No newline at end of file
diff --git a/samples/pbe/java/skipjack-cfb.base64 b/samples/pbe/java/skipjack-cfb.base64
new file mode 100644
index 0000000..45d51f7
--- /dev/null
+++ b/samples/pbe/java/skipjack-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19n4zca8LfA6iiKCnoRiQ/Okw7uww==
diff --git a/samples/pbe/java/skipjack-cfb.raw b/samples/pbe/java/skipjack-cfb.raw
new file mode 100644
index 0000000..30950e0
--- /dev/null
+++ b/samples/pbe/java/skipjack-cfb.raw
@@ -0,0 +1 @@
+Salted__fL��(���i���e�)	�
\ No newline at end of file
diff --git a/samples/pbe/java/skipjack-cfb8.base64 b/samples/pbe/java/skipjack-cfb8.base64
new file mode 100644
index 0000000..ffe939f
--- /dev/null
+++ b/samples/pbe/java/skipjack-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18dc5fJxg3eO18jgj+CCBW8bEiBBg==
diff --git a/samples/pbe/java/skipjack-cfb8.raw b/samples/pbe/java/skipjack-cfb8.raw
new file mode 100644
index 0000000..b88eb97
--- /dev/null
+++ b/samples/pbe/java/skipjack-cfb8.raw
@@ -0,0 +1 @@
+Salted__�J{�>�_���t��n7���8�
\ No newline at end of file
diff --git a/samples/pbe/java/skipjack-ecb.base64 b/samples/pbe/java/skipjack-ecb.base64
new file mode 100644
index 0000000..043f64f
--- /dev/null
+++ b/samples/pbe/java/skipjack-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Twzi0wluhUpj2mqCmsKpBAyG9NW3+9V0=
diff --git a/samples/pbe/java/skipjack-ecb.raw b/samples/pbe/java/skipjack-ecb.raw
new file mode 100644
index 0000000..d70ffe4
--- /dev/null
+++ b/samples/pbe/java/skipjack-ecb.raw
@@ -0,0 +1 @@
+Salted__��ؓCkG]�V�[n,�<���#���
\ No newline at end of file
diff --git a/samples/pbe/java/skipjack-ofb.base64 b/samples/pbe/java/skipjack-ofb.base64
new file mode 100644
index 0000000..185d89f
--- /dev/null
+++ b/samples/pbe/java/skipjack-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19+3i3BJd+8b2P4kc84XE0bvdKynw==
diff --git a/samples/pbe/java/skipjack-ofb.raw b/samples/pbe/java/skipjack-ofb.raw
new file mode 100644
index 0000000..39e4f27
--- /dev/null
+++ b/samples/pbe/java/skipjack-ofb.raw
@@ -0,0 +1 @@
+Salted__�T3�>f��O��B�IN�û
\ No newline at end of file
diff --git a/samples/pbe/java/skipjack.base64 b/samples/pbe/java/skipjack.base64
new file mode 100644
index 0000000..2ae32ac
--- /dev/null
+++ b/samples/pbe/java/skipjack.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+GkkE/WR9HWr/3hK1+f0vCb2EwMPxvNws=
diff --git a/samples/pbe/java/skipjack.raw b/samples/pbe/java/skipjack.raw
new file mode 100644
index 0000000..cf464a1
--- /dev/null
+++ b/samples/pbe/java/skipjack.raw
@@ -0,0 +1 @@
+Salted__�DC����!rɨ���\&94�-k�
\ No newline at end of file
diff --git a/samples/pbe/java/tea-cbc.base64 b/samples/pbe/java/tea-cbc.base64
new file mode 100644
index 0000000..3be186e
--- /dev/null
+++ b/samples/pbe/java/tea-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+N4jlJF5HA4CqXCaLMdgjGr4gCcWcMV6I=
diff --git a/samples/pbe/java/tea-cbc.raw b/samples/pbe/java/tea-cbc.raw
new file mode 100644
index 0000000..15879f1
--- /dev/null
+++ b/samples/pbe/java/tea-cbc.raw
@@ -0,0 +1 @@
+Salted__l�Ư�|àK�t�p�1RO����
\ No newline at end of file
diff --git a/samples/pbe/java/tea-cfb.base64 b/samples/pbe/java/tea-cfb.base64
new file mode 100644
index 0000000..b7c9f91
--- /dev/null
+++ b/samples/pbe/java/tea-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1//9v7c5qa6brx3B1IL8/k3DN9OeQ==
diff --git a/samples/pbe/java/tea-cfb.raw b/samples/pbe/java/tea-cfb.raw
new file mode 100644
index 0000000..5841c0f
Binary files /dev/null and b/samples/pbe/java/tea-cfb.raw differ
diff --git a/samples/pbe/java/tea-cfb8.base64 b/samples/pbe/java/tea-cfb8.base64
new file mode 100644
index 0000000..ac42414
--- /dev/null
+++ b/samples/pbe/java/tea-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18nOAp7ZtTx3hwVuGU7PvXkKXGp2Q==
diff --git a/samples/pbe/java/tea-cfb8.raw b/samples/pbe/java/tea-cfb8.raw
new file mode 100644
index 0000000..c2ec5a1
Binary files /dev/null and b/samples/pbe/java/tea-cfb8.raw differ
diff --git a/samples/pbe/java/tea-ecb.base64 b/samples/pbe/java/tea-ecb.base64
new file mode 100644
index 0000000..b441619
--- /dev/null
+++ b/samples/pbe/java/tea-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Nw7PSpP/e7N9eqS3VYCLU86sqN+sQs14=
diff --git a/samples/pbe/java/tea-ecb.raw b/samples/pbe/java/tea-ecb.raw
new file mode 100644
index 0000000..382ba5b
--- /dev/null
+++ b/samples/pbe/java/tea-ecb.raw
@@ -0,0 +1 @@
+Salted__����l�o���z;�#��WZ

W
\ No newline at end of file
diff --git a/samples/pbe/java/tea-ofb.base64 b/samples/pbe/java/tea-ofb.base64
new file mode 100644
index 0000000..e2d5026
--- /dev/null
+++ b/samples/pbe/java/tea-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18s9wJ3sg0L3FXWk7UwG2uqu11RgQ==
diff --git a/samples/pbe/java/tea-ofb.raw b/samples/pbe/java/tea-ofb.raw
new file mode 100644
index 0000000..f59f0e4
--- /dev/null
+++ b/samples/pbe/java/tea-ofb.raw
@@ -0,0 +1 @@
+Salted__Ϳ��z�vZ�Ƞ\��P
\ No newline at end of file
diff --git a/samples/pbe/java/tea.base64 b/samples/pbe/java/tea.base64
new file mode 100644
index 0000000..1a5a668
--- /dev/null
+++ b/samples/pbe/java/tea.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+sNDAL8YtooObpna/OX8DLzocbyvmSess=
diff --git a/samples/pbe/java/tea.raw b/samples/pbe/java/tea.raw
new file mode 100644
index 0000000..3e84eb9
--- /dev/null
+++ b/samples/pbe/java/tea.raw
@@ -0,0 +1 @@
+Salted__�[q ��7y��,�"s�`ΖUN��
\ No newline at end of file
diff --git a/samples/pbe/java/twofish-cbc.base64 b/samples/pbe/java/twofish-cbc.base64
new file mode 100644
index 0000000..c54ee99
--- /dev/null
+++ b/samples/pbe/java/twofish-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/NNaFelxgWYsIzd+iFdfvLUZ250HQHQtI=
diff --git a/samples/pbe/java/twofish-cbc.raw b/samples/pbe/java/twofish-cbc.raw
new file mode 100644
index 0000000..d52b77e
--- /dev/null
+++ b/samples/pbe/java/twofish-cbc.raw
@@ -0,0 +1,2 @@
+Salted__|e�l�����;i�
+��3�-�P
\ No newline at end of file
diff --git a/samples/pbe/java/twofish-cfb.base64 b/samples/pbe/java/twofish-cfb.base64
new file mode 100644
index 0000000..4170c55
--- /dev/null
+++ b/samples/pbe/java/twofish-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+j+QSgLHLu0GHIqdiVkVL+yobuaA==
diff --git a/samples/pbe/java/twofish-cfb.raw b/samples/pbe/java/twofish-cfb.raw
new file mode 100644
index 0000000..01ebdf9
--- /dev/null
+++ b/samples/pbe/java/twofish-cfb.raw
@@ -0,0 +1 @@
+Salted__0L/'����p���B5X�6
\ No newline at end of file
diff --git a/samples/pbe/java/twofish-cfb8.base64 b/samples/pbe/java/twofish-cfb8.base64
new file mode 100644
index 0000000..196e081
--- /dev/null
+++ b/samples/pbe/java/twofish-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/XCJv/O97fxn6yxzDAR/9H9C6THQ==
diff --git a/samples/pbe/java/twofish-cfb8.raw b/samples/pbe/java/twofish-cfb8.raw
new file mode 100644
index 0000000..9e1d1ea
Binary files /dev/null and b/samples/pbe/java/twofish-cfb8.raw differ
diff --git a/samples/pbe/java/twofish-ecb.base64 b/samples/pbe/java/twofish-ecb.base64
new file mode 100644
index 0000000..e1d44e7
--- /dev/null
+++ b/samples/pbe/java/twofish-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX195dmAFm0b+1i24kugg4ou+e+HMPufBeuk=
diff --git a/samples/pbe/java/twofish-ecb.raw b/samples/pbe/java/twofish-ecb.raw
new file mode 100644
index 0000000..3182afd
--- /dev/null
+++ b/samples/pbe/java/twofish-ecb.raw
@@ -0,0 +1 @@
+Salted__l��{��ݑl����>q��i.
\ No newline at end of file
diff --git a/samples/pbe/java/twofish-ofb.base64 b/samples/pbe/java/twofish-ofb.base64
new file mode 100644
index 0000000..cced7ad
--- /dev/null
+++ b/samples/pbe/java/twofish-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19kjJcggRCb+18SAEJhmDWvlLMW7A==
diff --git a/samples/pbe/java/twofish-ofb.raw b/samples/pbe/java/twofish-ofb.raw
new file mode 100644
index 0000000..47949d4
--- /dev/null
+++ b/samples/pbe/java/twofish-ofb.raw
@@ -0,0 +1 @@
+Salted__Ϝ
5e���p�qz at -�?��
\ No newline at end of file
diff --git a/samples/pbe/java/twofish.base64 b/samples/pbe/java/twofish.base64
new file mode 100644
index 0000000..c6241b0
--- /dev/null
+++ b/samples/pbe/java/twofish.base64
@@ -0,0 +1 @@
+U2FsdGVkX19CoOnVar7VaeII23EgP4ipAZ2XodKcQF0=
diff --git a/samples/pbe/java/twofish.raw b/samples/pbe/java/twofish.raw
new file mode 100644
index 0000000..bae695e
--- /dev/null
+++ b/samples/pbe/java/twofish.raw
@@ -0,0 +1 @@
+Salted__��\�/ޠX��RK���� 
R�=�
\ No newline at end of file
diff --git a/samples/pbe/java/xtea-cbc.base64 b/samples/pbe/java/xtea-cbc.base64
new file mode 100644
index 0000000..8ca76da
--- /dev/null
+++ b/samples/pbe/java/xtea-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/VPpaWg1t9N5RSoA8Xg0Yfg7T9nRjNIm4=
diff --git a/samples/pbe/java/xtea-cbc.raw b/samples/pbe/java/xtea-cbc.raw
new file mode 100644
index 0000000..fef76ec
--- /dev/null
+++ b/samples/pbe/java/xtea-cbc.raw
@@ -0,0 +1 @@
+Salted__b�8M�SM����n�	uZK���
\ No newline at end of file
diff --git a/samples/pbe/java/xtea-cfb.base64 b/samples/pbe/java/xtea-cfb.base64
new file mode 100644
index 0000000..7b45427
--- /dev/null
+++ b/samples/pbe/java/xtea-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+i85TvEyps5v51kOIKVH7BHrItnA==
diff --git a/samples/pbe/java/xtea-cfb.raw b/samples/pbe/java/xtea-cfb.raw
new file mode 100644
index 0000000..97a140a
--- /dev/null
+++ b/samples/pbe/java/xtea-cfb.raw
@@ -0,0 +1 @@
+Salted__x��g�W1��H�b-�1��
\ No newline at end of file
diff --git a/samples/pbe/java/xtea-cfb8.base64 b/samples/pbe/java/xtea-cfb8.base64
new file mode 100644
index 0000000..21f524e
--- /dev/null
+++ b/samples/pbe/java/xtea-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+fypkqSyuSpEfZKx80/3qRpV22Qg==
diff --git a/samples/pbe/java/xtea-cfb8.raw b/samples/pbe/java/xtea-cfb8.raw
new file mode 100644
index 0000000..0c019e2
Binary files /dev/null and b/samples/pbe/java/xtea-cfb8.raw differ
diff --git a/samples/pbe/java/xtea-ecb.base64 b/samples/pbe/java/xtea-ecb.base64
new file mode 100644
index 0000000..6267b57
--- /dev/null
+++ b/samples/pbe/java/xtea-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19jhcs+AOGFPsPKqKHpCkbqCG75AptTPo0=
diff --git a/samples/pbe/java/xtea-ecb.raw b/samples/pbe/java/xtea-ecb.raw
new file mode 100644
index 0000000..473b409
--- /dev/null
+++ b/samples/pbe/java/xtea-ecb.raw
@@ -0,0 +1 @@
+Salted__[��.�x^�XR@���S�b��
\ No newline at end of file
diff --git a/samples/pbe/java/xtea-ofb.base64 b/samples/pbe/java/xtea-ofb.base64
new file mode 100644
index 0000000..7022151
--- /dev/null
+++ b/samples/pbe/java/xtea-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18tAwVVVBYZnOl6r0cv/RuAtekpXA==
diff --git a/samples/pbe/java/xtea-ofb.raw b/samples/pbe/java/xtea-ofb.raw
new file mode 100644
index 0000000..371e663
--- /dev/null
+++ b/samples/pbe/java/xtea-ofb.raw
@@ -0,0 +1 @@
+Salted__���JC
��G�N��f��nO

\ No newline at end of file
diff --git a/samples/pbe/java/xtea.base64 b/samples/pbe/java/xtea.base64
new file mode 100644
index 0000000..69a1592
--- /dev/null
+++ b/samples/pbe/java/xtea.base64
@@ -0,0 +1 @@
+U2FsdGVkX19j1TDNjQKQw1rE1KFHZns5eBmCvWeX01I=
diff --git a/samples/pbe/java/xtea.raw b/samples/pbe/java/xtea.raw
new file mode 100644
index 0000000..990f578
--- /dev/null
+++ b/samples/pbe/java/xtea.raw
@@ -0,0 +1 @@
+Salted__ɣ��.f�
>*��Q�F�^�׾Q�
\ No newline at end of file
diff --git a/samples/pbe/openssl/README.txt b/samples/pbe/openssl/README.txt
new file mode 100644
index 0000000..7853cd5
--- /dev/null
+++ b/samples/pbe/openssl/README.txt
@@ -0,0 +1,5 @@
+Password for decrypting any of these files is
+always "changeit".
+
+These files should always decrypt to "Hello World!"
+
diff --git a/samples/pbe/openssl/aes-128-cbc.base64 b/samples/pbe/openssl/aes-128-cbc.base64
new file mode 100644
index 0000000..1632bb7
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/CR0ZIen7XtLIONFKXoUUwlU0il7SZIxg=
diff --git a/samples/pbe/openssl/aes-128-cbc.raw b/samples/pbe/openssl/aes-128-cbc.raw
new file mode 100644
index 0000000..1212ec6
Binary files /dev/null and b/samples/pbe/openssl/aes-128-cbc.raw differ
diff --git a/samples/pbe/openssl/aes-128-cfb.base64 b/samples/pbe/openssl/aes-128-cfb.base64
new file mode 100644
index 0000000..8df5dd9
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19+j8Eer0XidAqV7fHKVgbwxnDk4A==
diff --git a/samples/pbe/openssl/aes-128-cfb.raw b/samples/pbe/openssl/aes-128-cfb.raw
new file mode 100644
index 0000000..653204a
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-cfb.raw
@@ -0,0 +1 @@
+Salted__�_��U\A��UT�+�!�
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-128-cfb1.base64 b/samples/pbe/openssl/aes-128-cfb1.base64
new file mode 100644
index 0000000..4d00f4a
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+dSFH+j10CyNLwAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/aes-128-cfb1.raw b/samples/pbe/openssl/aes-128-cfb1.raw
new file mode 100644
index 0000000..484e62b
Binary files /dev/null and b/samples/pbe/openssl/aes-128-cfb1.raw differ
diff --git a/samples/pbe/openssl/aes-128-cfb8.base64 b/samples/pbe/openssl/aes-128-cfb8.base64
new file mode 100644
index 0000000..ad0474e
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/OSxAyDPgMDgjTvEekGK61k0rV+Q==
diff --git a/samples/pbe/openssl/aes-128-cfb8.raw b/samples/pbe/openssl/aes-128-cfb8.raw
new file mode 100644
index 0000000..7333a96
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-cfb8.raw
@@ -0,0 +1,2 @@
+Salted__쑶��6�Icp�
+�r}��Y
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-128-ecb.base64 b/samples/pbe/openssl/aes-128-ecb.base64
new file mode 100644
index 0000000..4dc065d
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18J3uzuGOGrPMUHrmhquo/97Ps1kOKjvfU=
diff --git a/samples/pbe/openssl/aes-128-ecb.raw b/samples/pbe/openssl/aes-128-ecb.raw
new file mode 100644
index 0000000..631a48a
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-ecb.raw
@@ -0,0 +1 @@
+Salted__�y	�؛u$�3��W�
R����h�
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-128-ofb.base64 b/samples/pbe/openssl/aes-128-ofb.base64
new file mode 100644
index 0000000..86459ac
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX181diQQs5GELPtmU73gs87cGoGFSg==
diff --git a/samples/pbe/openssl/aes-128-ofb.raw b/samples/pbe/openssl/aes-128-ofb.raw
new file mode 100644
index 0000000..ca86443
--- /dev/null
+++ b/samples/pbe/openssl/aes-128-ofb.raw
@@ -0,0 +1 @@
+Salted__�[�2��H���GC.Z���
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-192-cbc.base64 b/samples/pbe/openssl/aes-192-cbc.base64
new file mode 100644
index 0000000..44c5f3a
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/k5HwF+FgOGOXs9fCuT9hSxEDuIYSblP8=
diff --git a/samples/pbe/openssl/aes-192-cbc.raw b/samples/pbe/openssl/aes-192-cbc.raw
new file mode 100644
index 0000000..e90973f
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cbc.raw
@@ -0,0 +1 @@
+Salted__֋u5�&�GG31O�?q�Wt��͂
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-192-cfb.base64 b/samples/pbe/openssl/aes-192-cfb.base64
new file mode 100644
index 0000000..6d914f5
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/KIq1c4o4UvUpKK4s9SJz5jI11qg==
diff --git a/samples/pbe/openssl/aes-192-cfb.raw b/samples/pbe/openssl/aes-192-cfb.raw
new file mode 100644
index 0000000..347e984
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cfb.raw
@@ -0,0 +1 @@
+Salted__g�f��{�-���]�h�U	
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-192-cfb1.base64 b/samples/pbe/openssl/aes-192-cfb1.base64
new file mode 100644
index 0000000..eccff7f
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/QY2zPpdXFQu3gAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/aes-192-cfb1.raw b/samples/pbe/openssl/aes-192-cfb1.raw
new file mode 100644
index 0000000..659e076
Binary files /dev/null and b/samples/pbe/openssl/aes-192-cfb1.raw differ
diff --git a/samples/pbe/openssl/aes-192-cfb8.base64 b/samples/pbe/openssl/aes-192-cfb8.base64
new file mode 100644
index 0000000..8e04487
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18ORFdc9Vqh1g5OMXEdJTZKJ5Nrug==
diff --git a/samples/pbe/openssl/aes-192-cfb8.raw b/samples/pbe/openssl/aes-192-cfb8.raw
new file mode 100644
index 0000000..85132cc
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-cfb8.raw
@@ -0,0 +1 @@
+Salted__u֟
�ҧ�Ä������Vr
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-192-ecb.base64 b/samples/pbe/openssl/aes-192-ecb.base64
new file mode 100644
index 0000000..95e9676
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18OqCEgXpiMyN4wc4mB+S9tTMLxtkPATgM=
diff --git a/samples/pbe/openssl/aes-192-ecb.raw b/samples/pbe/openssl/aes-192-ecb.raw
new file mode 100644
index 0000000..5fb0ba4
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-ecb.raw
@@ -0,0 +1 @@
+Salted__8��ͺF�v)+QX}��8lZ�S5�
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-192-ofb.base64 b/samples/pbe/openssl/aes-192-ofb.base64
new file mode 100644
index 0000000..0916cb0
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/OuNnbiSdlHOGGT9o6tIG29p+k3g==
diff --git a/samples/pbe/openssl/aes-192-ofb.raw b/samples/pbe/openssl/aes-192-ofb.raw
new file mode 100644
index 0000000..1ac4b1b
--- /dev/null
+++ b/samples/pbe/openssl/aes-192-ofb.raw
@@ -0,0 +1 @@
+Salted__H�'܊���Rp]h��#��a
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-256-cbc.base64 b/samples/pbe/openssl/aes-256-cbc.base64
new file mode 100644
index 0000000..880daac
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/cfccZKdAm5MwO9uPkX/p2+WtVIvafIA8=
diff --git a/samples/pbe/openssl/aes-256-cbc.raw b/samples/pbe/openssl/aes-256-cbc.raw
new file mode 100644
index 0000000..e1808d4
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cbc.raw
@@ -0,0 +1 @@
+Salted__2�,<Kj+�H�:�eȠ¿$�)9)+
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-256-cfb.base64 b/samples/pbe/openssl/aes-256-cfb.base64
new file mode 100644
index 0000000..33d1dd6
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19xnj0ssEJbv5hcgr6/57WDT6+lxA==
diff --git a/samples/pbe/openssl/aes-256-cfb.raw b/samples/pbe/openssl/aes-256-cfb.raw
new file mode 100644
index 0000000..ee4f70f
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cfb.raw
@@ -0,0 +1 @@
+Salted__f�����!��
@�vs�
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-256-cfb1.base64 b/samples/pbe/openssl/aes-256-cfb1.base64
new file mode 100644
index 0000000..965ed83
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+jQxVlHdV1CqSwAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/aes-256-cfb1.raw b/samples/pbe/openssl/aes-256-cfb1.raw
new file mode 100644
index 0000000..d483aea
Binary files /dev/null and b/samples/pbe/openssl/aes-256-cfb1.raw differ
diff --git a/samples/pbe/openssl/aes-256-cfb8.base64 b/samples/pbe/openssl/aes-256-cfb8.base64
new file mode 100644
index 0000000..14b6174
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/vk1JozaSOqDGDIm8vAV6e2hL3Vw==
diff --git a/samples/pbe/openssl/aes-256-cfb8.raw b/samples/pbe/openssl/aes-256-cfb8.raw
new file mode 100644
index 0000000..814fd2e
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-cfb8.raw
@@ -0,0 +1 @@
+Salted__���e��*��	B��5�
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes-256-ecb.base64 b/samples/pbe/openssl/aes-256-ecb.base64
new file mode 100644
index 0000000..e27987d
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18EBM0NsnydQq6slUNeyknxvEGAA2QCOgY=
diff --git a/samples/pbe/openssl/aes-256-ecb.raw b/samples/pbe/openssl/aes-256-ecb.raw
new file mode 100644
index 0000000..703bc0e
Binary files /dev/null and b/samples/pbe/openssl/aes-256-ecb.raw differ
diff --git a/samples/pbe/openssl/aes-256-ofb.base64 b/samples/pbe/openssl/aes-256-ofb.base64
new file mode 100644
index 0000000..bbc278c
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+C5homVRhjJYpwt6mPV9cVW3vGZw==
diff --git a/samples/pbe/openssl/aes-256-ofb.raw b/samples/pbe/openssl/aes-256-ofb.raw
new file mode 100644
index 0000000..dc1a75b
--- /dev/null
+++ b/samples/pbe/openssl/aes-256-ofb.raw
@@ -0,0 +1 @@
+Salted__

N��<:l��/��������
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes128.base64 b/samples/pbe/openssl/aes128.base64
new file mode 100644
index 0000000..f79f113
--- /dev/null
+++ b/samples/pbe/openssl/aes128.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/5U/WWiPGrmTZRWZPyDHOMKMN5Je/kKbI=
diff --git a/samples/pbe/openssl/aes128.raw b/samples/pbe/openssl/aes128.raw
new file mode 100644
index 0000000..13c9415
Binary files /dev/null and b/samples/pbe/openssl/aes128.raw differ
diff --git a/samples/pbe/openssl/aes192.base64 b/samples/pbe/openssl/aes192.base64
new file mode 100644
index 0000000..ae9b529
--- /dev/null
+++ b/samples/pbe/openssl/aes192.base64
@@ -0,0 +1 @@
+U2FsdGVkX192xm+Zu1nX/gx0WarzSZhjXXNYkkC46Mw=
diff --git a/samples/pbe/openssl/aes192.raw b/samples/pbe/openssl/aes192.raw
new file mode 100644
index 0000000..0f9234e
--- /dev/null
+++ b/samples/pbe/openssl/aes192.raw
@@ -0,0 +1,3 @@
+Salted__��V�Eq
+����
+'�Kyy�
\ No newline at end of file
diff --git a/samples/pbe/openssl/aes256.base64 b/samples/pbe/openssl/aes256.base64
new file mode 100644
index 0000000..94b9d5f
--- /dev/null
+++ b/samples/pbe/openssl/aes256.base64
@@ -0,0 +1 @@
+U2FsdGVkX19ZErtOI0xWaZpeebrblB6HNZSVB4QwbvU=
diff --git a/samples/pbe/openssl/aes256.raw b/samples/pbe/openssl/aes256.raw
new file mode 100644
index 0000000..8c95e24
Binary files /dev/null and b/samples/pbe/openssl/aes256.raw differ
diff --git a/samples/pbe/openssl/bf-cbc.base64 b/samples/pbe/openssl/bf-cbc.base64
new file mode 100644
index 0000000..a315959
--- /dev/null
+++ b/samples/pbe/openssl/bf-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18BCvjqlyAGSuP+yp4jdcjowm3aEV95ypM=
diff --git a/samples/pbe/openssl/bf-cbc.raw b/samples/pbe/openssl/bf-cbc.raw
new file mode 100644
index 0000000..64011a8
--- /dev/null
+++ b/samples/pbe/openssl/bf-cbc.raw
@@ -0,0 +1 @@
+Salted__
���a߃\�bec��,kH;%X=�
\ No newline at end of file
diff --git a/samples/pbe/openssl/bf-cfb.base64 b/samples/pbe/openssl/bf-cfb.base64
new file mode 100644
index 0000000..735d13b
--- /dev/null
+++ b/samples/pbe/openssl/bf-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+34fmh8JsQX+N3TaSXOnZ2wCmDRQ==
diff --git a/samples/pbe/openssl/bf-cfb.raw b/samples/pbe/openssl/bf-cfb.raw
new file mode 100644
index 0000000..53be327
Binary files /dev/null and b/samples/pbe/openssl/bf-cfb.raw differ
diff --git a/samples/pbe/openssl/bf-ecb.base64 b/samples/pbe/openssl/bf-ecb.base64
new file mode 100644
index 0000000..228042c
--- /dev/null
+++ b/samples/pbe/openssl/bf-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19JnXUueE7stEFnIl75kA0KiJf8PoXw8t8=
diff --git a/samples/pbe/openssl/bf-ecb.raw b/samples/pbe/openssl/bf-ecb.raw
new file mode 100644
index 0000000..57477bd
--- /dev/null
+++ b/samples/pbe/openssl/bf-ecb.raw
@@ -0,0 +1 @@
+Salted__�����3�w7={���@�����<
\ No newline at end of file
diff --git a/samples/pbe/openssl/bf-ofb.base64 b/samples/pbe/openssl/bf-ofb.base64
new file mode 100644
index 0000000..65220e5
--- /dev/null
+++ b/samples/pbe/openssl/bf-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/qY/rlPjfOD14R0xNPzgRWMfw07A==
diff --git a/samples/pbe/openssl/bf-ofb.raw b/samples/pbe/openssl/bf-ofb.raw
new file mode 100644
index 0000000..69fde74
--- /dev/null
+++ b/samples/pbe/openssl/bf-ofb.raw
@@ -0,0 +1 @@
+Salted__�0�-�M�����0*��(�
\ No newline at end of file
diff --git a/samples/pbe/openssl/bf.base64 b/samples/pbe/openssl/bf.base64
new file mode 100644
index 0000000..01788ae
--- /dev/null
+++ b/samples/pbe/openssl/bf.base64
@@ -0,0 +1 @@
+U2FsdGVkX18qjls17bp4yNuuyQ74RlpoY6QqRT9QAkk=
diff --git a/samples/pbe/openssl/bf.raw b/samples/pbe/openssl/bf.raw
new file mode 100644
index 0000000..51edd1a
--- /dev/null
+++ b/samples/pbe/openssl/bf.raw
@@ -0,0 +1 @@
+Salted__��c�����K�������HF
\ No newline at end of file
diff --git a/samples/pbe/openssl/blowfish.base64 b/samples/pbe/openssl/blowfish.base64
new file mode 100644
index 0000000..88fe735
--- /dev/null
+++ b/samples/pbe/openssl/blowfish.base64
@@ -0,0 +1 @@
+U2FsdGVkX18DFToo8Zb5k2/Q6hl6N7OwZotaTEWTrBw=
diff --git a/samples/pbe/openssl/blowfish.raw b/samples/pbe/openssl/blowfish.raw
new file mode 100644
index 0000000..c34fa5f
--- /dev/null
+++ b/samples/pbe/openssl/blowfish.raw
@@ -0,0 +1 @@
+Salted__�w�b{
�R��(~��� 6I:�iW
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-128-cbc.base64 b/samples/pbe/openssl/camellia-128-cbc.base64
new file mode 100644
index 0000000..1b54479
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX191lwXrmRQxE0TrCNbeupylcJZ8VtJv2/M=
diff --git a/samples/pbe/openssl/camellia-128-cbc.raw b/samples/pbe/openssl/camellia-128-cbc.raw
new file mode 100644
index 0000000..6c374a6
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cbc.raw
@@ -0,0 +1 @@
+Salted__�V�

�T"��O�VI�y:k=�
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-128-cfb.base64 b/samples/pbe/openssl/camellia-128-cfb.base64
new file mode 100644
index 0000000..9df07c4
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19L18gNUQSx/Y+VPZuAf+Ey6dVHIw==
diff --git a/samples/pbe/openssl/camellia-128-cfb.raw b/samples/pbe/openssl/camellia-128-cfb.raw
new file mode 100644
index 0000000..c534d38
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cfb.raw
@@ -0,0 +1 @@
+Salted__ː��4x�`��U��
��:
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-128-cfb1.base64 b/samples/pbe/openssl/camellia-128-cfb1.base64
new file mode 100644
index 0000000..8b42799
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Ye+SfFNdm7U5wAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/camellia-128-cfb1.raw b/samples/pbe/openssl/camellia-128-cfb1.raw
new file mode 100644
index 0000000..492135f
Binary files /dev/null and b/samples/pbe/openssl/camellia-128-cfb1.raw differ
diff --git a/samples/pbe/openssl/camellia-128-cfb8.base64 b/samples/pbe/openssl/camellia-128-cfb8.base64
new file mode 100644
index 0000000..6b4b38b
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/ou3Wg0Obl2o0/fa+WwNAF+tyS0w==
diff --git a/samples/pbe/openssl/camellia-128-cfb8.raw b/samples/pbe/openssl/camellia-128-cfb8.raw
new file mode 100644
index 0000000..4d83619
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-cfb8.raw
@@ -0,0 +1 @@
+Salted__��s��
�f�q���
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-128-ecb.base64 b/samples/pbe/openssl/camellia-128-ecb.base64
new file mode 100644
index 0000000..597a7cd
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18AQ2nB+n58DNaX4mwTdbokFdol6VP2Sig=
diff --git a/samples/pbe/openssl/camellia-128-ecb.raw b/samples/pbe/openssl/camellia-128-ecb.raw
new file mode 100644
index 0000000..968b5c3
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-ecb.raw
@@ -0,0 +1 @@
+Salted__+'ș*Z�0�j�ooL��湱 l
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-128-ofb.base64 b/samples/pbe/openssl/camellia-128-ofb.base64
new file mode 100644
index 0000000..e1c76d2
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/mQuHRAAq74ZdRlcfcZTTx17sySg==
diff --git a/samples/pbe/openssl/camellia-128-ofb.raw b/samples/pbe/openssl/camellia-128-ofb.raw
new file mode 100644
index 0000000..594b5a5
--- /dev/null
+++ b/samples/pbe/openssl/camellia-128-ofb.raw
@@ -0,0 +1 @@
+Salted__&r)������M�߾x؂�01
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-192-cbc.base64 b/samples/pbe/openssl/camellia-192-cbc.base64
new file mode 100644
index 0000000..202059b
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+hcRQ4/yt8SNxOpXHyALH3sLeBJJ3dmd4=
diff --git a/samples/pbe/openssl/camellia-192-cbc.raw b/samples/pbe/openssl/camellia-192-cbc.raw
new file mode 100644
index 0000000..a7bc8ca
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cbc.raw
@@ -0,0 +1 @@
+Salted__?)�Uտ�S���
"uTD�S۟��
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-192-cfb.base64 b/samples/pbe/openssl/camellia-192-cfb.base64
new file mode 100644
index 0000000..f6f63e6
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19M//cM++R922+a3AvqtTYN3sD+TA==
diff --git a/samples/pbe/openssl/camellia-192-cfb.raw b/samples/pbe/openssl/camellia-192-cfb.raw
new file mode 100644
index 0000000..6bf189d
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cfb.raw
@@ -0,0 +1 @@
+Salted__ê^9��^�q�Y
̹]Xع
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-192-cfb1.base64 b/samples/pbe/openssl/camellia-192-cfb1.base64
new file mode 100644
index 0000000..9769a5e
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/hZdJojga9mvBAAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/camellia-192-cfb1.raw b/samples/pbe/openssl/camellia-192-cfb1.raw
new file mode 100644
index 0000000..5cfb273
Binary files /dev/null and b/samples/pbe/openssl/camellia-192-cfb1.raw differ
diff --git a/samples/pbe/openssl/camellia-192-cfb8.base64 b/samples/pbe/openssl/camellia-192-cfb8.base64
new file mode 100644
index 0000000..f4791ee
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+mqlN2aCBpyLgeXRQtqNX90++Jvw==
diff --git a/samples/pbe/openssl/camellia-192-cfb8.raw b/samples/pbe/openssl/camellia-192-cfb8.raw
new file mode 100644
index 0000000..7f9e80e
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-cfb8.raw
@@ -0,0 +1 @@
+Salted__4���x��/*���+���,
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-192-ecb.base64 b/samples/pbe/openssl/camellia-192-ecb.base64
new file mode 100644
index 0000000..be235fb
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/1ByOMlVpW5gJ+hUEuYBQCf3p21m5hvHw=
diff --git a/samples/pbe/openssl/camellia-192-ecb.raw b/samples/pbe/openssl/camellia-192-ecb.raw
new file mode 100644
index 0000000..6e723d2
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-ecb.raw
@@ -0,0 +1 @@
+Salted__E�m"k�ؽy��!i�2Df�K
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-192-ofb.base64 b/samples/pbe/openssl/camellia-192-ofb.base64
new file mode 100644
index 0000000..87999b7
--- /dev/null
+++ b/samples/pbe/openssl/camellia-192-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19fDggOe33p5O85aMJg4Ic9Q86QEg==
diff --git a/samples/pbe/openssl/camellia-192-ofb.raw b/samples/pbe/openssl/camellia-192-ofb.raw
new file mode 100644
index 0000000..594b9f8
Binary files /dev/null and b/samples/pbe/openssl/camellia-192-ofb.raw differ
diff --git a/samples/pbe/openssl/camellia-256-cbc.base64 b/samples/pbe/openssl/camellia-256-cbc.base64
new file mode 100644
index 0000000..ed2f582
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+xIS0t1hNR/OB6/3SpUooUlyjAKlwsumY=
diff --git a/samples/pbe/openssl/camellia-256-cbc.raw b/samples/pbe/openssl/camellia-256-cbc.raw
new file mode 100644
index 0000000..c024af7
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cbc.raw
@@ -0,0 +1 @@
+Salted__�؝b�Q�ǔ�R�W���o
�'�t�W
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-256-cfb.base64 b/samples/pbe/openssl/camellia-256-cfb.base64
new file mode 100644
index 0000000..5b68815
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19iJ77g6jgSSAAP5e/bIe7O6Iq/Sg==
diff --git a/samples/pbe/openssl/camellia-256-cfb.raw b/samples/pbe/openssl/camellia-256-cfb.raw
new file mode 100644
index 0000000..3d15c99
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cfb.raw
@@ -0,0 +1,2 @@
+Salted__���y�_H�d��
+�Rn�
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-256-cfb1.base64 b/samples/pbe/openssl/camellia-256-cfb1.base64
new file mode 100644
index 0000000..e515ceb
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Vi0yGB2BogY+AAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/camellia-256-cfb1.raw b/samples/pbe/openssl/camellia-256-cfb1.raw
new file mode 100644
index 0000000..48ad2b7
Binary files /dev/null and b/samples/pbe/openssl/camellia-256-cfb1.raw differ
diff --git a/samples/pbe/openssl/camellia-256-cfb8.base64 b/samples/pbe/openssl/camellia-256-cfb8.base64
new file mode 100644
index 0000000..08a553e
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX191muRJTezui22cEiJu1qyPJ2FSHw==
diff --git a/samples/pbe/openssl/camellia-256-cfb8.raw b/samples/pbe/openssl/camellia-256-cfb8.raw
new file mode 100644
index 0000000..205ba19
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-cfb8.raw
@@ -0,0 +1 @@
+Salted__94��:�آ����m���^
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-256-ecb.base64 b/samples/pbe/openssl/camellia-256-ecb.base64
new file mode 100644
index 0000000..254449c
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX199maVIVUYl/KMF5PrquhZxKT0JzrtYhAE=
diff --git a/samples/pbe/openssl/camellia-256-ecb.raw b/samples/pbe/openssl/camellia-256-ecb.raw
new file mode 100644
index 0000000..007f44b
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-ecb.raw
@@ -0,0 +1 @@
+Salted__����H�}��H
�Q�<�?��H:��
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia-256-ofb.base64 b/samples/pbe/openssl/camellia-256-ofb.base64
new file mode 100644
index 0000000..dc89309
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18Bp7PrPYIPJ8C6M/MHVO9p6tdNsw==
diff --git a/samples/pbe/openssl/camellia-256-ofb.raw b/samples/pbe/openssl/camellia-256-ofb.raw
new file mode 100644
index 0000000..d9b84d7
--- /dev/null
+++ b/samples/pbe/openssl/camellia-256-ofb.raw
@@ -0,0 +1 @@
+Salted__Plc fe �dۄ��1�
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia128.base64 b/samples/pbe/openssl/camellia128.base64
new file mode 100644
index 0000000..19e6457
--- /dev/null
+++ b/samples/pbe/openssl/camellia128.base64
@@ -0,0 +1 @@
+U2FsdGVkX197osioYPDn0yIAybXX/iMReMRmK2x+LxU=
diff --git a/samples/pbe/openssl/camellia128.raw b/samples/pbe/openssl/camellia128.raw
new file mode 100644
index 0000000..a2f64eb
--- /dev/null
+++ b/samples/pbe/openssl/camellia128.raw
@@ -0,0 +1 @@
+Salted__|з-ڽâ��&�Ծ�ڒ
��
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia192.base64 b/samples/pbe/openssl/camellia192.base64
new file mode 100644
index 0000000..dfd0702
--- /dev/null
+++ b/samples/pbe/openssl/camellia192.base64
@@ -0,0 +1 @@
+U2FsdGVkX19kg7hmBLX4JWKGyLehExxM3FGoZ4XAfU0=
diff --git a/samples/pbe/openssl/camellia192.raw b/samples/pbe/openssl/camellia192.raw
new file mode 100644
index 0000000..5741fe7
--- /dev/null
+++ b/samples/pbe/openssl/camellia192.raw
@@ -0,0 +1 @@
+Salted__�̝q����V�.�$a�/��/[|
\ No newline at end of file
diff --git a/samples/pbe/openssl/camellia256.base64 b/samples/pbe/openssl/camellia256.base64
new file mode 100644
index 0000000..91136bd
--- /dev/null
+++ b/samples/pbe/openssl/camellia256.base64
@@ -0,0 +1 @@
+U2FsdGVkX18ehKu2fdaQXkfnCZH9lwMev/u+fenDBxI=
diff --git a/samples/pbe/openssl/camellia256.raw b/samples/pbe/openssl/camellia256.raw
new file mode 100644
index 0000000..fca569e
Binary files /dev/null and b/samples/pbe/openssl/camellia256.raw differ
diff --git a/samples/pbe/openssl/cast-cbc.base64 b/samples/pbe/openssl/cast-cbc.base64
new file mode 100644
index 0000000..aee53d5
--- /dev/null
+++ b/samples/pbe/openssl/cast-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/fJ/tvKiV81WYcgGVM1Frl2fiI5VLK4Es=
diff --git a/samples/pbe/openssl/cast-cbc.raw b/samples/pbe/openssl/cast-cbc.raw
new file mode 100644
index 0000000..b8a2de3
Binary files /dev/null and b/samples/pbe/openssl/cast-cbc.raw differ
diff --git a/samples/pbe/openssl/cast.base64 b/samples/pbe/openssl/cast.base64
new file mode 100644
index 0000000..8cce378
--- /dev/null
+++ b/samples/pbe/openssl/cast.base64
@@ -0,0 +1 @@
+U2FsdGVkX18qMeuo5SMoJooS+Pt8lZGrLFnBTyll78U=
diff --git a/samples/pbe/openssl/cast.raw b/samples/pbe/openssl/cast.raw
new file mode 100644
index 0000000..ced1e03
--- /dev/null
+++ b/samples/pbe/openssl/cast.raw
@@ -0,0 +1 @@
+Salted__{A����a83��Ȱ���z�I̕
�
\ No newline at end of file
diff --git a/samples/pbe/openssl/cast5-cbc.base64 b/samples/pbe/openssl/cast5-cbc.base64
new file mode 100644
index 0000000..44a28a7
--- /dev/null
+++ b/samples/pbe/openssl/cast5-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+kjmfi9mnlAwiucUKi8XXfh3Z117F3uAY=
diff --git a/samples/pbe/openssl/cast5-cbc.raw b/samples/pbe/openssl/cast5-cbc.raw
new file mode 100644
index 0000000..f7243b3
--- /dev/null
+++ b/samples/pbe/openssl/cast5-cbc.raw
@@ -0,0 +1,2 @@
+Salted__���"�U
+�U(��&��4�zd�%
\ No newline at end of file
diff --git a/samples/pbe/openssl/cast5-cfb.base64 b/samples/pbe/openssl/cast5-cfb.base64
new file mode 100644
index 0000000..ccc5bca
--- /dev/null
+++ b/samples/pbe/openssl/cast5-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+TNbM051700oXXbN9XQ8JaH5vu8Q==
diff --git a/samples/pbe/openssl/cast5-cfb.raw b/samples/pbe/openssl/cast5-cfb.raw
new file mode 100644
index 0000000..3cb7503
--- /dev/null
+++ b/samples/pbe/openssl/cast5-cfb.raw
@@ -0,0 +1 @@
+Salted__�~��}]�ٕ668�-�gy��
\ No newline at end of file
diff --git a/samples/pbe/openssl/cast5-ecb.base64 b/samples/pbe/openssl/cast5-ecb.base64
new file mode 100644
index 0000000..248caff
--- /dev/null
+++ b/samples/pbe/openssl/cast5-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/SSY+Kvv1K5sXb+F8webiiprWDK4eVnNQ=
diff --git a/samples/pbe/openssl/cast5-ecb.raw b/samples/pbe/openssl/cast5-ecb.raw
new file mode 100644
index 0000000..af6aee5
--- /dev/null
+++ b/samples/pbe/openssl/cast5-ecb.raw
@@ -0,0 +1 @@
+Salted__�*��%�����D
_,�t�0��*
\ No newline at end of file
diff --git a/samples/pbe/openssl/cast5-ofb.base64 b/samples/pbe/openssl/cast5-ofb.base64
new file mode 100644
index 0000000..1fe008a
--- /dev/null
+++ b/samples/pbe/openssl/cast5-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1800C0YbS7y8aO10eGQB5pMPkxpHA==
diff --git a/samples/pbe/openssl/cast5-ofb.raw b/samples/pbe/openssl/cast5-ofb.raw
new file mode 100644
index 0000000..f42345c
--- /dev/null
+++ b/samples/pbe/openssl/cast5-ofb.raw
@@ -0,0 +1,2 @@
+Salted__���~K���
+�!G6uuY�
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-cbc.base64 b/samples/pbe/openssl/des-cbc.base64
new file mode 100644
index 0000000..264b65a
--- /dev/null
+++ b/samples/pbe/openssl/des-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19tMkO5uwIwhT233JWfPEA34ZbDTyeg+x8=
diff --git a/samples/pbe/openssl/des-cbc.raw b/samples/pbe/openssl/des-cbc.raw
new file mode 100644
index 0000000..84888b5
--- /dev/null
+++ b/samples/pbe/openssl/des-cbc.raw
@@ -0,0 +1 @@
+Salted__4�YjU8�d�7׃k�jâLr(
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-cfb.base64 b/samples/pbe/openssl/des-cfb.base64
new file mode 100644
index 0000000..1941567
--- /dev/null
+++ b/samples/pbe/openssl/des-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+bar1f5XcN2jRf4uGp1tVS75anLw==
diff --git a/samples/pbe/openssl/des-cfb.raw b/samples/pbe/openssl/des-cfb.raw
new file mode 100644
index 0000000..2c8eb57
--- /dev/null
+++ b/samples/pbe/openssl/des-cfb.raw
@@ -0,0 +1 @@
+Salted__�N��m��b��U+"��.
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-cfb1.base64 b/samples/pbe/openssl/des-cfb1.base64
new file mode 100644
index 0000000..3df3081
--- /dev/null
+++ b/samples/pbe/openssl/des-cfb1.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+q/8Tq539aM3mwAAAAAAAAAAAAAA==
diff --git a/samples/pbe/openssl/des-cfb1.raw b/samples/pbe/openssl/des-cfb1.raw
new file mode 100644
index 0000000..fa6ce59
Binary files /dev/null and b/samples/pbe/openssl/des-cfb1.raw differ
diff --git a/samples/pbe/openssl/des-cfb8.base64 b/samples/pbe/openssl/des-cfb8.base64
new file mode 100644
index 0000000..5e1c3e5
--- /dev/null
+++ b/samples/pbe/openssl/des-cfb8.base64
@@ -0,0 +1 @@
+U2FsdGVkX18j8MF73qCoRMNpfhNZvVM1fu4r8w==
diff --git a/samples/pbe/openssl/des-cfb8.raw b/samples/pbe/openssl/des-cfb8.raw
new file mode 100644
index 0000000..b2962ba
--- /dev/null
+++ b/samples/pbe/openssl/des-cfb8.raw
@@ -0,0 +1 @@
+Salted__'����X>�~G�P�]C��
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ecb.base64 b/samples/pbe/openssl/des-ecb.base64
new file mode 100644
index 0000000..e733bd4
--- /dev/null
+++ b/samples/pbe/openssl/des-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Wcc1l+wXUlVCAWcfwjT84SxciiCAE/2Y=
diff --git a/samples/pbe/openssl/des-ecb.raw b/samples/pbe/openssl/des-ecb.raw
new file mode 100644
index 0000000..0ddd6e9
Binary files /dev/null and b/samples/pbe/openssl/des-ecb.raw differ
diff --git a/samples/pbe/openssl/des-ede-cbc.base64 b/samples/pbe/openssl/des-ede-cbc.base64
new file mode 100644
index 0000000..6870ed5
--- /dev/null
+++ b/samples/pbe/openssl/des-ede-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19CwfOjnni1RYXijIQlic2fCBGhM0Ym2Lk=
diff --git a/samples/pbe/openssl/des-ede-cbc.raw b/samples/pbe/openssl/des-ede-cbc.raw
new file mode 100644
index 0000000..a06630e
--- /dev/null
+++ b/samples/pbe/openssl/des-ede-cbc.raw
@@ -0,0 +1 @@
+Salted__bMqD�nI�hK)cs�9��j���u
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede-cfb.base64 b/samples/pbe/openssl/des-ede-cfb.base64
new file mode 100644
index 0000000..5eec8f9
--- /dev/null
+++ b/samples/pbe/openssl/des-ede-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18PsrrurG1uhCD2QkpLZYUeEtH1Vw==
diff --git a/samples/pbe/openssl/des-ede-cfb.raw b/samples/pbe/openssl/des-ede-cfb.raw
new file mode 100644
index 0000000..6580777
--- /dev/null
+++ b/samples/pbe/openssl/des-ede-cfb.raw
@@ -0,0 +1 @@
+Salted__��.���A�YX�hcłV���
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede-ofb.base64 b/samples/pbe/openssl/des-ede-ofb.base64
new file mode 100644
index 0000000..39bb1fa
--- /dev/null
+++ b/samples/pbe/openssl/des-ede-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/rhq/q4yJ1ffD6Ghc69IWn4GsqcA==
diff --git a/samples/pbe/openssl/des-ede-ofb.raw b/samples/pbe/openssl/des-ede-ofb.raw
new file mode 100644
index 0000000..81a7523
--- /dev/null
+++ b/samples/pbe/openssl/des-ede-ofb.raw
@@ -0,0 +1 @@
+Salted__��4HV6��y%VY���{KL

\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede.base64 b/samples/pbe/openssl/des-ede.base64
new file mode 100644
index 0000000..ac9c3be
--- /dev/null
+++ b/samples/pbe/openssl/des-ede.base64
@@ -0,0 +1 @@
+U2FsdGVkX18r2UMwx1RbibeBdeNvjm9YOszrJZoXRIE=
diff --git a/samples/pbe/openssl/des-ede.raw b/samples/pbe/openssl/des-ede.raw
new file mode 100644
index 0000000..b1f7dd4
--- /dev/null
+++ b/samples/pbe/openssl/des-ede.raw
@@ -0,0 +1 @@
+Salted__��<p?M��ĝ��`ǽ gTx���
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede3-cbc.base64 b/samples/pbe/openssl/des-ede3-cbc.base64
new file mode 100644
index 0000000..de2152d
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18jj2kcvpaYme9ZFVUXQeeMX7OM15bPVbI=
diff --git a/samples/pbe/openssl/des-ede3-cbc.raw b/samples/pbe/openssl/des-ede3-cbc.raw
new file mode 100644
index 0000000..956423f
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3-cbc.raw
@@ -0,0 +1,2 @@
+Salted__/��Y/�����FQ�p$o�
+¨
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede3-cfb.base64 b/samples/pbe/openssl/des-ede3-cfb.base64
new file mode 100644
index 0000000..bc44959
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19I7oHyglbIqCQDbHBukOaaRPjauw==
diff --git a/samples/pbe/openssl/des-ede3-cfb.raw b/samples/pbe/openssl/des-ede3-cfb.raw
new file mode 100644
index 0000000..9a616ff
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3-cfb.raw
@@ -0,0 +1 @@
+Salted__a'�
7MY�z|N/�с�
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede3-ofb.base64 b/samples/pbe/openssl/des-ede3-ofb.base64
new file mode 100644
index 0000000..cb1f162
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19O+uqDgSn48JKfd1ZmT/EW9DSfWQ==
diff --git a/samples/pbe/openssl/des-ede3-ofb.raw b/samples/pbe/openssl/des-ede3-ofb.raw
new file mode 100644
index 0000000..2aaee9e
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3-ofb.raw
@@ -0,0 +1 @@
+Salted__KjTO�7�t��
��_��

\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ede3.base64 b/samples/pbe/openssl/des-ede3.base64
new file mode 100644
index 0000000..3ad36d8
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3.base64
@@ -0,0 +1 @@
+U2FsdGVkX193v6U3qbRyleGYQ+3nf3vgubY8Mt7HzEc=
diff --git a/samples/pbe/openssl/des-ede3.raw b/samples/pbe/openssl/des-ede3.raw
new file mode 100644
index 0000000..3e73552
--- /dev/null
+++ b/samples/pbe/openssl/des-ede3.raw
@@ -0,0 +1 @@
+Salted__�uݡ��q�:u��V݉|�Elaf�
\ No newline at end of file
diff --git a/samples/pbe/openssl/des-ofb.base64 b/samples/pbe/openssl/des-ofb.base64
new file mode 100644
index 0000000..128aec2
--- /dev/null
+++ b/samples/pbe/openssl/des-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX192vJ3lZfCnhYIFA+wrnKArDflCUg==
diff --git a/samples/pbe/openssl/des-ofb.raw b/samples/pbe/openssl/des-ofb.raw
new file mode 100644
index 0000000..07522db
--- /dev/null
+++ b/samples/pbe/openssl/des-ofb.raw
@@ -0,0 +1 @@
+Salted__K(�Px
pm�o�Ki�vJ1�
\ No newline at end of file
diff --git a/samples/pbe/openssl/des.base64 b/samples/pbe/openssl/des.base64
new file mode 100644
index 0000000..0a49602
--- /dev/null
+++ b/samples/pbe/openssl/des.base64
@@ -0,0 +1 @@
+U2FsdGVkX19zPRX+p1hN8OdiT/721hQELF0qPM/BrZQ=
diff --git a/samples/pbe/openssl/des.raw b/samples/pbe/openssl/des.raw
new file mode 100644
index 0000000..e8f603f
--- /dev/null
+++ b/samples/pbe/openssl/des.raw
@@ -0,0 +1 @@
+Salted__�u��
G8����`��M�D*F/$
\ No newline at end of file
diff --git a/samples/pbe/openssl/des3.base64 b/samples/pbe/openssl/des3.base64
new file mode 100644
index 0000000..5c316cc
--- /dev/null
+++ b/samples/pbe/openssl/des3.base64
@@ -0,0 +1 @@
+U2FsdGVkX19YbvQFfBFxGlJc2AuPkALt+lhOkLfiuBA=
diff --git a/samples/pbe/openssl/des3.raw b/samples/pbe/openssl/des3.raw
new file mode 100644
index 0000000..eb1c405
--- /dev/null
+++ b/samples/pbe/openssl/des3.raw
@@ -0,0 +1 @@
+Salted__�A����`�L�&�+=/<2Ǥ���
\ No newline at end of file
diff --git a/samples/pbe/openssl/idea-cbc.base64 b/samples/pbe/openssl/idea-cbc.base64
new file mode 100644
index 0000000..1a02484
--- /dev/null
+++ b/samples/pbe/openssl/idea-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX18anz5GbGQC3cEYSpxQJpP7adc2pierOGk=
diff --git a/samples/pbe/openssl/idea-cbc.raw b/samples/pbe/openssl/idea-cbc.raw
new file mode 100644
index 0000000..ed7621c
--- /dev/null
+++ b/samples/pbe/openssl/idea-cbc.raw
@@ -0,0 +1 @@
+Salted__���CU�/Ud�6J��vzL�
ղd�
\ No newline at end of file
diff --git a/samples/pbe/openssl/idea-cfb.base64 b/samples/pbe/openssl/idea-cfb.base64
new file mode 100644
index 0000000..87b3b73
--- /dev/null
+++ b/samples/pbe/openssl/idea-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19WEa+hCPUXsXw1cQcOxuhFKZsTYA==
diff --git a/samples/pbe/openssl/idea-cfb.raw b/samples/pbe/openssl/idea-cfb.raw
new file mode 100644
index 0000000..9c43fda
--- /dev/null
+++ b/samples/pbe/openssl/idea-cfb.raw
@@ -0,0 +1 @@
+Salted__�L[��ߩ�ߛu���h���9
\ No newline at end of file
diff --git a/samples/pbe/openssl/idea-ecb.base64 b/samples/pbe/openssl/idea-ecb.base64
new file mode 100644
index 0000000..cf252fb
--- /dev/null
+++ b/samples/pbe/openssl/idea-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX192rke++eIbThteXe01uv4EAkShDnmCkfQ=
diff --git a/samples/pbe/openssl/idea-ecb.raw b/samples/pbe/openssl/idea-ecb.raw
new file mode 100644
index 0000000..2e5dec9
--- /dev/null
+++ b/samples/pbe/openssl/idea-ecb.raw
@@ -0,0 +1 @@
+Salted__Qt��Ґ鲥+��٤<�?���\�
\ No newline at end of file
diff --git a/samples/pbe/openssl/idea-ofb.base64 b/samples/pbe/openssl/idea-ofb.base64
new file mode 100644
index 0000000..71f1ae8
--- /dev/null
+++ b/samples/pbe/openssl/idea-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19Oo4w9AlD0tpEySsbAkOjLdswl1A==
diff --git a/samples/pbe/openssl/idea-ofb.raw b/samples/pbe/openssl/idea-ofb.raw
new file mode 100644
index 0000000..80dad7d
--- /dev/null
+++ b/samples/pbe/openssl/idea-ofb.raw
@@ -0,0 +1 @@
+Salted__���S��UKļEذ�
�/�
\ No newline at end of file
diff --git a/samples/pbe/openssl/idea.base64 b/samples/pbe/openssl/idea.base64
new file mode 100644
index 0000000..99f5907
--- /dev/null
+++ b/samples/pbe/openssl/idea.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/NG2JQ8i+waaovzgmxYzKJAw8r9XYnR2Q=
diff --git a/samples/pbe/openssl/idea.raw b/samples/pbe/openssl/idea.raw
new file mode 100644
index 0000000..9e5e848
--- /dev/null
+++ b/samples/pbe/openssl/idea.raw
@@ -0,0 +1 @@
+Salted__���2p��ε�p��R��
u����
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2-40-cbc.base64 b/samples/pbe/openssl/rc2-40-cbc.base64
new file mode 100644
index 0000000..9415335
--- /dev/null
+++ b/samples/pbe/openssl/rc2-40-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+Dkr+tjgpPtlo+jpfdPAWpTkV88yzXaM4=
diff --git a/samples/pbe/openssl/rc2-40-cbc.raw b/samples/pbe/openssl/rc2-40-cbc.raw
new file mode 100644
index 0000000..c17e87a
--- /dev/null
+++ b/samples/pbe/openssl/rc2-40-cbc.raw
@@ -0,0 +1 @@
+Salted__�q���
�=�:�΋U㩣�2
�
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2-64-cbc.base64 b/samples/pbe/openssl/rc2-64-cbc.base64
new file mode 100644
index 0000000..5b5b232
--- /dev/null
+++ b/samples/pbe/openssl/rc2-64-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+3+4JXs1/XiSH2fB9mn1yqU8qdonwvl+o=
diff --git a/samples/pbe/openssl/rc2-64-cbc.raw b/samples/pbe/openssl/rc2-64-cbc.raw
new file mode 100644
index 0000000..b9c08ee
--- /dev/null
+++ b/samples/pbe/openssl/rc2-64-cbc.raw
@@ -0,0 +1 @@
+Salted__��>�f�

x
��<�����L
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2-cbc.base64 b/samples/pbe/openssl/rc2-cbc.base64
new file mode 100644
index 0000000..fbcde0e
--- /dev/null
+++ b/samples/pbe/openssl/rc2-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX19O/CBHf3CpY8+jvQkw0Tq2czsnICJOv+A=
diff --git a/samples/pbe/openssl/rc2-cbc.raw b/samples/pbe/openssl/rc2-cbc.raw
new file mode 100644
index 0000000..d5200c6
--- /dev/null
+++ b/samples/pbe/openssl/rc2-cbc.raw
@@ -0,0 +1 @@
+Salted__�bZX4��5f��჎�4����s��
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2-cfb.base64 b/samples/pbe/openssl/rc2-cfb.base64
new file mode 100644
index 0000000..7952786
--- /dev/null
+++ b/samples/pbe/openssl/rc2-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+JuIje5xmEnRsCsmwaWTYgjVVqKw==
diff --git a/samples/pbe/openssl/rc2-cfb.raw b/samples/pbe/openssl/rc2-cfb.raw
new file mode 100644
index 0000000..7aa1960
--- /dev/null
+++ b/samples/pbe/openssl/rc2-cfb.raw
@@ -0,0 +1 @@
+Salted__���*� ֻo����F9
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2-ecb.base64 b/samples/pbe/openssl/rc2-ecb.base64
new file mode 100644
index 0000000..208b26f
--- /dev/null
+++ b/samples/pbe/openssl/rc2-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX1/uCJVscD2CrMxyEtpyqI7D4mFtNj3hsig=
diff --git a/samples/pbe/openssl/rc2-ecb.raw b/samples/pbe/openssl/rc2-ecb.raw
new file mode 100644
index 0000000..9f9e117
--- /dev/null
+++ b/samples/pbe/openssl/rc2-ecb.raw
@@ -0,0 +1 @@
+Salted__���x]Cb�V���U�g�I��E
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2-ofb.base64 b/samples/pbe/openssl/rc2-ofb.base64
new file mode 100644
index 0000000..1b575c3
--- /dev/null
+++ b/samples/pbe/openssl/rc2-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19iLfApzAcq690yVAy0D5IZjybZ9Q==
diff --git a/samples/pbe/openssl/rc2-ofb.raw b/samples/pbe/openssl/rc2-ofb.raw
new file mode 100644
index 0000000..28fc695
--- /dev/null
+++ b/samples/pbe/openssl/rc2-ofb.raw
@@ -0,0 +1 @@
+Salted__泷>@Rp2[l������
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc2.base64 b/samples/pbe/openssl/rc2.base64
new file mode 100644
index 0000000..fe79ed1
--- /dev/null
+++ b/samples/pbe/openssl/rc2.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+W2lM2oWECxc+df8bRWRjjQAZWgHyK0TE=
diff --git a/samples/pbe/openssl/rc2.raw b/samples/pbe/openssl/rc2.raw
new file mode 100644
index 0000000..376a092
--- /dev/null
+++ b/samples/pbe/openssl/rc2.raw
@@ -0,0 +1 @@
+Salted__r���阙t1����o9
�x4O
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc4-40.base64 b/samples/pbe/openssl/rc4-40.base64
new file mode 100644
index 0000000..6623b2d
--- /dev/null
+++ b/samples/pbe/openssl/rc4-40.base64
@@ -0,0 +1 @@
+U2FsdGVkX19tJLA4MdMspjkJ9yV98jm4ZEH4LA==
diff --git a/samples/pbe/openssl/rc4-40.raw b/samples/pbe/openssl/rc4-40.raw
new file mode 100644
index 0000000..cc3b9ac
--- /dev/null
+++ b/samples/pbe/openssl/rc4-40.raw
@@ -0,0 +1 @@
+Salted__%�°SⲨ��7�#��"��
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc4.base64 b/samples/pbe/openssl/rc4.base64
new file mode 100644
index 0000000..6653092
--- /dev/null
+++ b/samples/pbe/openssl/rc4.base64
@@ -0,0 +1 @@
+U2FsdGVkX182oCiqgQ41HapT14y1GjgXQW+xTw==
diff --git a/samples/pbe/openssl/rc4.raw b/samples/pbe/openssl/rc4.raw
new file mode 100644
index 0000000..e0774e7
--- /dev/null
+++ b/samples/pbe/openssl/rc4.raw
@@ -0,0 +1 @@
+Salted__�t4Z/�ck�ء�{�"Yp�
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc5-cbc.base64 b/samples/pbe/openssl/rc5-cbc.base64
new file mode 100644
index 0000000..8ede98d
--- /dev/null
+++ b/samples/pbe/openssl/rc5-cbc.base64
@@ -0,0 +1 @@
+U2FsdGVkX1984SHjF+Gnmpg7mzTZcUatW+a4AbICOJ0=
diff --git a/samples/pbe/openssl/rc5-cbc.raw b/samples/pbe/openssl/rc5-cbc.raw
new file mode 100644
index 0000000..fd2070f
--- /dev/null
+++ b/samples/pbe/openssl/rc5-cbc.raw
@@ -0,0 +1 @@
+Salted__Vv�'�C�Dn�J�T��p�O�`c
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc5-cfb.base64 b/samples/pbe/openssl/rc5-cfb.base64
new file mode 100644
index 0000000..3bba7cb
--- /dev/null
+++ b/samples/pbe/openssl/rc5-cfb.base64
@@ -0,0 +1 @@
+U2FsdGVkX19S/C6iCDSQ3z9Tuvs1mLppmLIrKw==
diff --git a/samples/pbe/openssl/rc5-cfb.raw b/samples/pbe/openssl/rc5-cfb.raw
new file mode 100644
index 0000000..12c626e
--- /dev/null
+++ b/samples/pbe/openssl/rc5-cfb.raw
@@ -0,0 +1 @@
+Salted__����>Ƨ��~�+�lz�����
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc5-ecb.base64 b/samples/pbe/openssl/rc5-ecb.base64
new file mode 100644
index 0000000..118973a
--- /dev/null
+++ b/samples/pbe/openssl/rc5-ecb.base64
@@ -0,0 +1 @@
+U2FsdGVkX18bkW6/nLaP0zItEAKqgnmMnJ1oquul/tw=
diff --git a/samples/pbe/openssl/rc5-ecb.raw b/samples/pbe/openssl/rc5-ecb.raw
new file mode 100644
index 0000000..4e7963b
--- /dev/null
+++ b/samples/pbe/openssl/rc5-ecb.raw
@@ -0,0 +1 @@
+Salted__������F�G��@��Pyw
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc5-ofb.base64 b/samples/pbe/openssl/rc5-ofb.base64
new file mode 100644
index 0000000..ddbb752
--- /dev/null
+++ b/samples/pbe/openssl/rc5-ofb.base64
@@ -0,0 +1 @@
+U2FsdGVkX188hLLVFYY9QjWngoLlMX1ziLhd0Q==
diff --git a/samples/pbe/openssl/rc5-ofb.raw b/samples/pbe/openssl/rc5-ofb.raw
new file mode 100644
index 0000000..f547846
--- /dev/null
+++ b/samples/pbe/openssl/rc5-ofb.raw
@@ -0,0 +1 @@
+Salted__�*��@bҫ���K��]e����
\ No newline at end of file
diff --git a/samples/pbe/openssl/rc5.base64 b/samples/pbe/openssl/rc5.base64
new file mode 100644
index 0000000..78dbf97
--- /dev/null
+++ b/samples/pbe/openssl/rc5.base64
@@ -0,0 +1 @@
+U2FsdGVkX1+XyN0T6HGqi3prs1uD91+BIG3RIaqJYxo=
diff --git a/samples/pbe/openssl/rc5.raw b/samples/pbe/openssl/rc5.raw
new file mode 100644
index 0000000..710fae7
--- /dev/null
+++ b/samples/pbe/openssl/rc5.raw
@@ -0,0 +1 @@
+Salted__�yx����HvA���ɗ�W!B�ǣ
\ No newline at end of file
diff --git a/samples/pkcs12/pkcs12_client_cert.p12 b/samples/pkcs12/pkcs12_client_cert.p12
new file mode 100644
index 0000000..206b9cc
Binary files /dev/null and b/samples/pkcs12/pkcs12_client_cert.p12 differ
diff --git a/samples/pkcs12/pkcs12_client_cert.pem b/samples/pkcs12/pkcs12_client_cert.pem
new file mode 100644
index 0000000..f45a4d2
--- /dev/null
+++ b/samples/pkcs12/pkcs12_client_cert.pem
@@ -0,0 +1,94 @@
+Bag Attributes
+    localKeyID: 63 5B 15 F0 27 F2 03 31 C2 A3 21 65 54 08 FB EA 03 B4 C1 D7 
+    friendlyName: commons-ssl demo certificate
+subject=/C=CA/ST=BC/L=Vancouver/O=www.cucbc.com/OU=commons_ssl/CN=demo_certificate/emailAddress=juliusdavies at gmail.com
+issuer=/C=CA/ST=BC/L=Vancouver/O=www.cucbc.com/OU=commons_ssl/CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIJAIz+EYMBU6Z/MA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTEwNTIxNTIzN1oXDTA3MTEwNTIxNTIzN1owgZ4x
+CzAJBgNVBAYTAkNBMQswCQYDVQQIEwJCQzESMBAGA1UEBxMJVmFuY291dmVyMRYw
+FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEZMBcG
+A1UEAxQQZGVtb19jZXJ0aWZpY2F0ZTElMCMGCSqGSIb3DQEJARYWanVsaXVzZGF2
+aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhj
+r5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2BlYho4O84
+X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRyzerA/Ztr
+lUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY07hNKXAb
+2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8BqnGd87x
+QU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiVJTxpTKqy
+m93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E
+HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFJ8Ud78/
+OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNSyoemDT4N
+MA0GCSqGSIb3DQEBBQUAA4IBAQBwLCkX9lU7sPKCU9sGrAGMLEDCWTBYeK8X1zlL
+h/Lf7c+TgNUFyoEThLzWhxUBfkX4J9k+Rgqlkg3OcSW0QGsXFuf91DCMn9+K91NP
+kecN6rcGA/RIi20J6s9YmVWJWAXciiUFVY0ZZYfzvjK1mEIBY4CbJatQiEvhbQl/
+aid8ZgdkrKbB1nPmBTBOMul9Z1FgIBRetzxxxwKFqlcWZlY6M86FrmJYQVxmiK7m
+Pqd7suace7kpLvsM3sRzXEDPqSeB8fBaoqVxCngsdx0MiPueSYw4J0mDtRRTT990
+CxgCFeby0mem9EsZ7CMBBFJbQ44NjjfGoZoh9LXKxiFPMYtU
+-----END CERTIFICATE-----
+Bag Attributes: <No Attributes>
+subject=/C=CA/ST=BC/L=Vancouver/O=www.cucbc.com/OU=commons_ssl/CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+issuer=/C=CA/ST=BC/O=www.cucbc.com/OU=commons_ssl/CN=demo_root_ca/emailAddress=juliusdavies at gmail.com
+-----BEGIN CERTIFICATE-----
+MIIEnDCCA4SgAwIBAgIJAJTNwZ6yNa5cMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS
+BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq
+hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjE0OTMx
+WhcNMDcxMTA1MjE0OTMxWjCBojELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRIw
+EAYDVQQHEwlWYW5jb3V2ZXIxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDASBgNV
+BAsUC2NvbW1vbnNfc3NsMR0wGwYDVQQDFBRkZW1vX2ludGVybWVkaWF0ZV9jYTEl
+MCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL0S4y3vUO0EM6lwqOEfK8fvrUprIbsikXaG
+XzejcZ+T3l2Dc7t8WtBfRf78i4JypMqJQSijrUicj3H6mOMIReKaXm6ls4hA5d8w
+Lhmgiqsz/kW+gA8SeWGWRN683BD/RbQmzOls6ynBvap9jZlthXWBrSIlPCQoBLXY
+KVaxGzbL4ezaq+XFMKMQSm2uKwVmHHQNbfmZlPsuendBVomb/ked53Ab9IH6dwwN
+qJH9WIrvIzIVEXWlpvQ5MCqozM7u1akU+G8cazr8theGPCaYkzoXnigWua4OjdpV
+9z5ZDknhfBzG1AjapdG07FIirwWWgIyZXqZSD96ikmLtwT29qnsCAwEAAaOB7jCB
+6zAdBgNVHQ4EFgQUe5raj5CZTlLSrNuzA1LKh6YNPg0wgbsGA1UdIwSBszCBsIAU
+rN8eFIvMiRFXXgDqKumS0/W2AhOhgYykgYkwgYYxCzAJBgNVBAYTAkNBMQswCQYD
+VQQIEwJCQzEWMBQGA1UEChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9u
+c19zc2wxFTATBgNVBAMUDGRlbW9fcm9vdF9jYTElMCMGCSqGSIb3DQEJARYWanVs
+aXVzZGF2aWVzQGdtYWlsLmNvbYIJAJTNwZ6yNa5bMAwGA1UdEwQFMAMBAf8wDQYJ
+KoZIhvcNAQEFBQADggEBAIB4KMZvHD20pdKajFtMBpL7X4W4soq6EeTtjml3NYa9
+Qc52bsQEGNccKY9afYSBIndaQvFdtmz6HdoN+B8TjYShw2KhyjtKimGLpWYoi1YF
+e4aHdmA/Gp5xk8pZzR18FmooxC9RqBux+NAM2iTFSLgDtGIIj4sg2rbn6Bb6ZlQT
+1rg6VucXCA1629lNfMeNcu7CBNmUKIdaxHR/YJQallE0KfGRiOIWPrPj/VNk0YA6
+XFg0ocjqXJ2/N0N9rWVshMUaXgOh7m4D/5zga5/nuxDU+PoToA6mQ4bV6eCYqZbh
+aa1kQYtR9B4ZiG6pB82qVc2dCqStOH2FAEWos2gAVkQ=
+-----END CERTIFICATE-----
+Bag Attributes
+    localKeyID: 63 5B 15 F0 27 F2 03 31 C2 A3 21 65 54 08 FB EA 03 B4 C1 D7 
+    friendlyName: commons-ssl demo certificate
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,958A07981A0FCEB0
+
+xwOFxogRiAGShZ/VkWz5Nqwdk3j12i5vLLbNhA5OgAwgRUqk5DzuJYaozJ+lVLk/
+sCwKtQ+OmaYeSYtXsTuUcNIgki8GgaPnBCXOyfZIR8ZjSCA+VT41lAvcWQ3EUUvB
+wB0yT2kWhSIwR+0lWw57MiUhyzLmTBlynSVZBRTe45/y0c4ulzodQW7zrE8G0hqq
+pB1moyADgeLh/i1iqvf3LNrZoRA5j5d72jA5sOJTK75BDekFzrPbf6Z94/N/+6nN
+oluxagf2thJ1fFs1vqOmJGb/sTBow5ToZ7lwe3kH/q5rc/0ecJWu5EAezvYB9dFs
+V1QUVOSsdkdRq8QhfS2QjYujkqUg9CQtWbEF90EyV4DWhUSugEOPj4LKPmqHg2+i
+zC39d/jizCeax42taJYYF5moWy/h43UtkLdHCkDjHmOXuMQaXGxJyV686ABuuMgI
+UN/CRKv6TjmmJZwxDYCuGNbcOov/J4Qk/Qf7FM62ZPT0DBnIXGnOHmegvGNbL3hx
+va60Fvga5uLxT4f2a5JXrNOJyxVlkFNqirWvWuS020rVK7SmF6Hx79v83g2oW83b
+Ox7KZ+zlcndqFUDA8iwdhmrqTpRqYxCF+PHFC/wO0LmA25693pLN+2x0Zdk0cH/Q
+hzykSOcydEctrkqPrJzg3m4U0gICssfPrbB8pkP6qk3ucSsFWYRQpo1Fv+yDqssG
+yiDOzmYXCxkjYcYm5MkX4vY/ggNi4ge3TVNMWCtIyr9WoVXT/0qFDN4i4vlJkTOQ
+kyhjfS25Dou2+PyNUe4rfWg7lH/5EhZbn6ZN9E7jKd0OOymLSeh08nt5abcuNBE3
+2QYXqBxBUmh29dyxn0Rl8UQQceFC6zvai2XVYKiw3EdMAeNp0NIKOEtkLZsGrE+t
+IWul0NZyqJmMDAP1GzNMg8HaL0mPh6PgoesNKMRYAqD1uNqzQfHnid1TrxFoJuzH
+GSwmX7QctDt7iXmqG9WETbw+WXg1IbpetxC/Lom54jRo05GcI0eCDCSY88EwSNPT
+SWLHlBw12axu+fzNFmkdV2y5qoi7YHq95S2BzO0Eh5p0BiCl80zCyT+eTt+2aJOK
+i7TTQDSjzwtqj7qgqltJAmdrbMFF0d15eO3+Fj9PULN5cOBor80RWs9gv71I5Ybe
++QA0QijIPuH19nB7L4hOT5vZgp1aCUsLyoCgv1WaIBgYgqQbcgDhbQs/vPBP699y
+/52Dr8G11/9MIEqA9yVLdj/dksGhhjRy3mtT1m35qG05ohKMd3+jESFA6IpHOyNF
+D3v/raj+ioW94KqYZepSvQYfDV4GUKeI40YlH3yDzSbj9npDtWdHX3OnCo9TKNkH
+xhyDt4t9WB7G7nUxq76/ZKSnAA0zvMRRRqFQOn8F3JMnEMYy5Dbn4I1xmmTXl3xN
+Kz7bywFiFb+lcCW9FGHRFVL9skEYLxvEQVbv+IteVqzrbInhfvIxgRr4Cbxoy8sU
+rl9sGr5ab4OTuIr6zOpUxJkWkTFy+LRv2M+lJ5OFbKJYLC3azk9t+dzjST6pE16R
+SQLoi0JXCiE5ohaL+IGXnegKNFIy9L/Wy0sBFUipkhhlDAWGNwgsPTnC1mhwGjKF
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa.html b/samples/rsa.html
new file mode 100644
index 0000000..f03e594
--- /dev/null
+++ b/samples/rsa.html
@@ -0,0 +1,114 @@
+<pre>
+java -showversion -cp <a href="../download.html">build/not-yet-commons-ssl-0.3.7.jar</a>  org.apache.commons.ssl.PKCS8Key <a href="rsa/">samples/rsa/*.*</a>
+
+java version "1.6.0"
+Java(TM) SE Runtime Environment (build 1.6.0-b105)
+Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
+
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	128	<a href="rsa/openssl_rsa_aes128_cbc.pem">samples/rsa/openssl_rsa_aes128_cbc.pem</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	128	<a href="rsa/openssl_rsa_aes128_cfb.pem">samples/rsa/openssl_rsa_aes128_cfb.pem</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	128	<a href="rsa/openssl_rsa_aes128_ecb.pem">samples/rsa/openssl_rsa_aes128_ecb.pem</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	128	<a href="rsa/openssl_rsa_aes128_ofb.pem">samples/rsa/openssl_rsa_aes128_ofb.pem</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	192	<a href="rsa/openssl_rsa_aes192_cbc.pem">samples/rsa/openssl_rsa_aes192_cbc.pem</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	192	<a href="rsa/openssl_rsa_aes192_cfb.pem">samples/rsa/openssl_rsa_aes192_cfb.pem</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	192	<a href="rsa/openssl_rsa_aes192_ecb.pem">samples/rsa/openssl_rsa_aes192_ecb.pem</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	192	<a href="rsa/openssl_rsa_aes192_ofb.pem">samples/rsa/openssl_rsa_aes192_ofb.pem</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	256	<a href="rsa/openssl_rsa_aes256_cbc.pem">samples/rsa/openssl_rsa_aes256_cbc.pem</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	256	<a href="rsa/openssl_rsa_aes256_cfb.pem">samples/rsa/openssl_rsa_aes256_cfb.pem</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	256	<a href="rsa/openssl_rsa_aes256_ecb.pem">samples/rsa/openssl_rsa_aes256_ecb.pem</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	256	<a href="rsa/openssl_rsa_aes256_ofb.pem">samples/rsa/openssl_rsa_aes256_ofb.pem</a>
+   SUCCESS    	RSA	Blowfish/CBC/PKCS5Padding	128	<a href="rsa/openssl_rsa_blowfish_cbc.pem">samples/rsa/openssl_rsa_blowfish_cbc.pem</a>
+   SUCCESS    	RSA	Blowfish/CFB/NoPadding   	128	<a href="rsa/openssl_rsa_blowfish_cfb.pem">samples/rsa/openssl_rsa_blowfish_cfb.pem</a>
+   SUCCESS    	RSA	Blowfish/ECB/PKCS5Padding	128	<a href="rsa/openssl_rsa_blowfish_ecb.pem">samples/rsa/openssl_rsa_blowfish_ecb.pem</a>
+   SUCCESS    	RSA	Blowfish/OFB/NoPadding   	128	<a href="rsa/openssl_rsa_blowfish_ofb.pem">samples/rsa/openssl_rsa_blowfish_ofb.pem</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/openssl_rsa_des1_cbc.pem">samples/rsa/openssl_rsa_des1_cbc.pem</a>
+   SUCCESS    	RSA	DES/CFB/NoPadding        	 64	<a href="rsa/openssl_rsa_des1_cfb.pem">samples/rsa/openssl_rsa_des1_cfb.pem</a>
+   SUCCESS    	RSA	DES/ECB/PKCS5Padding     	 64	<a href="rsa/openssl_rsa_des1_ecb.pem">samples/rsa/openssl_rsa_des1_ecb.pem</a>
+   SUCCESS    	RSA	DES/OFB/NoPadding        	 64	<a href="rsa/openssl_rsa_des1_ofb.pem">samples/rsa/openssl_rsa_des1_ofb.pem</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/openssl_rsa_des2_cbc.pem">samples/rsa/openssl_rsa_des2_cbc.pem</a>
+   SUCCESS    	RSA	DESede/CFB/NoPadding     	192	<a href="rsa/openssl_rsa_des2_cfb.pem">samples/rsa/openssl_rsa_des2_cfb.pem</a>
+   SUCCESS    	RSA	DESede/ECB/PKCS5Padding  	192	<a href="rsa/openssl_rsa_des2_ecb.pem">samples/rsa/openssl_rsa_des2_ecb.pem</a>
+   SUCCESS    	RSA	DESede/OFB/NoPadding     	192	<a href="rsa/openssl_rsa_des2_ofb.pem">samples/rsa/openssl_rsa_des2_ofb.pem</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/openssl_rsa_des3_cbc.pem">samples/rsa/openssl_rsa_des3_cbc.pem</a>
+   SUCCESS    	RSA	DESede/CFB/NoPadding     	192	<a href="rsa/openssl_rsa_des3_cfb.pem">samples/rsa/openssl_rsa_des3_cfb.pem</a>
+   SUCCESS    	RSA	DESede/ECB/PKCS5Padding  	192	<a href="rsa/openssl_rsa_des3_ecb.pem">samples/rsa/openssl_rsa_des3_ecb.pem</a>
+   SUCCESS    	RSA	DESede/OFB/NoPadding     	192	<a href="rsa/openssl_rsa_des3_ofb.pem">samples/rsa/openssl_rsa_des3_ofb.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	128	<a href="rsa/openssl_rsa_rc2_128_cbc.pem">samples/rsa/openssl_rsa_rc2_128_cbc.pem</a>
+   SUCCESS    	RSA	RC2/CFB/NoPadding        	128	<a href="rsa/openssl_rsa_rc2_128_cfb.pem">samples/rsa/openssl_rsa_rc2_128_cfb.pem</a>
+   SUCCESS    	RSA	RC2/ECB/PKCS5Padding     	128	<a href="rsa/openssl_rsa_rc2_128_ecb.pem">samples/rsa/openssl_rsa_rc2_128_ecb.pem</a>
+   SUCCESS    	RSA	RC2/OFB/NoPadding        	128	<a href="rsa/openssl_rsa_rc2_128_ofb.pem">samples/rsa/openssl_rsa_rc2_128_ofb.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 40	<a href="rsa/openssl_rsa_rc2_40.pem">samples/rsa/openssl_rsa_rc2_40.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/openssl_rsa_rc2_64.pem">samples/rsa/openssl_rsa_rc2_64.pem</a>
+   SUCCESS    	RSA	UNENCRYPTED              	  0	<a href="rsa/openssl_rsa_unencrypted.der">samples/rsa/openssl_rsa_unencrypted.der</a>
+   SUCCESS    	RSA	UNENCRYPTED              	  0	<a href="rsa/openssl_rsa_unencrypted.pem">samples/rsa/openssl_rsa_unencrypted.pem</a>
+   SUCCESS    	RSA	UNENCRYPTED              	  0	<a href="rsa/pkcs8_rsa_unencrypted.der">samples/rsa/pkcs8_rsa_unencrypted.der</a>
+   SUCCESS    	RSA	UNENCRYPTED              	  0	<a href="rsa/pkcs8_rsa_unencrypted.pem">samples/rsa/pkcs8_rsa_unencrypted.pem</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md2_des1.der">samples/rsa/pkcs8v1_rsa_md2_des1.der</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md2_des1.pem">samples/rsa/pkcs8v1_rsa_md2_des1.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md2_rc2_64.der">samples/rsa/pkcs8v1_rsa_md2_rc2_64.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md2_rc2_64.pem">samples/rsa/pkcs8v1_rsa_md2_rc2_64.pem</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md5_des1.der">samples/rsa/pkcs8v1_rsa_md5_des1.der</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md5_des1.pem">samples/rsa/pkcs8v1_rsa_md5_des1.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md5_rc2_64.der">samples/rsa/pkcs8v1_rsa_md5_rc2_64.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_md5_rc2_64.pem">samples/rsa/pkcs8v1_rsa_md5_rc2_64.pem</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_sha1_des1.der">samples/rsa/pkcs8v1_rsa_sha1_des1.der</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_sha1_des1.pem">samples/rsa/pkcs8v1_rsa_sha1_des1.pem</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/pkcs8v1_rsa_sha1_des2.der">samples/rsa/pkcs8v1_rsa_sha1_des2.der</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/pkcs8v1_rsa_sha1_des2.pem">samples/rsa/pkcs8v1_rsa_sha1_des2.pem</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/pkcs8v1_rsa_sha1_des3.der">samples/rsa/pkcs8v1_rsa_sha1_des3.der</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/pkcs8v1_rsa_sha1_des3.pem">samples/rsa/pkcs8v1_rsa_sha1_des3.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	128	<a href="rsa/pkcs8v1_rsa_sha1_rc2_128.der">samples/rsa/pkcs8v1_rsa_sha1_rc2_128.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	128	<a href="rsa/pkcs8v1_rsa_sha1_rc2_128.pem">samples/rsa/pkcs8v1_rsa_sha1_rc2_128.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 40	<a href="rsa/pkcs8v1_rsa_sha1_rc2_40.der">samples/rsa/pkcs8v1_rsa_sha1_rc2_40.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 40	<a href="rsa/pkcs8v1_rsa_sha1_rc2_40.pem">samples/rsa/pkcs8v1_rsa_sha1_rc2_40.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_sha1_rc2_64.der">samples/rsa/pkcs8v1_rsa_sha1_rc2_64.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v1_rsa_sha1_rc2_64.pem">samples/rsa/pkcs8v1_rsa_sha1_rc2_64.pem</a>
+   SUCCESS    	RSA	RC4                      	128	<a href="rsa/pkcs8v1_rsa_sha1_rc4_128.der">samples/rsa/pkcs8v1_rsa_sha1_rc4_128.der</a>
+   SUCCESS    	RSA	RC4                      	128	<a href="rsa/pkcs8v1_rsa_sha1_rc4_128.pem">samples/rsa/pkcs8v1_rsa_sha1_rc4_128.pem</a>
+   SUCCESS    	RSA	RC4                      	 40	<a href="rsa/pkcs8v1_rsa_sha1_rc4_40.der">samples/rsa/pkcs8v1_rsa_sha1_rc4_40.der</a>
+   SUCCESS    	RSA	RC4                      	 40	<a href="rsa/pkcs8v1_rsa_sha1_rc4_40.pem">samples/rsa/pkcs8v1_rsa_sha1_rc4_40.pem</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	128	<a href="rsa/pkcs8v2_rsa_aes128_cbc.der">samples/rsa/pkcs8v2_rsa_aes128_cbc.der</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	128	<a href="rsa/pkcs8v2_rsa_aes128_cbc.pem">samples/rsa/pkcs8v2_rsa_aes128_cbc.pem</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	128	<a href="rsa/pkcs8v2_rsa_aes128_cfb.der">samples/rsa/pkcs8v2_rsa_aes128_cfb.der</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	128	<a href="rsa/pkcs8v2_rsa_aes128_cfb.pem">samples/rsa/pkcs8v2_rsa_aes128_cfb.pem</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	128	<a href="rsa/pkcs8v2_rsa_aes128_ecb.der">samples/rsa/pkcs8v2_rsa_aes128_ecb.der</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	128	<a href="rsa/pkcs8v2_rsa_aes128_ecb.pem">samples/rsa/pkcs8v2_rsa_aes128_ecb.pem</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	128	<a href="rsa/pkcs8v2_rsa_aes128_ofb.der">samples/rsa/pkcs8v2_rsa_aes128_ofb.der</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	128	<a href="rsa/pkcs8v2_rsa_aes128_ofb.pem">samples/rsa/pkcs8v2_rsa_aes128_ofb.pem</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	192	<a href="rsa/pkcs8v2_rsa_aes192_cbc.der">samples/rsa/pkcs8v2_rsa_aes192_cbc.der</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	192	<a href="rsa/pkcs8v2_rsa_aes192_cbc.pem">samples/rsa/pkcs8v2_rsa_aes192_cbc.pem</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	192	<a href="rsa/pkcs8v2_rsa_aes192_cfb.der">samples/rsa/pkcs8v2_rsa_aes192_cfb.der</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	192	<a href="rsa/pkcs8v2_rsa_aes192_cfb.pem">samples/rsa/pkcs8v2_rsa_aes192_cfb.pem</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	192	<a href="rsa/pkcs8v2_rsa_aes192_ecb.der">samples/rsa/pkcs8v2_rsa_aes192_ecb.der</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	192	<a href="rsa/pkcs8v2_rsa_aes192_ecb.pem">samples/rsa/pkcs8v2_rsa_aes192_ecb.pem</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	192	<a href="rsa/pkcs8v2_rsa_aes192_ofb.der">samples/rsa/pkcs8v2_rsa_aes192_ofb.der</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	192	<a href="rsa/pkcs8v2_rsa_aes192_ofb.pem">samples/rsa/pkcs8v2_rsa_aes192_ofb.pem</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	256	<a href="rsa/pkcs8v2_rsa_aes256_cbc.der">samples/rsa/pkcs8v2_rsa_aes256_cbc.der</a>
+   SUCCESS    	RSA	AES/CBC/PKCS5Padding     	256	<a href="rsa/pkcs8v2_rsa_aes256_cbc.pem">samples/rsa/pkcs8v2_rsa_aes256_cbc.pem</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	256	<a href="rsa/pkcs8v2_rsa_aes256_cfb.der">samples/rsa/pkcs8v2_rsa_aes256_cfb.der</a>
+   SUCCESS    	RSA	AES/CFB/NoPadding        	256	<a href="rsa/pkcs8v2_rsa_aes256_cfb.pem">samples/rsa/pkcs8v2_rsa_aes256_cfb.pem</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	256	<a href="rsa/pkcs8v2_rsa_aes256_ecb.der">samples/rsa/pkcs8v2_rsa_aes256_ecb.der</a>
+   SUCCESS    	RSA	AES/ECB/PKCS5Padding     	256	<a href="rsa/pkcs8v2_rsa_aes256_ecb.pem">samples/rsa/pkcs8v2_rsa_aes256_ecb.pem</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	256	<a href="rsa/pkcs8v2_rsa_aes256_ofb.der">samples/rsa/pkcs8v2_rsa_aes256_ofb.der</a>
+   SUCCESS    	RSA	AES/OFB/NoPadding        	256	<a href="rsa/pkcs8v2_rsa_aes256_ofb.pem">samples/rsa/pkcs8v2_rsa_aes256_ofb.pem</a>
+   SUCCESS    	RSA	Blowfish/CBC/PKCS5Padding	128	<a href="rsa/pkcs8v2_rsa_blowfish_cbc.der">samples/rsa/pkcs8v2_rsa_blowfish_cbc.der</a>
+   SUCCESS    	RSA	Blowfish/CBC/PKCS5Padding	128	<a href="rsa/pkcs8v2_rsa_blowfish_cbc.pem">samples/rsa/pkcs8v2_rsa_blowfish_cbc.pem</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v2_rsa_des1_cbc.der">samples/rsa/pkcs8v2_rsa_des1_cbc.der</a>
+   SUCCESS    	RSA	DES/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v2_rsa_des1_cbc.pem">samples/rsa/pkcs8v2_rsa_des1_cbc.pem</a>
+   SUCCESS    	RSA	DES/CFB/NoPadding        	 64	<a href="rsa/pkcs8v2_rsa_des1_cfb.der">samples/rsa/pkcs8v2_rsa_des1_cfb.der</a>
+   SUCCESS    	RSA	DES/CFB/NoPadding        	 64	<a href="rsa/pkcs8v2_rsa_des1_cfb.pem">samples/rsa/pkcs8v2_rsa_des1_cfb.pem</a>
+   SUCCESS    	RSA	DES/ECB/PKCS5Padding     	 64	<a href="rsa/pkcs8v2_rsa_des1_ecb.der">samples/rsa/pkcs8v2_rsa_des1_ecb.der</a>
+   SUCCESS    	RSA	DES/ECB/PKCS5Padding     	 64	<a href="rsa/pkcs8v2_rsa_des1_ecb.pem">samples/rsa/pkcs8v2_rsa_des1_ecb.pem</a>
+   SUCCESS    	RSA	DES/OFB/NoPadding        	 64	<a href="rsa/pkcs8v2_rsa_des1_ofb.der">samples/rsa/pkcs8v2_rsa_des1_ofb.der</a>
+   SUCCESS    	RSA	DES/OFB/NoPadding        	 64	<a href="rsa/pkcs8v2_rsa_des1_ofb.pem">samples/rsa/pkcs8v2_rsa_des1_ofb.pem</a>
+   SUCCESS    	RSA	DESede/ECB/PKCS5Padding  	192	<a href="rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.der">samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.der</a>
+   SUCCESS    	RSA	DESede/ECB/PKCS5Padding  	192	<a href="rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.pem">samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.pem</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/pkcs8v2_rsa_des3.der">samples/rsa/pkcs8v2_rsa_des3.der</a>
+   SUCCESS    	RSA	DESede/CBC/PKCS5Padding  	192	<a href="rsa/pkcs8v2_rsa_des3.pem">samples/rsa/pkcs8v2_rsa_des3.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	128	<a href="rsa/pkcs8v2_rsa_rc2_128.der">samples/rsa/pkcs8v2_rsa_rc2_128.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	128	<a href="rsa/pkcs8v2_rsa_rc2_128.pem">samples/rsa/pkcs8v2_rsa_rc2_128.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 40	<a href="rsa/pkcs8v2_rsa_rc2_40.der">samples/rsa/pkcs8v2_rsa_rc2_40.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 40	<a href="rsa/pkcs8v2_rsa_rc2_40.pem">samples/rsa/pkcs8v2_rsa_rc2_40.pem</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v2_rsa_rc2_64.der">samples/rsa/pkcs8v2_rsa_rc2_64.der</a>
+   SUCCESS    	RSA	RC2/CBC/PKCS5Padding     	 64	<a href="rsa/pkcs8v2_rsa_rc2_64.pem">samples/rsa/pkcs8v2_rsa_rc2_64.pem</a>
+</pre>
diff --git a/samples/rsa/openssl_rsa_aes128_cbc.pem b/samples/rsa/openssl_rsa_aes128_cbc.pem
new file mode 100644
index 0000000..e315053
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes128_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,8DA91D5A71988E3D4431D9C2C009F249
+
+ZUo4tso7YF0+ayrQpLsgM4TN2H31b5g5ryj//QqqVG/WmvYgl56Vu7fDbYXytgnb
+PQoJLo+8iUI1d51nirw3RrtAx7Z9lrBu6mX+JBE7nwCVsjBVVlAx1B6d6Jwc20wj
+935VaUkwT3n0zZ1dwb9HLjEGUp82TIbiZ3KjWKnfER2AhFXJl3SzswA5Fvwe0AYm
+KTAEYaaxigTTPgltiEQDIvA/Pnh9ZHjh6rbM816Fa2hdk30wjU4U/KkTYbg4hdoV
+vLeQpYnMT2uICCuvNXq0cXXetfbgdMFsLTxvVElUZrjyMTsw1QtjijeM+gj1dbDj
+HGzR0k97Xj3q+84m+SoNW29zPLZzSaFDX4KdKKG2cHs9BTYJmzb0h7qP4pCXjGgF
+8V2iUDMs7BQlgNnOa9gwT7x7DN4HM6J0MIlNIiYQZnupqqYQTDR0rd+fhdIsXHkA
+qNZKI/4ep7voVIufSS8ZyoISES3f7dvs5nnM2C+QAtL+l/yaaqRdfUyn9BL1djaP
+akSRPXmHrmed8s8YamuhLHyf+GPL2uYpd4i1voA2KKYSx4PnfjH/F/8fXPZr3dNh
+sDtcjhgXHTNAEVVek9VOaHtlUNZEY0UcbP5uqBZta+wP2rBTC94DxIbN+k8A2SlP
+cKGkaRltjnPJAXWmwKMRm1J7vXngXYq0r5VUvnGPiUhFlQwAW5TUml4+1SMEUirZ
+y/Oh3AjhOus67uiAXAQoqlr9KykueXobFrhZjLCgRf7iDmP/t1eK40UyV83w85yz
+cORi8FNfqvCARz05qXwfhf2NBMTRbLNzKCGjS4iY0dLNk+QYNgJGoM4nFVkHYgbM
+pTThzpYgtRnxQf1mYTZFtqr8hRJqiRfexzCyk2JC3rDtEO8WUmNdvdKNN0KwCd4+
+dcVS8KzNov9fYMqiiol0dL89WBN1RN+hs7HnOJkNZZgaNVspOLCT4+SN5fLgtbJI
+BzbAgTK1ILrSom5fyzZcRkYwzIqNc97YhRYnxDp7vJFlgsBqySJgtdGUkTPrrzAO
+CCYyi/ukSVphPe+qRsvj9L4syZgpLRgDdZaW+BR0pbTUg2WQvZuKL5iMhfB8cbAC
++FjoKeSlxI68jukrAYHBNcco+qaAYrUaHsJFUsbf7j85DzHxnaA3M+P0i+LWJwOI
+3G751QR2CrjgK+QD7XUtUjBMrsVGlJmfaQsEm7+rtuPynXq+ArJrvgha4lc0GRD6
+yNDCTTMafuBnJ72wop1UEE8zGOsqERsgvOAL10J1s5KCcPHGwrDhjhr3/x1GI6/e
+H80zp/E9mPgzYQMfhl06s9SwyvsxFCIZAfrKIhq7lVqeEDiusYbe15kCLmTVNZ6C
+c/BhDc76vwek05AOLaZLGbdpMRwevbOn4WvUHV0o5Yr1h1IGZKx9BQYwFS65SDCg
+uxfM+dKulE6MWD2hPUP9s47+R812cBnHu5BVV+Cq52YygAiAP1+nfFw7TBKzqczo
+fnIsoL69JthqtkZiwl36uMmcoWwZM621ZqYFJI53WO57uhW0uuoyidQj8HoNG/re
+o3OyAgVO6sTFsw/Dwxo4WX2AKuIt9W2IJMFNC7aS7lH0iPrtiVC3FFXvuY5agipH
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes128_cfb.pem b/samples/rsa/openssl_rsa_aes128_cfb.pem
new file mode 100644
index 0000000..8bd32ac
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes128_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CFB,2F7AF90B0C0A420FFD62214EBEFC4CD5
+
+hciElffC9lqjzOx+aBT3DYY0/oZrI0Q34xfQg7IOTUPUAxrrT/UjHlToX56VIbRm
+PH2M5yoF88Ji7BI2V/Y2QRAjAYRFVjZvPO9ke4IGYI8xfnKRivfxLtW/YfaiKnqc
+7VyyO2UI2tYGm27+JJbGLR+GdaHmcnLmencGdS4Hn3KDQ9IK4eLLXrBPWyzGnxEZ
+qA2OWdzqodjppFCjlx892YJUsq+w3BXu5lkPoooTEoxB5RywZfngUY9Y+raN60S6
+zhjkaaJTEqAfnAsdVMUvzpkYpoH5LCO1vl4+XpKdeUu3wJ5p3D9TVc4kt6/V/MeL
+rHJVN8FKJKYddTlaP7xOmh4bivrJao6LzRUdnyxGL6SkVQ4ipitgWcSwFGgRQc1m
+/MzFmTATtC8tocSqXMY8nblp0/sabGhUSTGG+uBGddDr16D/8J5rb8cMCfR0KLPF
+3uwV89PbbqpS73IUKkolRjxslO74TPDT5ds0i+UV+J+AJM+9CnyY7WI3FgMlVvRn
+KwYJuihDzFjozJfe386XWYs2Joa3Eo0vbaVvp4hbHq5Gh7S2iiBpqy2uN0xxuZA9
+QB1XpLd+rOC0y5l1usuVc9kBlGsTiFVyBoZo/pWVlTU3z8Hzgv8p1TAJN6jgqVH7
+oMVgubXsz1XPHrrjjgZEEpxqzXtKJw3DKchGDfAn4VLTSrOINwMC5sR8l30OZVtD
+IdlmftUBhv2AeVUqkLsSMKGdeagfwoqOlfL4FKvSt4n8Vq+Hn9lY/S7n3cjM17YE
+YAgpBjX4PJqXsp8K5KmBHPQMB08jW+NQFABOprdes5bwflrERogdLZmQH4vxqUvs
+DFhHVJxo1wxeRDOftVgtxnmHzU+SaB9MgdWWhC/4pxx5uzqYi0Q2kSOZ27EXZNdh
+MgVX16W6jLUw9zaR1wJIJZU7SmhJOL1fxvt85RytaD28+JvPTNs2ffDpjPu0sXh9
+n0gYiWztuBNUv1m+LMpi1SPtHvtoZLhc++9g4BXoZevtgNl+FqvHs2Ob9w3yXqkT
+lyJQbqju674MaKXDoQ+3+tnXad8MRGCvIgmIUzmMZj3O7QcrBbDY/pbcxoEDOaKI
+SygvYvKfrBIKq6PuGsN1KHSMrjc2A4+wuTYy75xsai9YtwwT1tyIIeCv5NXbbtJq
+vW+nbSNYW+khIicBc+Ye+GFfUh2MXj+iC1lK+5i+1leKo4zLNFDmnXKgZ4jOOPMa
+FMYPZkwANQ6//tyP/qzLWGyBucIC/Ym9hUvi0HlYjjU3Z+Zv92vM+2+li4mtMy7M
+tdcm72bqsT3+1rtJKKRaYG/FiQizOGTDyhgV+JX9MEVwJPa+61V9jwkIPPR6iBrl
+u7NoFfSp666XbD+LurRh82vlS7KYOB2zimHFxI6nOHBsypJynqtgIzLg5N1+LhVz
+t+cxucW9eFvkEEXmjZwofqlxq9BDso587kKY+EpOkXrlnG/ha9XeZcyUipn+jQ0Q
+64Cb7LfvcU5UEXTcMh6BKkoeNP07O1ecpD1LXMGYFn2HsfYHigwwcZ7sm9oCCC9q
+vF/rjXg/oIMagmc6MZOjRE2eT9tpLRAaMynLiln7XS5u+Q8O3RexEw==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes128_ecb.pem b/samples/rsa/openssl_rsa_aes128_ecb.pem
new file mode 100644
index 0000000..b6def08
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes128_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-ECB,3E3ACDA483AAD613760CC55C7DBFE582
+
+PJupElZP0QC92uiYotAm/CG6i8ypU5SXxc3zmrk7sBdxVU9JQXsIE/oIUK40AlFW
+cGuHWxxYkdYNtTpuwG/CVlsrq20YfpxQrl525f4pz8ETWt/P5+aLQ0TemEKr+LVE
+921o6LNstZpftQJbe3yMz0cFTjSfsxsHbadfUZUQzobr1XcbazPyhr5rrSntgIMy
+rJ5M4G6QrOEAIHfVVZ1oizlFnd4vjGOKk1i6APgEEqJTIyFWoCXEzDtaMcl97GEI
+EWGusd8DJrqpJKnohVoTZdOzLrnerJXEUEJ0cz+UjvljAYg2MBSJk5v6HCp8aWcc
+CCoWUbJp2933n4nLBq7EXTVmJ1pwbB4cjNM1oL2BznW/pdznrSRcw8qut35ikEKW
+mB97+IMVr03orl0uFjHBIch6cPLYkXKi5w7CO4vvJeqqPK+mCtckzgIlzsdTL7Pp
+tp+wrMBtG2Ibh2HeJuvvlFCgoYBY482aPu/4NMei2eqfs0p5g0bf67R/BiG2Sxxr
+4o8hmR14v+dzLsQeoKrr3RnMqfmrbqgdkUfgBomlsunHUu9u7jB70TuYsZk/COPn
+SgMM0T1pxEuHdXfyZPSS9u2SFGEhbW4zIuVz79Lo7h3sKdYJqmwmgOk1P3IL/nra
+YpcacWzmV0g/GK8O+2CSGvEh1+m0ffQac1Pd2Abjzg9jghshsBTVTpkcFI0UfkIm
+gpP/hwLONl5a1KJn7u/ltFPdZkJ5CWPe0ZQ1mqjhDaPnc8j7iuFzUilsWITLRof0
+KHUDsAZSV7gZ5G/Lh6DGZdlwfkD4b+2GOPayQ44mr4p2hdOque6Z/LEXtOv+UvvF
+kR9azOu2RXVTiDLL4c/ntltS6laT/nCg0goMs5NAis+3cxKd7Uk/yXBAulwR6wmy
+MIZuSM4gk2pqbt6TJWIfxl4ZtPwp+jYIpMZc47XQ7w5m7YSquJzjilaj+IDVPkhF
+TWTMf+Ucb4duBD39HZjBWAoLkF487M8KDtcxL60uHuhVJsKyYsb8b20ukA++c6aH
+0VqU3NB8VXH7De3pA08G51P+XLurlLUUr118STaEd4r7GR8FddFmSh5x+PSuVXut
+D2p2W7pfvS8OTuaMF0PZo0KkUq/TbTpvMcTax+G0DgGJqFFhqxNur6WoJyYbQE0M
+nX8USnuJhS+BRNPEXc5i14dWmZEeE8i2KGm8RlL3KZfyrpBk2zwnGs+WM8xAlBSY
+KnGO6bLvRaUl+8IT1nKfY30HLr2tX+F0fEM9Tn443VgsXkYnMoaPDU0aW6+J0lLE
+lTeqJn8MPVRbU0Ss/0Q2PQLpayHrR+ly6yxJPOY6Nc1eLkhXoB1DwiGh5Mp7J6+V
+R5UL4nRr40hZy+35sH1lf/+1mY95Rb1hAYP9r5K9dAvqkdUMSPz8rtzb/4gevLi2
+rxB5XyOHM/qZL9ySpJWjFPBwOtJ/EJioRTvnG+/8jdxXWBiGKdkGLKV8k1z7gOee
+ewq2/8n4HnzMm5YKdTesy6LuaO5TaOAUe89Eo/CxPgdM5YnxSxRsxunrPR8JMLYI
+V6xyNRRHLOy2ffGdJZ3nqbSOxCNiHW+Glh5I2jyrKG5Bs0S1jbt3l0hZKWSU8k5k
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes128_ofb.pem b/samples/rsa/openssl_rsa_aes128_ofb.pem
new file mode 100644
index 0000000..2986eb2
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes128_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-OFB,271025C313E6EFC0403320C73382F15B
+
+/L1xK2Hx7pYQBTuhHX1P/mkXqLAlbSSz58hL1E4oxsDJODiVH+ueTSKajA8+tbxG
+eBK4p0s5j1fp7SJ9m4QXBwvhCnis992H9kQws6U9gGFrofrYAniRFhX6yzvm86ee
+deQ2Pfcv+evGRPigkoeRSQGxSa40fJ+5cBs4G22cfrKabaEKxnLtQpqPG17JQ4/f
+LdrHz64IyJTgvV6LCzJxShO7vxwIXaA82HNR6Qp09WUXxLB1/pfQ8oQfZbTUkvWi
+CBdXWT42VZklPl7StNiAN9U85K/USIYkKG47CpJvWMYbWJ3Dt1EFiEFi/wmYTinv
+b2K0xUrVUKxAMfmVtr1wGSJA9P9AT0/sBO2vTn5ibXVVHibtAET+vGXLtpGqf89/
+RmcqNEFYxvLzoTyR2FONtVluAC2yk10cKHY/pzZwQyVfjcgMlbnrZz9Pp1Y6ntR5
+AfXpVR/qyYOaQ8BeMCXkfR79GPyCPV6txy3KE2mbajwamvL7eR0+0R3Q0lhVcWGp
+g91D1nbgVFkHGOugO+2yb8vLq9k7K84Za+TY9NCqCG6g0S46yAgZD2rqrAAO4UIf
+6+nno8TS41W5wmsdEarbRoIg7iIKaPKzEmRRurSdlj/s7MKHgQFoet/OdZuAQkV6
+FumyDmqekmPAgIIJEO2NdrWo87RWKCzc61Yl52qmWsqrJIHrPORMGdjdlLVxXXIE
+XZQot33Rx7/f0VZktYB5fWk08kjWQ0sKTDiHEp8Xobq/RDyMTm9TFIkeFm4rLkl6
+Zt2bzp7ssoKeYuJgpoRzUmGP83wgl+AaJZpupARdz5MlqXd5knuPTETFPaFIf98d
+r/sl/V4E1nh0x83HNOBrLlpKbeWocVV4zv22q4zemALPCOQKUPWulINQWAYiTPDA
+lBQhFRnJXSZYFUqFWpxjp3yIWCvTZd4wgX5IQpaJvG+ehRn0H4FR0hJukMG7Pn5y
+ye0M0XlvVYWfxhLRDK23iNkRzVIbIxZfxqaInpGvatcTHyb2vnVFateSGlXIk0wU
+GxgytnTGW2fZtCDOqeQxCL66nIkpqKhB2hJKaD5WIG7SUikjBblvVcN+gkj9IWML
+7LB7xjE+4cyt27Rt9QHuLchdgSScPnPTZhdX0iK1LVELlJQFx8WPZpfXwpQR/xz8
+tqAKOfyhOX2XxYYOoaNN+ffQ3mEnsVFx2uQOp7PvNjL06XdYP4p/AruzVnbqsDsG
+BIo+oo7PfepNw1jRxcmeoaMotIZ8Feq8H8QEARqQSnzRWAJZhV5D9ztmUtaeqyy4
+QDbgxBxdV0nLAWG7e54FMn5yJfjqq2pkBl69ZvR3N+F+L5/eWlEpalIoq2l8AffY
+gDxlGgp030MAyFYSLJNYj+UUwq8k5INaC0QKjARbBMblf0HOX4U6RBqrpzn2xyvU
+mlM6pTiO+mOpG9WLgQS9XTUk2te8n0vAVUTk4Camj94Vdl8JWFNsfJIgwE59hprg
+a3Pz4FosIcBbj1pYtlA9Lz3kIGe9U3z9rHeQHNxJ8agW8NKGvlzY/YBdb115UhnM
+WOVp5TkpF2MyE+TGWqXzwNo3GutaNVs5YO5nX3Mtx4ClRrsmQYVTMg==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes192_cbc.pem b/samples/rsa/openssl_rsa_aes192_cbc.pem
new file mode 100644
index 0000000..b80686d
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes192_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,51C73DF9487965B976234C88321E3F30
+
+6yLkX7C2XTX5AE6KqWsB2Lmt+TMGsoHIH5BDl+o7Yjx7aBSzB9X9KPTsVoPmTCOg
++yhhV6am/yBImCdyuY8d9Q0A1kPIJTEkshgk5vc2KpW08blLCHSCjokEVbQ4TJDH
+bMtrEBVMU1g9KBTMuBpbu6MLVaFth2GTsqExX2gu7FB5EAKvEGhkmLudo1jKkgvR
+aiiyMd2CH2MTdatZtw5PrJmkhV/6RMZRKP8r9wkez8NN14ehmk5QDY2s/hj5uaEf
+xK0GXY6OcwoRo85PsOYhmOeFDqHKGRo9a0pPBy5ZaV4udj0QZekE1fziOxiPf6K8
+0BL50UUzQBW+3n0dIZbzlOiJQScQkjoxi0kc088FHXHf74VBoJUo6pckAu4OwpXW
+L4XLIGAr2Kv4OMiFSJOcaihyawE312B2URcAzVCO7skhTYHaC0fMYDJCGTc2D9rR
++V5tVfT1dG4xdB+p/b9TQyAu8PE10jT+tVNJqGsZRI8I3iOtyWsBcn4sQInpYFYU
+R/v2tgG4hDdq1beEY5N/ZaLsoSyFYZmwbzB+BVhPg0W/9s91/nYAQgOL6XrExQjF
+lZxS28ujAq1LDNzg0NDA2KsDGJF2TuST2stnxyvf23h8+KV2nZLOZXjhlVl/Nr5O
+WPm3gCmuPf8F6FPqM+zI4YBBRtvLRkXafUNuvc7PYVNiaPyuMh7I7U1EUUzTpkqi
+OI/YD4xv6DpDand/WEtLHaYfVYU6PAapLV0T28BoFITp/qxHYYnXVfhn4htSgiwW
+R1btcxWyNjsIedjb1LJ2EwEfuXqZmzDz51uDLBq3XQ/dbvDkDzfZR3O1KGaACxAT
+tAeAdnTnAVliWYQiJ7BHn4LTJZ0ERGL/R1xpQs4quki4WHtEBRRzP6BbmUYYhigO
+QwvTK9darP1Ev7miF5BkRnrzWqCQHNTlDB3i/RzIfIDChQbSZtrpZH/V/quPuPlO
+1353Q6D221UiChhw0+8GmIszbLwBkDq+Zr7/poUBAqHmTaA3LeiahACM55ATbg1+
+FKf0nvUL0SaEBAqFxSdQ1mnW83VCMlCE7Luh49BDl4/nufCdF+iv3cYRW2SDHPrU
+HELYYLz+b4QLl+XO2SgUYEkU9s1Z+eCKcVUXGzz6vZUsA8UwvYIy8b/1cz4Y5sZ4
+MLpEXnQRMwAjArh4fvmosAG+diC18H2asLWpUS5HBBrSb8lAqKPLl+n72SlZkFjE
+WP+qq3koz3EyJsjwH2qbpx5BLhTPcEVHl3DZ1eOQmCXcpSm/cqKp2MKQFubCC4rr
+nphTD8uYKCP3mJXB8vqIIO9ho7+GVlCHJdZGu+3bw1L89O6ZG6WClbY56eGz2xUn
+DBmikb9sppeYSs0eX+yQ9kjQRf/BGnRab2dSTGtDT7jp6cL+zWUUOawLHWS72XtN
+3XYSEvvAWPygwbBuAuw17pwPPmTXduRiJosR1lRk28FGsMwzbj4byXm77IO3vD80
+cyrAQ/bmSpvlmYEHvmRn9N7QT7SFANY4a03aBK2iuqZQUz/zeo3eyrJudBXIiwUz
+/ZRteBa6SQagqDsmfeuGCjgTFGVnutCokh9lajm9BZ1pZtCmHEDd7yz4Odx5CmxG
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes192_cfb.pem b/samples/rsa/openssl_rsa_aes192_cfb.pem
new file mode 100644
index 0000000..00cbae5
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes192_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CFB,58F8574921C585278A50F7A2EA529595
+
+RQtPMTKDNttPq1R+DiwHrEK33FOfxK1Cst5x1jrDhXe5MObLhqbz4Ft2idjtG/vC
+pemznnZqQYKsuJl/Th6Ydsthkg7HH1pYLRstc/tWQTESa0RseHDtdw3e/Wxhm6DH
+pSqymOfRq8R7PQKPxboj9fjxeooWlA+RQxGdyRJ6gki6PljOD29C2hxZV4HuL2II
+tUn/cdzaGu6bCvpFDvDuFja3TRtIrHSbCq01uZg6XrFui7BuwJxxR5lERsauJ6RX
++lAvhwXqN4nsEQefvZc/GeTFzklsoJ+c3HJy7pN15nyfwNzmmH5EK7C4CdBJQymv
+MRwe9hY/LGXB5IFEgXvop9bh2qYk9tb/zb8aAHcLS9rwFsGOo+5+Yib3ds4GC5fx
+ILKH234g+hkhutao530kmWXFf7qup8lvTlBZueAWcIFdmBCsWjm8ejxQUZaPCqEY
+sZ1UMDw1HPX7/4TXdVNZWrxHisv0VWnhwJNflEcI/k/GR0/qUgkHnUPycWTtg0W2
+7ivs7D0EkIJy2OyFj5swWs+eqhsSDmd0BgGL0VduLB0voi1eU908Af3PllsTwf4D
+UaLFvOkllIbul+YweImT9TinmkWIFMZuNDR/PHjpbLN/39YkvSub6oS4LOgKEu1Y
+Xr779QOZHMcIP+PXoaxqOWls9hgI6M3PAH+gAjwF77OWIQIh8JZCibR6HWYcr/qo
+iFTzJGNN7P06s3IOek+YoHG1c0GoPsNungPOzthNnaAUcRyvZ1Yg8cy/nhrA8Eeo
+A4G/I241jr/Ex5jooykpeotV1/AMIF7qxFeTARQgObRi/fiR0r9rjaSMbOt4PlRv
+Ln0ZBqedtkkRBPRGO0VViSbUAUOq0oSb98FWqPFpcFl8tXRyqe9m/W2zACczZplz
+OySvRuASdKYpGk4DmMlQtS8wjzMYTesBx68OiZfw9W2nkH+Xapc4cH8hyb3+aXXb
+b53nbp59+mx4UwPOcrdzVHdKhDT3BjYrJTv9kHAY8yA4Nr08ZsO5tOeI7vF+bUKx
+kWu4AIEccB030iu87/xHXUEOBzsV6HzzT1TrZ5GKSh43vhRwoasYON2xlO6RuKCD
+Yv6GbcPd4lv2mv4lAaDXk5IThABHUL8yhqfwru4L43av5AwdslRKIvBM7UWrlXFe
+A/Hipy6jjcusGiOyH7WfWBFV2/f6NtX6lGuna03F/yMZcHI/HEK5RyhqOYOmcxfw
+A1eGKSqOnq9IJ6vXnF8PuRYKB9i8Ha0z5JmWkh/dX5dhTzwH6wOz4+bLgkgXBdhY
+jptSs5zsvrxGiLCbENPTjArsBbT5NISh+VTrrUtmA5BLPWx6d4NNJ5eBXTnpOIJr
+rxA0halZtFYKj0mp1ZgnVylHC45QDiwzDnhXra83RVrcgQjcX4npjKOaYZRQ5cKR
+2F1QdvoLvE9YqhjH0QFQWMWfvmLHGIDIDkSB6EyFsgzWdv6kIaiYsmdir5FzE8c5
+SvHvu28j1X4OL62AquOFKMXQVns1/jLp0KERx1EhrQChHUxpA/cbqNJbhjHoRQK6
+0zXWP9gNlyrSIKY4egyQmjcTDvNXVcSDu2o7EfnprNCYirFgsAbw5A==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes192_ecb.pem b/samples/rsa/openssl_rsa_aes192_ecb.pem
new file mode 100644
index 0000000..106704e
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes192_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-ECB,A3A4C4B92548B906A635B84B3D67591E
+
+E4I7KvCs0qknDw8D9ISQev5oQCNiHskfB/SvuKJ/qJoJP52qk+ajN9pNMp+011R+
+MRaMlK7tANTrQ0L/Yc6QNUZW2aHyiex0aoC4ien4ojgvqHfaP12dMxFhOoLctN+N
+zrAPSuQg2OEBiWxEoDqpgA7FTUbxPiJ3QdtwwOXS5kqAKIEIoNnCPCL+45uKBrP8
+encSI+nrZIXLFqGEukKZuFH9qzdF2leOKSmEW1kmwxMOfQLMVQMJyVzd19cCxU/1
+FZtPRRIzFlx4PlNYLKDpypSUavgo5V/o3UHk6vbP/Wd+Wy1ERwNliV7CTCCpOrBH
+qJezvhkbktiHQQ7+5zU0jsTzTlZcxATdm2ktyfEa5GKrCNfrmUYNwNSi8DC2Dn1x
+4z9r6OfKV3dKcSkgmFS3ZI97ZhrnMqpvo0h1kg8tuiboI9pPWp8OsLIvw5+jz707
+GLsl6hI0EX61YFc7bqeetnObgiaJMJxQJXHi0U+Z01GjZ+qgGb6USmQ1D8r34nuj
+4l88VYW4jBhxa/IFpzUoxIioKG58xQT+OK2Fi7BF/OJLQpj+3RA3YLqry0D+AOT+
+f+nDJepwrQ/CZtoQl53ssct+mDY0D1IU6u7ah9WdIuuptV7+WxutFfDpXsmErKcZ
+eILXaH5zK9iNVnVNQDmnVacjQt0x0Rm28wrjI5N7M8jGWKWi9PMLElx3BTo9EbON
+pJ6x6xshjmdCR3gOLo86CZGkoUM1eNGhJuihrl6HelcZxeFnuiNYnLb5hIaqDd1v
+NpFUQBRC6Q3jz85zIvVsiN2vIyak2OGDRs7r5dqb1x9QVz5tMjxuKe3t+rfX1FN1
+vCusACQQzOl6NdTgmm5Of+pMniOL/kRF78e7zva8vM1Qf31/z8wtq3gemt+pZstW
+WV/kRhIvY/p2Nm41TtltlctThbYquFTEy8gxhB/Cot2k7Z494+8UBVIn7SjsdDpU
+X+N24itXM9/sd1LHrXBSbBT5PzSBJFC5MS4Nt6qpvSKIRbyWINjUoTvbbUwoCo6g
+soYBPJR9KeAcQ8YdBOEXtFScq7c5ZPOGCj/+3p++Pk7yMmlxNPvs6HLjdHchjAYz
+jycK/uWYNLOwKS/AMxwi4R3i45pPgIRuwGdRyi17Z8kOKATdyQwScbPOShW9/066
+OA0rEORx3C9gMoKa9QYo3O9YLjA7NS1ERSY9c3X9anSgR7eSs+DLRwFiB3EHoCba
+ULqd3n7qBKgkQpVF60p34yKb3K8o5s0cIE7oAm3VdoI/O/RSs87rDmUbpuYzAA24
+mXRwBvPpwEhke5PoPeFIYmcWa4wUZOJWuF78U/tZw047vcLKgr60Z1s+DlQJvFXI
+tXkV3qS45f9UDaWQ15YNev9fq+x/1JDO1LjQ9AHANBjRQSzE9K6YpyIw/SZlbo1O
+xuFrE077EL3hrRNh00O2rtcrK53mAOKMX9D5xifIcN4/uD9AdwU24YvC44gij47m
+hSg5wz0RokMNGLKTXaJxJGs4+ZK8JWQs/Kf/V9j6j/i4iDWuy5Ra7+/dIU/Qy1ZW
+cc8Uo2ji4i2z+QyzbpbR/jBqO++lcV2byEVDy8Xp/0X2G9mY0ymIbm7ATTlzE2/b
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes192_ofb.pem b/samples/rsa/openssl_rsa_aes192_ofb.pem
new file mode 100644
index 0000000..88dd91a
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes192_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-OFB,9797077D8AC3052C37DE4D719CA8FC00
+
+SU3g1XmkcVhlJpQSWXdeHcHI8IQCQBg0oenT/35NKgWnFBlysqwGwl/pwgdDBmm4
+jLsPaE5Vanm4aqWv9DNhItOQokIbIkxF6qKeV3wNSNbTsSaG2LNphwMiLs9rw4G9
+3aFV+0THPLAy3BDTsB3NPuRqlOSVcwVrfaeMXQGhCOPGmsGDeczai1xH7eq1C1no
+KUqNMGdf8g1NuCmQnvswuTF9BCi6rIO0JRqLPTxoz/1emKfHhJFefpSj88zg3ucm
+cz6ZOAlsmWm1MQrktXd+odzpmjHtd1vNsgr4GSYUeVxxWQX4o8pVFqWqiQXii+HS
+ubtMARXAuFIGoM1RCMN8o7sJG00RbG7zNxfhHqe4wSkKgx3qEuusUDewXkDeYhHJ
+HGQCD1epByGHCZkLwBntccOqbCQoSNB0/PcFU6vJrtgVFl8N4VsNMRuLj2ZJ7uuL
+/EZ3qkLTk/Ek68++m2dtAdyj2KF1O4z2SFROSh7MCqWl2rYh4zZcBtGEfmQe5Pwz
++kPycc76ayzHO8Bjg6rl/16Ua5Wx7d6vy4Hg7JYb5eDmj2UGJ8p/z83KBdQnb1ku
+84ZjpYgmtjZ1vY8Z5iZqfZro9JBjWM4wFZIKNXcBniC7kBV9fRC5nzpjs6qWTPRb
+bd7PLMuyRZz9PO6cRuhqYlP5tYSGYYVhAMVutIqSrQVRDV8AnmblfPiOtT5lHC48
+GR/xPTIFxxVqsDmeyBzyXn9gzAJKgjTVCXNksXojM/ZMfDDvAF6m/Ntz/izp2CbI
+f2lcHgsm7SwVn2fvHikAugA9B6ixMCXygO0L5OEUDJW1e1fB7FMasjrwRorDsxsj
+JUNDW0KhUXWt/U8lNyfRm3oNUjQQU3x1iEymjQZV10ZO9DTn28fZOF70moUWnl0y
+ffELY1vLtLNP7Y5tcGNtJARSGnMUW99P7OKpLNXkhL8zE3DGEL1N+gDS1n81kzTH
+7hPjM6yR6gJQVsQrQmXrEpIlHQeGA99LYchzyVog14qMhvQItDlCsr5UIPwVwhMP
+LTA2LITZOYieRAqrv3vn+yFHYG4k9/C/xHwKHE/4pDw8bLn1o8thGv5ZW4yDsHGx
+n6F6vqJrkPW6vXkmwcgO5jK8JBbEpyzAPc6aSsibH3JF0ufsfs2hQ4bwb96OmU6v
+mukMLjQoi3BJC70Op1bpe7wtCELJw1oFvbZDoXLYsa3c06HK1M4rmzJQTIEBjqxd
+vs3g4L4CQ4RHAzlkjLrCF+wcBHt33586bDrt03qBEA7GSyAUu1NSM3UKjjM0OydG
+u8echgFIz6XetqDICHdN0r3ZWyICM/FgnVQhs39fCgafVJsy9C4p5jByUuDPvebP
++gvvVqkb+DGwfkKT3RUFAcYiNHdtIob3kmp8OJKTFk/nwdUwqUTEu3VFCmWog9ps
+oe/0KOL7j1Kn1xEFkOt5MdSFCcpbsYjQNi7F1gWAr1vMXDDPsSizsniGSvXZIYBt
+Pk5AH4MflqbHFofWClhGczSLi0FRiVPqWyudoU7LOesQhhN74Dn5IzkeAGtDL8r6
+4vC+G61PZdFXhLXQfOEL99hgJ2mjQP4rVqwdz143YE4/CUHmpq6d8g==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes256_cbc.pem b/samples/rsa/openssl_rsa_aes256_cbc.pem
new file mode 100644
index 0000000..7b03203
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes256_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,1876F5A50C9046D504D47B2BF8951875
+
+BAPOppBjFxMrMU+NI00PbmXXutKdPAiP+If8JqX5xGQDB9bSt5Q9R2QkaMx8Z94f
+trVbp82iERyPYnwcnA1Av+pcZhKi/mYFgDBPP+dDLp8qKRFAWil0zc0U2jkfo0U7
+v8cpO5+oipkJ9RtjaTg3/XmrwCUFZH4KA6G+SUFc4Oxj8/dzQ5YUDtJ5iyArRlnr
+v4nsvP4OvsI5UFYwp/T97ks0KSmo6YLMpJwUBwcleX2vOhX8fd3thk9I+EbVVt/f
++JztCTwr4EsLxWe4XVmit9AKfLU0AhmcA20j2YXE1VFvRJdyr+gOGPD2SDoRgiZH
+rRBhfi7cou3QmZ5d43jFYoYCBc98blEV07umH0DXMTL8XSrfWNIjZf8uQR3+ZbHt
+W60jVdhOCEb40KoRTHQAMBQdgVVkrbXCFyc9NeVzzhPqyKXElGxLBjRB9u0h15DV
+WCJUdc9UGuHzFpVFzpEaehdm/7vl+SZXUzAOgAQDtL+ATsvZglyMx5y2UA+5L1eZ
+grA6e3tQFdBcv8w+WgYW37oAY2VkHKjoHs1TnR8z1t+OpVovnpcklawybh9Avv5J
+kXyZGc+lbbb2gvUw33VeYR8yIE4zBoePuhTFM3K4NfkBbKavBBXMjQlsdRzlt48r
+RqdFnpYc1XB4ZLP2VparhG+Q1UueVML8uBcd5F6X/0u9n78LfIITwRUpVoaLXRzs
+94Us0pbzWFDxqxtqKPZHLAVJOYvEOwZD5Haw/bwho73EHEx38MY7mk9T5PonsBko
+7Op6aEmKK1qfpJ1aPvy74UmIlVDHu5WEMkYx7nQL67gnFXHY0yKjmP6dc2y3+nfR
+qNK95RTaS9VbACRS+re+P9+Z3aAsQGvj3MA+4Q+qlscUmb8uk+M7tg9ADk0VSe1u
+Ts2x7UZroI61c+WzgsQzMAwm2QLPoKQcvv2b+iGD82enAtleTTHL9rkoS+KmNNU6
+hWL+AJ7HP9s/5+FJ7/4CD84pcLECXQ+f185vvE42TfdZmoq6NgSKrGVZPLxYnyjO
+qa2sTRzImZrXPtsnFEL9OBflWA+ZHaAGo4HJNxZW4Z90HJlAZN3isSZnE3jPToKP
+YFdHsPv5m/KpNa5luh4L3K41QWzLmPlRR0aygWM7/0fYkgxI8PnBeCp4OjoK6qHx
+VYTWMKJQTLyji3YwMr4CufFAVty3InUZzm+ALMFHqEORB6JqPTR9mtnR145FHtxE
+1z0LnEoDFEdGuLjtC57yR+lYS/vgMbtj4EqQ2zK93JaXvI2HxxOiZCZEDww262Bx
+QZo0vBoAd5vkMKmz5eAMpRVkguF1wN1RPvao7I2auJIHp/3zoaUowpZgtbmDHZFA
+Kddfc927GQRxtUH3QQVe1R6FFAa7JBHNeJsBvZu3bj3l/7BATzcne5OPhjZ/t8Sl
+hMqEBZuo0svrEc0w+e8dpbPEjuj8UwBmHYZWlALby5N+YJ1NEtLYmyHe2PFNXwK0
+2fo45CCSyl7YJrHD1ONJ0M804ML4nMwmYq6fOAaV9ufQBFqQQj/hyyE93blB8f2E
+I8LMN/SUKN06YU0nErN0PRdm7CkrS+kutn/Pz2H4oSbUZ67z4Ee1tpnVQjoDYdQU
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes256_cfb.pem b/samples/rsa/openssl_rsa_aes256_cfb.pem
new file mode 100644
index 0000000..a616b68
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes256_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CFB,37639E4753C0E4CD43EEDEEA18AA66D7
+
+HKuYoKfUqTRf4sW12EzTuIFK5J1FkeJAD+ajYnKeKYneNiDbmDlQv0kIk12qBv6l
+LA0oBH62QKjUDKi/sg8NAO5CqYkN2ZB0gQurTgGT/jrvMkkkkwE0x1n69bGNScCN
+mkqMnAnjQqbo1xERzwqX5OWNTTb4iDLiPyjiUlQDONl14pe4x6zGpVziCVCQh8Q6
+rAPDryZBg/wQtPXNhNpk8MiTiSwe03wq10QP6W5TmUIKp3kD4OVfBxpW1N4znyIu
+unJDVcRdBf6XA+aL7plAsETL6F9Tx3Mxm5GaeaJcSOWWzKMvqYhAcEYwM01lx0w8
+LMMRUogny67ZqaLywXZWH6FCJGCnJK5oaJE+jlnKZ6xhbwAxMyxWRCZC9pF22ocI
+3IY602+shDOWZQDoihhddwPJejh+o3mVFEglco3YEByL7Cy6GvqxhctEEH7uKvlQ
+gXGb7srmOpeHHfP76N9afF2hn0mqyToakdZqgnlgT2jm4UDHJ1vQ+onIksV56I07
+tVMEmPhXQCIHhfKdzEgI/v8CiLL3W/g8r+20/5qyKCL5vPBLAxmRudYKbGkhm5pq
+GkzaSp1cKe4ipUfVc5OEUikOMCuadal0TUQZ+h658aBCxLWHNPdZCzNdY/bZLN9z
+XPhAzml/H6VOZyIxb9hm+FNESvqNKdlU2NaE7HW0ILKaDif7gsZhvogP4qNDp2P9
+xPANQh9UxpA16AUTUNOqk78t9aQVpbjZfAeGmcw6AxJ77uK649JgkEnKqcuxcDSi
+zn/8NGeaKow/bTW6jJJj7b4cMys32uxRjeeeClC0moQiy28OIJpRRCRJIs7Muka+
+dMBoNyftBnCONH+oqj+F5au3QPMwKH4v/4VpO3hcByXcqxegH+BPEZzzYJ1OnI3u
+dh9VlpTdC/CD+Gn3ZRqYbguSaqow1ZF+nlpD0xcs0IQjNEe2BVR7CULUFVXIgF44
+pTv96/LvbG1J9b0VuBr+iIp30FG9azd2xyn4O3lW2xk1uzvo/Wf1vDGvT6AYyXNG
+DQS1dGtIm3+sy975sNTlba5gWgh0YNHjeiQq19I6ZzLFhkvLKfh7zpx+R53YcqSY
+lXj62N0u2s4KUygqg14oiIUoEnNr+n7Pq0es/gYs34mY/KvlqA8Prax91BaoqqLW
+qHN5bEv90KdKaJlvdWsCUjA3wReeaQa+U737GMXaON9/oOJ02bWC8/OIzUPgfGRH
+v/8YL7kMnTd+Col0f+XxnebWSfJsAzT7mjfly+An9EjccTeiOon8submd+L8WySK
+lVvWzBD3l4HKjQkr/3/YtmpuymVZyeTzngVuSdw+iXWPmOOuXHyjyD2Htn5iNWch
+Zlw37a5sHhiFtpNZtOnhpmDbX9sgt68KJMB/E9Mh3JuWCaKZZ3Cv/22KA4KQRlNB
+FSvDDKJBrM1m599A6GPJisR+iC7g7asJQ8hI1OqaY69v8nP0Fo+Qk8+Ac1L/n/Vm
+RjksignkKjvqgWENNn5Bf9A9+zZrLLu9wJJLae7wIiw4UgsNob68sGjWdLyg+tab
+QTxd15H5VUIuD6pkeAI2qC+0sSw9V6LKm6pmEIIbp188CzApcsGBXA==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes256_ecb.pem b/samples/rsa/openssl_rsa_aes256_ecb.pem
new file mode 100644
index 0000000..f679d6d
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes256_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-ECB,C5DF56EE3F83A1F8C1AC805EA73D4D24
+
+ac22chm8+bxXpppAKfsrFJwCY0S4VPnXmFRqlAPZRuqBH9ylFcG+F8TuHdIsLeof
+q6s8yxkXa8y+/3hyqIZeMwN5Ai1Cas4P1iMwEtMUCMeaip5t0nf+yeCyx433hDSW
+dVnsdeuiFCiBUPUXfp6dCGO9kOLUEwu4wM4lIJkJ4QVyauO0/DwObQ6s6xEMFvQH
+GF1AFFTfW39CpZuS1rguG4hTxW6aNxjEaSKHJnzWu+kduMLJEaLUiL5+i/tUw937
+V8DhGdWU//1Q6KKLMr+5w0k9i/FhVxAGJZoZ5j79ToYORGr4jpkDPOvHaCydM6Iv
+JH0epC0wfG8L/dArNGLEftTpVVlvqHMpAlc0Rgvn+LtqstfyWFXqbQ90NBxC5Fs5
+xiGxKFGpkX4stoKIaOvFVw/hoCI/oxs8Eihz8u4QjBsl/3TdYQ6AUyfBGEWImy/y
+hh+QKCVOfzAmVGcffXYf7fvZETVgpo6tynxKVlSRXO9ZuzANJCC8jkUEOjc7jSKl
+jyMKQMNnQxyplgaFxnWIfs/snvlLQW8DlpMPH8xSkHkUgLKMWrSLB9Cisv0N7V5t
+Zl7Xxm3tOteLG73JxJKJkSZ9djlhkPvlvS///mvLQc6jse8EzY8peQMI1pYQu87U
+CvHVDOYn56SFVJmo2koER8FG8a1910NqdCKpNkzjqTl1Qbz7Z2VwghTslM7sUA2L
+AJP6PgdCkiGbi3oU8moPy3Nyg908j/17Bj9VyCXiegMAOxI6Kefim5Nn/sq+2/7Z
+MHIucQX6ka8KjEp9jvf7jvNC5WYxJkKIl+yzwAzqRQ395Lp1sun6jPfngnPQmkXY
+toeOeFvKlxaQu3QgNY7Hq9wwGbK/uo+rLK+Jbnt/75w7x5aGHQF3kf36epr3O/0l
+MyZPPx6sLblYcNQhBV8rnSey1WeO6105h61xTXdKV6To/m+RDZYvt+qs4z5SNQlj
+oKTezoQUh4J4QMg0EPhghyCS+/+cPMdnVnwX6Ds6nD2feX2CpN27xieGEp5ZhioG
+qWi6/59B38kBW2e60eQyL5f53bhWvywBg3HeUsXCD0ujtXBqPMuNnO6FU+/5Ohg5
+BAJ/bXaWiOkobmppBeaViidGv3NytL48ZIuQ1PZsYQajFb/k1SkyLebmeC2NYdO8
+VBWxAz5glgIKP11K9DJMD3n6PVl+ZyvlYZUGXjfUhOxHKVmNDHv2o5Pv8jf3WEhs
+yuWEoRECvfNlkDrmda0MxMhEYjeTysbxeX6fvwD2InzuFKhfzwh49p5LdZLurEm8
+DI8KBIXUx8g3svArJRvbVLyW0deMlXBY7h8Yc/2y7c5qBwfYrYhgazxVBfRqS3lt
+EsO2sa0V0GaGhPh7LUt+n1qDDYmaOfxOdpZoSLm/surciEQIQVNXt264YuFJS+ot
+vHWWVHzS1AZIgizu7NHRVeUmu4XEgT8vRsJYeogyG9o3U27L/lF1L5ysvYQjtvkd
+q5idZxCnY5RctE2wa5gjxPjmgbt1sUN23KOiPyz2cmXGBh/dwqEhIV6j7+WeS4/r
+SFBZBeGRHi8tACblT/6G9UB6FcycyD3hf317Zb3jXZLve17ozwRZRQ8aBkz07+iy
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_aes256_ofb.pem b/samples/rsa/openssl_rsa_aes256_ofb.pem
new file mode 100644
index 0000000..34ed53b
--- /dev/null
+++ b/samples/rsa/openssl_rsa_aes256_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-OFB,E6AB8D4FECB44185E26505049A97B0D6
+
+Fg8Nq9CxyVZmBNEiN9vBI+gsZL4lvWqCPaR5E+Po7acLxYGos4zIcmLCBa2X8lvM
+UInn087k98OAClm+0PvhZ64/AdDE952UclD/xiNvQCH25HGQy7wk/BxuOM5/FT0S
+rlV6RGMibelHpnv+yploYoHD8CSo77N4RHdEuepPwod2fGTKu5Cbbt1FBGU5LXWJ
+BrDMOlSN8P/rD5ePADhDsYnh86g4cBVHTb3MkrteLa0m1Szt47E6d3s+Ued8Cg5S
+7tiJOTFnXkmG87LsLZ0HDp6yML3g2gpTL/1Zhn9zS9lZc3cnkBfRJmttLBPjVCiB
+mStjlXnuJTDBdgQhJPJ4+2xJiR/ucFbCnUF/VICsl0hdz2Hd0PCOdhzj6U3jbRk4
+uI2sv5TV/E+e/Ppvdh2W8LISSBdIwp9CJf3se8RFz1dUXwTMGM50LKr/dpvy3T4m
+NMO/Cf/LyA7HBFJxjqf++wi5LPDXzROm1QHncvXNUjypNPND3RhP53pMeQ/Ffd04
+dw29zrmbyQKQOOac5Ss9Lj33Q/WzBgw5UxxxMxwRVDyfFpdz6JRfMrnj2c97auLI
+RI3euI9A9yRNxneBKTobS0EjYyqAiU6b5MbNwrybqvavbA/+ZMEg9Ylg7vtBOXpW
+YLLYFYPhWNEambOfNJi4tHcX8znGACxO/W7v3Ir+QFhw2IzSvntcMODKGaNKMGys
+HJ6mqKbmYidjhtKen1qHB5u2bukaGWUj2kjkv7jjuDK3ExsvB2PjEV5d0foPEwW7
+9QQeKc5pY4tOxFVA4qCq1tTzUhWr0mBkPhnFjc7XOLbu0sHYdr6ArZ3SadaNT12w
+LG2yg5r8BgmaUVTTQAzIiHhAQYZoCHAq+ohNocIikIh7lPE58DL2GPpEdXZsgzTi
+T+EUSkSw4VtIMmnWw5GNE3zCOxvx5qzhKiXVcnB+2+IF3nlHkQqFXcYNGhezZjnJ
+4FlR4FPzumRmMj1x0zmdbp7eTFpipUpKqJtC8iuea29pEl8opXDNhvmpmrT4/429
+7x8eJOjZhm8WL1dVpV2/Ikc9boEsYzHcBkY7kuaTqT8I9tdQ08ODo8UE5aReaFuZ
+vlBY4J+A4lltQ7qQ+sAk6gUMvlY8h/9L9gZiGbLe438Ndizskuwy+jAZAEx0f0cK
+YnTsZxBHPkWQXgBHMhe3BAAA+CZaXPps0SjD0yMQs7lkAgag6zBXW2vqttoJLU9R
+f6uP+BLwZCFDF1NtkROLV1oROnaGvMbHWcar2tw5qNe3BAsPQqGk8XnqwILz4IwX
+MN6QrjzbBC2jcL5jsxPZ/Tis9+wfI3t1Ke0EljYqA9RVWuC2KtRK+X3xOK6tWEK+
+QlagHRDI0Z0u0slCLjpB/ev9Ajqwlr0h25T5ucdsLd3FFEKZbzspdfsJuOXPM5la
+Uv9gpYIcuFrKcVbvuBPzt6NX/rp9gozZv7ZOnujjor6RDorHsfbgbEfcerydvJGu
+PRk788TkAB0LOE2wD2J2UO8+Ufp1qK9GWmtr0WFCazqFfeiorTh71iS7pwUt08so
+0BRkqfrfP6pXEcnh4p+LKh+dnbgIBD+KH0qHsyc0ci43byoOSDDHnQ==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_blowfish_cbc.pem b/samples/rsa/openssl_rsa_blowfish_cbc.pem
new file mode 100644
index 0000000..e3f6e24
--- /dev/null
+++ b/samples/rsa/openssl_rsa_blowfish_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CBC,E59962EBB3DD3C74
+
+1FpslA4+P9E8HcUUGpkIMWeZYV2XxCgOiSgCe2NAUiutcRkVAg9nPbzwnsQTbckx
+d5uOE/w53BURpxPkz3nNcike0sr3fa/MzaoRUDo0P4MU5bmAihjnZqhRllqvw4Zt
+BsyxjHVn54RaqZC4RNQUqwIHYZwJmHUi7Zk3+Sw7fivMZBr/AWqa66I2hk20+obB
+y5ubRjtjw6uaciPLIoMZksxoEwi5xv4KnQHAQnaihQ558RPpUwweqHXyOZPEC1Kx
+gNQPrTGc4Zm+CKqR4CceACSYzcYtechZpSQqn61emmtyhowDqXpqqjG2nimNihcI
+hbp5O+O3fKZFkJllB20xuaj0rK1NFF4aLiS3BK6aWeCZ6aXFawSvbQb6vGx+pQmP
+eQemfllRXXkT43CHUmMTaf6gKnz5DaxDBqdVP73dBa6UoWnxTrZcUNKiPUCvB3g1
+ciJePjBnsijb2Bh6jIwr7yghIbS65AYE/0V+5Duw360Fa1OqJkMuz5pKeJIUcYEZ
+3yuI22CZeorkvymKhrt1hUn5xLIKRZkWg7UbXG1WXCrGtPdJ+CxnwupHMdL8iMLi
+1haNeJ3E/PeMjehQRzSEEFwDljn/b1JtoWsEwnQPTPKY3505OWIhYRwRXLEo5n1y
+QEfktZ9UtIsJcIpfi7hMvbpp/7Njlu2MJKZ/1ZtvwVLoaXFTSivqcAkDdP7u5enb
+OJ4EaDWrRXS3Zj31fpYTV5p0fRaejFPevRNnYvMLRiSoFobd5MUrKjxpxPRCLiW7
+24BF9QY7C2Nso9yR7gNkzLw5x/725lGxa2ZD16nJmiECOaEB8ORVlilmjX2OQi66
+hpGVtjHMaoGr5IvBrtc7Q9aM0bdoFZD5I2mOm0hniNHG9es2IMByHWRAQFzOOLGH
+IFoIyW3OIuzK3cz8lMLsh/Hlbzo/3bpX0rbrn1XZULWAJ1oNzRJRi6a3Sw2YoIMh
+656IJB/fGRbG9CMVMl0T7onDUhZYLA/mV+xy2CjkQdPBjFpQUTn5YHu6zMU7gejo
+YSV/4esuUfhogLiqw7sPuCDqLL2UftN29xloQDTY6MlrkFb9jCciAwn02DAmsN4h
+7Utus3Z2N7gJnxt1dRecqr2o/agIINm3tMh0LK3/CydmlthZQNpsxMD7IqaWFfQR
+Uq7zQUfYZi0l2J6iy6FUHUokskqwgiNhMP2Z+uZ1xHUnoP7E0IZMHnVWEKBIQZ0d
+ddDucux1jOBlMwLqom3jYPjPkxoeSU2E0ozVNSOqsPnoKkz2qKnEHhea2sAPg4eX
+lsZ9ENQyQMZVapjic41BU/32pbrE/+JkK2Cc+dcLlrnHo+JpFeTdbleJhZ2JgXHW
+8r04vZHA7tQOc0KNR522Niu7dvOW302lwmfp7D5xfon62/AxVhos1DSZuNpVClm3
+V59lqeCBDm1yJwdM/946Eq45YJiTNTzYsPPFl25KNv+3+GKkhZ20GuLiaqprel3S
+MC5XbMJg4nc0LiAfDT/q1jO/EKZ5LzRRtkVvx1D8To6DAptyFoJSMKyFu79tQdfN
+371+sXEX1VjpEGxO2t/DUmuERIBdc9X7rPNOXSl31QxsXy4s73zcAhI94X8xrqYZ
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_blowfish_cfb.pem b/samples/rsa/openssl_rsa_blowfish_cfb.pem
new file mode 100644
index 0000000..b3581da
--- /dev/null
+++ b/samples/rsa/openssl_rsa_blowfish_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CFB,A6C793D28C38F56A
+
+sjmmZGwl3qF65MFuXEtiTkltbaXuionUsMtzc/XzyPPaIxcdl/03iR5Fix0hTY2Y
+/W9BntQGcycH7uNcoYwOUScTRr2BJncyoDXZaUx/WOQ6cDHuhRWWwpLpmitfsn1B
+SRvLdKddL1GE2nfG2xhCdN4N7pVPUwIahHye1AkaSJ4gur8tU0++mJQTjDo63xKB
+oTh3mZB0OCnelXtoYFKGFXNh5ouAPZgcE84breDJBoGReH6f4elkigtSx/J2QhgN
+vXERboYz/HHhHSRCtMSp0qLEQo+uLcFxZcSMQE12eglOOucht877V5n5RMLFT/3c
+DeZdg6D1b52UzaSjTvLm/jJCdkYqZf4SFuBgLHF/rEALQ1vBqDiKQ7QxuWz5ApPm
+P0ntscETngWuJ2g2M1EoxGehwNiJJEslYE/CB0Aky1XeUmUAUm++Q3QVfUA3G3C7
+pP7whQSr1Y7gL44EmttFCX+dX8GWXuZDXa399wijphVw+6bl0gp/hWRWriTern1D
++/4S78ddrci4slA+/Kkq423wjLNGZtOoy9cXRmFdbQlMfVaeu5U7LmrTQRrgGVM6
+GQjgNanXYhkCNubQ+v2Q6FflAdri8Ac8ZvFXxSIGZ3JG14cm072vOdp0/rCNkzSb
+fmtyzXUGgNgKzfp/GFvIXD04lLfeipzlUhNvDK8AKUNIctrMHZegpbfSm6HD6BiV
+rUFNLvr58WDK0eLeRxg4pFTCf9QXr9Q1v4MWehkn+LOTconhJtRictdlj+G2ymOQ
+LYgSRPPdXVNxlBI6u5WRtMxzZM6G3N8jkEvFfFsyeMtE+R0OsXiIwvGzdksnI/1F
+deQJzav9uMBj4A0bJuMQ3Ls8ydZNFU2RDofSU84bP/g6TzU8MpT7QXQXPD2jKdLp
+JouxtbRw+YY+9p0sk5PFYxti+T17jZN//pqiBrZUzvspwr5sWoa8BbA3bWE2gnXT
+cmx98wREJ3wWRx+t0k44084kD5/cvVH7MsAQ75XxGa0ofVj3crMCL29c+/QaUnhR
+GrdJ0sVJeIthiOQZZ5zBqG+IhJfG/jkKpweA9fkQ5gm+FoasTfDnAdSJjah7WfoO
+C6LKzNBB1FaOHqy4X6LUN5wraEOP+0OI3hKPdOB47yUzPF6FGneGk4BajDHG4RyT
+F2ZnG1aa+FRfakQ6l7ok4j+VPtDlCPY2jnT7muj2F78G69abNOS7ASXg5+PJzso0
+liaWo1d8TDfEazlDQvglDAKpzYw2mSbpJVmmbPSaVZxUARcIIaBqxu6xWepfdN8v
+qZGrOp7vTOuGu8f2YmWKd3+lcNm2CwwGYIPpuTFjtUuF7guKEdTffyj5tpOdo942
+RAy/F3tCy5zfZrI8SkSkx+wfZAnkUnI3xQNdKKVLCXcpBtQWht2UGO1G9W84OmFy
+eg21zeITIwPJZfUif9WHihdINSlfm0CiS+gDRzXukS4HgniPfS3NPo6HAepc2Gzr
+QUGF/ENern3v85DCEE/AebRaQN7liM+6Z55UZ4GOT3Tj64+Nth7MNQXqBYEmCS8P
+ndWvlalOs+vlj2Rl13IcSUOK8OOr6S7jeZhoutej1b4lbw8RwYBXGg==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_blowfish_ecb.pem b/samples/rsa/openssl_rsa_blowfish_ecb.pem
new file mode 100644
index 0000000..bc3353e
--- /dev/null
+++ b/samples/rsa/openssl_rsa_blowfish_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-ECB,1E15270A7DD42BA2
+
+zz3p7Ml80hSdlJsI5RyvOScQlsGC1GLg3AK0dC/Hh0IKPTDF7a2OITL6H/y/3txz
+LJ6jAcobjRfVMWGAJUwFaSlE5QF5W1+RauV+M8oMmv+Mf2K/Urha6m63EauLEVWu
+IDtxj74qfQgyd//qWHU+XmWhhNEGk5MrH163VITZqpG3Qe9dYHdalh4TB/ILJqfN
+URKLjdz8L4YbL48dwK6UxargixQ3tfrvIdTr4mkMiquNlayTk9g5qXWnEXy+I1DB
+HweXveJeSUHhYRXdx37y2I8Bz8HcuZF5wODEDJJuYXy7a8Q+Ar0Ll/uQ4NXE3iI0
+NA8RA0caAlc+Du/xfzKdUgIPQaLt/sjhM4gPBDLlASUmO+PJfb1VYgDIbNbXiR9x
+92ePzennPnbhKsPcuZzXoc/jH2BiQwwRT2gLscZ86n9O1FNoaPAnYERlyNIVrQoC
+0Ll6NnGBM9Ls5k1royQQtZU2x5Yu5Q7DGcNqX2yI14AZrI4e9/Y0nEa+17WRD6eO
+fdaIC5dVrv8HZxlfzwFs33FpufovP2vlINWM3IqDjMf4FIQsoLdnmTsgoLRYm4JK
+zfcyiImXPt2iUrcybZHKa0EXYjrcoIVBS8YP1UTcG8WHnj3ploMxXOw0AmpXcznf
+sbLsaehbs4ugM5G358PMeWFXTv8K2YXRtArXHtkIYzA45zqWzpta5E7LiTQJfBRL
+VNtLja40a0gaajvROCekEzWhezZc7bu6RQ/XZXxBYHx9m7nhzKRkDlBrrJVpWSW7
+QmS0ptXblyt2tbaUtNLsi2SP7gP9ggTlc5hCpwygT+lxrcr6j18CiPgMYOgDmFY7
+gZ3jZ+HHd2+8GnimOai+r8wh1aW06/tLfIZxpIn4T9yGh/EMW/R1RTJjN0xe6oqw
+wC+TPUM2bMvDtAvdn8bYh3pVVLXnFa6LjhhgNvnx6wBoiBCJ4E9R1Ec0QA4jF/97
+B4e8TEv7PAFB+VGhIPnQqfsAqRfM88FwgZqSfZrBXKMVWA7I4fBeVD0cJQq8TwCz
+TY9Fi1YnomqTfacH1hf9KiX3j8OkfrhIM3+w26nE553/wOcO42YJ55NgnNXlQL2e
+e1s4uJ9lroATY2WqvgLy5Th8n5y6kVkjuODb/8hk3KXqiLqbUOmZCYLuT4ZHZ+Rk
+xtWuFpmFiuWgbg6Nr2t2KYXwD39pjGBRmmwMX1mBxmUD9NK28yO4HEgiPVzfn7sU
+1PWC7HpgPf797M2/N1gyUfrBbfw4OXWpycvmtJLXHEJi/p/H1bz0MuMJvPtNhzUO
+CP4jq0xbu9nT5eW9rD7kgvv10W+aUf314RcWKaLkOxkk2dTENjbviASce5X3ZU4l
+eGG2wtoHvCvHnNVj2ImKf0jbAL7dymVJlA1XwsLANAmk+9RGyVJgHn7ZkOfRVJmW
+VMfZ6AVeFY5BeJ0LCq1uE6QMClVx8fLN2iBEqamBNekcZ62Qz3b1R7ZbN2tlPKee
+JnLSouju6Mu8U9twVI2tr63OTh/a0XAjtlO0OAXuVcOmYOHT9fSjPdAAt3Rp50Sj
+PDvgN8s+qSkQKpx7C2OA9Wisrr71UrBrCfBhCOmN5gyWFg24PwwRKUnc1a8mT5Zx
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_blowfish_ofb.pem b/samples/rsa/openssl_rsa_blowfish_ofb.pem
new file mode 100644
index 0000000..acbd8da
--- /dev/null
+++ b/samples/rsa/openssl_rsa_blowfish_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-OFB,B9F95E282FEAA06D
+
+StEkcUPp3txNaJlYBP+eVabWYcEzAkX64aj8vaDX64i7bVl4ospAs2stac7uXtXG
+IZLTqNNACoqC0jWWTDJca9vTEoqjDRKjN9yjXYfrovj5oKi79wfsSU29oH1dcKG8
+G4y8qNsA9TexRQDWTBxYO6EiQFVie9O3oXzjhO1hYwxldSWOV5ZRWoVmg16vAOxX
+Gx2W1twtjQXG/hp0HxosPkZteUDdhMZLWonYuqEw1oBC4iDG1Tjp0p5uSnb1gaIr
+pzZScikP0Z4/8CxiKV9/C1VNE70EHdAUYKjUx2PAbPaMFyO/sAXOy1INI7Wis7jh
+U2wKeXgCMRxmca4OMITcjDp6OGmKf41uWyTFwjO1scMvjSJsOZxNjAjcrZW1PPRA
+tvnhRpU9h1G9BOH2rM7VUI6zJ2FSNKG9R6M0WOQqxRegJzvK+YNLhw5lUzrbWOR0
+RdkKL15gfnuXqLTDTMuLX+aCDS1Mu/ZRmDqLWkJH4W1HJ4l2rBojX5fcbamueMyf
+Sbd1S7QtmF/B9LaGDEPMT12kOQHZkRBUYpyolK6BoMuRPYnGS0RkUwvIuPZA8uJU
+vHHuYRZsOA45YFEipyB/sek61bvqYy+8TaPxzpfj0fkh7AUSQmbk3qQRkQbltzqq
+/MkFShIzS7SUkyiowOet8fVjXDJPsw2bS3uOHC4zy2QQmhVKzCYWd4yCFl+WtJnZ
+eEkrZH2BpoCDEzKlex/NQlH9KBLOor221nJEVd5tkdWWZt71eGld20eFL3ewtDqV
+GJX8jFmR51vQL6NZ2Ehp/5zhearuBJ8VKJfFxIKSrbPjyCbEwUgYOyVHHyvYyMR/
+6hcflrUu1IFFwFhryg2bucAkdX9AhsO1dimxSgZKEFlZbihPBysCdUw3WRea57iS
+n/zqLrOm786KiWh0ndBgJ973g1x+OeuUvbNl/0yiO4Vjny6PkXcBOORu+ILEflzf
+UiEKyG8+cYzoYZjeiCFBxsA2+gZMdgjxVYF/lKzTqFkfpwYV+tF2K5N8W51cL8Is
+yhz5OHiENobjx3QeFCZ4LWDEXg1H8cA34i9oELbXtyG7W+hkZp0B9tRDrXcDwVWk
+4oYqWLNCQXqr1lL6cCuctKLdXbc1ibLt1nYGpJrPkPCbOshsI+iCMmulT23s+jqW
+TMW0RNb3wFjR5z9A1YTWfiqMKEcyzRhP6bEM/+WNmHE5LRefx+dnvZrVJzGZA/3k
+JAOpsxEPKv7YNR8N9yoAopRfFEOH4HYtLbsAA2sZfD6iVAXAAeiZ2Ehn+Bvek5lV
+5zIOtsXswRgzXvxXCPy0V5GWqMglbkUS2HGsWaHpxDSMbvBJuaSi2blZ16p3IICM
+7YcCLolKUaWqpXjhb3UypoYRwJs+40EiXid7aJ8rKoeId1SeETOwVWkz95NMiVK9
+5K37/OMvxOAdjAUxtmz/+v+twKfrUhYqP3Qkapy6FgA+qxnzpCFZZXrMKjpr99Pc
+QVNcvM/SKWB34jZGTo+Styc7d+iXDC1BUS/43Pvbka/Aa2IV/LPQA2pD44aP5l3V
+/tOfQFQWI0wCqpBPV8aXqGuqZU2ES0yc9DJ974a8NvS1cNWfsMcvNg==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des1_cbc.pem b/samples/rsa/openssl_rsa_des1_cbc.pem
new file mode 100644
index 0000000..2d2233e
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des1_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,4629ADA1FF55BE00
+
+2093wYtiVZThSK/Ecf2pxfukmymwYi+yaWhMDfxz/O001tbrlC/emwfU7iprUPeD
+NJyyAV4GLjUBA51tfDqia3ATKaBfUtMQoC48+q/Lkr5KhLZEU0LLVuGrfvmDXmPb
+Ne9Ud8XZGnrDmvAFkguzK7cF4PFWUX3l5oYKinm8he7pA+t9RJ6QX7+BHKQHlWcR
+cT9e1iN7MykRD2Hh7YjSxg1uRlJ+1H5zIJBDjQ/WIUMj4EdNJriurt7eYY2XrP9M
+fyvTOBgYRHn6uQU0tdV0619j5yjEBpPTRf2M4RGOeNYGfvmk4RcyZPdnccDq5bWT
+w2XhhBPZMdCHmDPTCOwgfSvqBBX6OtH2EKd1aJQmtudMATPjA49Q2v9ZrgIQQxmA
+ZXIXuYH8wNPlzpm+abolucwIQhWJqr5TP5q7IKfYLD7FIjyrPBJecGoDuPB/Qp8x
+D9G73DKYgu3aYEFxcjs7tWwWe93pn7glEPmuybK2HP0iD5/YhXy9OUElAUZVBHXb
+WNyFdcdmyP/hcex5nI3Q27yM1auTS4Wpmvg9I5Psr1NN5ilWFNiJ0fr/YcOMpVsz
+NqQPuSLqxX5sg7X6m7MkE0/k8PfFO+tpy1cC/K18nnka8WgH4SJ+R1I8WXLKFznU
+X+mWcOaci2YBUHT7TWRzJ9/5bL0CEWlheabTjqbaV/4kiE5L0Wcbh/am56c2YAzi
+6MzassP58vp4hHXTyda94+Kj4ymYFbRBLqh9CVspolwDhy6e7ydcspGz/RRbuWrN
+Xc+lsExkvnLkYvkfmaAU/C5ME5PNjgM0kH0qXLyXPPtdKmwWrkGjElzaY2iajzpP
+XEmnYu4E8AsNdNg3HVcQfoUU7jFq1NeB4uibFrq8vh6VLmqGvK6XCul0gxJsfsh+
+j/38B1+5I97I0oplDZrAQMgek3BXegw6HZVqADC2KH4Jir50rYNCFrN1un9aohHG
+BdTzB1wGkjW2fJ/yrU5nkkTYcNhl9zU0D09XvFvXyeRdLzJL5eFqqZluwsPPw/TM
+CSwjTZbbeS2LvvstAsoYGfQTUr/E+BOXVpFmNg+94DBxwM7lCy57nG2Y6oIy8Qcb
+IfmF+wKMZEVJxy8O2uaCYUwU7qpucq1tz8l4bTo8wUctxw80Iflq7WYg/8V2ilro
+F1nSJ7gF0bn33KwlLxLy7akXiol8Rg6aOg+cAiMi2Apfg+5DXWrKf9YOwebDLOX3
+LWvDuMYRVccwVWsA+X4zUezGjVNuxjnjtsDfeiScf9QyliK8kjlMP/r+chrhFFzc
+LXARzcVfYCQhF6heOOY9YTHvcySV4NmgRKC/dlzvN4NMGh8VxWiEFDo7Vu8XTXpN
+7OiSd/BvmOism6emrC8zRMD8c1ZgCxuY1MOMVXRir/Qy1IWZXiYmI71mmJmRhE79
+Gn5JJ3aZ9xZmr34l296CWOBY/suTRvkrfyMRoSTC8Z9K5nbd+cm0MLzWMgiT5PAg
+cy6PHN9zVWInz/2z00qf+3lx45ZmMeVj2+2h1PFapXaCwvek3VgsXL2HUV/mKNcU
+ZH7mV8imvIopRSS4YQXB0Ophiv6i7lJWdKrSYd/Ac+Bt2E4z7q7y4wFNlZBvsBoO
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des1_cfb.pem b/samples/rsa/openssl_rsa_des1_cfb.pem
new file mode 100644
index 0000000..814ff89
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des1_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CFB,07BD7DC7BB2EAC98
+
+yH7T+ZIRWmzcMociF5wV3YjHWCUMs9C/GUrnBP37vvJrBDBB3x0u6aQMaOs0U1Ih
+xbGOweaw7cMag1HhafjVK9ZFZlYsCfXRZk6JdOvzPchDctQrnjkDxnwpOllmp0w4
+Mg9mYLuEvN968Tx2TS26va/rPAu3xxA8mrcCuSfyt6O9HteT1axwDpZzOktmnbYy
+xHQDRcpDXaXspP2sVTaZJ3oq/AMGfrFXCu2m9jFHcyZKmEm/DW2aLmfOI5I7gCLP
+1KMekkauODnQZEE2Iyi1SVbTBKH5DPp7yXAXWOtugBcWNHbMF9QHqKlMs5Hd2MYg
+doXtBSRRBc9pLdF1FMwHHjPFI+GZL3hurqcD+YyZJqYvzEgnI9dls2K8MzQKYKDn
+6VpDCNbEf8aC0QmvCLIjqei5fH2RVYeV2M4Db1GDmpRAIRJEq0fXf5ojAD0Mhv6p
+DZYsz+f/MLTGwce+HCWxZyAyfptdK2ScfvaH8mUr1OHd5IdvRudh5+9sCtch5xQL
+DFIp1eBRd+2gvLBMja7gBE/xHXoFZtTR8xORCwgYXVrLLf4wG27XLdKQVQiS8dpi
+E+xCtiZmZfxb/1Ly9yHP/ehWD9DmxRRr/n1QeGMjSlLSzffuLgt/0tftK5yOSZri
+Xc1T83n5rLqhBglNEvwR1ewsTgeIxkgZo7q/LFajrnGh4L62cIoLkLX3lG0jaEC5
+VTa06i0b7U1nJ6kiqjHuXzkZWjTim4V7p7r/SQtAGuK3s8AmqJH53EMmiK0zFq9Q
+ao1ewixzD4NplA2HY4kAAVRQMR7WWIRrV2wXRTqoKwITMbZ8Yio8PwgSjsYhuzwv
+Mct1CmTc2FcCH/+AZOqc2HNS4qwQVmwLnOLmsr7L9kgf9aPIl1hkn9KzC6GAU+fZ
+F+N0Ti7d+ZkNAtAUg8fi2Bf/rtPvxmyJp6QICI4Tj4MFpGIRWP5rLwU6XXNch0l1
+nAcIYFvzLNL1v0TDnDz/CFW7XSp4IaDl0OLyAt+JxnPuFOAo1wJOhUWHheGynEBP
+U3K4u+761XMdqHb1n14OSgfyynIuLM6WtnBDoevKX8v0dYjO6PnvcuZoRqs1sYKr
+D93XsV8uMv79Oo84xQPHpJrUIJVLDeE5GLFimD7rUPvMURg1IrFnGyfcMGTvsv9O
+us/B1dNmOHjG7eZwJ/8MDNsYcpwm7CQsTOJUZkQDN7MZOKJZJr2gQK659eULJwaZ
+lEkR2p6A51etvlSPZ2pjy2Mgxk/T0mX/mVprEvCkxFWGlAxys1UFWKHDOOP4rUZs
+iE7nxBMyW+4zHAcco4Nly5gryqWiW0gn99/I7+qQHkb5X6ydP+GKOHmUdcb8RPIH
+Ec3bV7mBtfYxDC/ouStuQdVC7jWGwU7PeQqoz4d3mhK8dfeOvpudiTD1BLw30LKE
+Dt8/tob6zIHMEA5NTu6g5cbfa0lhRH1tD+O/7RejWPwOTc1LbY2igvHoh5uWTo8G
+ufvYO41PElmJoujef4njSZHcMvHArinYdlWlvMIg52d7Y3lQTTztY2UeO6DKRHx8
+Qjda5g8SDiqgFktkl5r9FYfqMQFqheSgKnHaJ2oPPbwuJyuNdy2Rug==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des1_ecb.pem b/samples/rsa/openssl_rsa_des1_ecb.pem
new file mode 100644
index 0000000..91a3f49
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des1_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-ECB,451BC59702897B57
+
+lYkflQyHR1brYuUKx2oj0+L9fRwOhpKR6NMeH2nlLEMz1yntUt9DGuBRwP4RJs8o
+AHo7amQ1YzGpQCEZx3p+tMmk/hHRcRmU3ZeuP3SlGwpUmbMe3NI8I2dvh/qDL3Rb
+QParp+YK2vH/u/N2VPB11NvgwoUQpfS35vOhoLk3GUcupSKfbsbl/gn398DsgfoI
+d0qD5VSxNutst5I05pl4JFnL5+DBv1s9w68TdvAvBqWmsfhb4ei/mSp81e6ndxOR
+VLF5hgXauJjEHvI+c/ITF0roIyyxiMMjFd8IuIHbeznIjOWn4P5YcNcSswSG2wOz
+1wB0e8dlskukcUGqFS6W6mJzqb2TK1Eo+l0w2B2rNGX/MlGV9f6r7e0DQQFH0nCI
+nLS76C+WB5G6RA/7OMOWtsMnYSLldvXBxxZktcD1CNjyvuCOI5NK1KmG/Kajho6S
+/+A1mTs274pI6sIsCNl4ay2pfgwjZSWh95l8+YNt7o0C5lHudZ4hZHCDT8U2uCoe
+7dhj+KTuIS3VPI7lzruMZBGAj+haZ/cAEdqYGXizOle4MwKM5+lS8E5gEviTABua
+7jqhqbBE7CkN05Y3QmyE48yzi58hzSmiTOuAJ6jhB47A6Vsp/FpKFzfsK4BoD0Zh
+0ujT2BeJhtsFmPY6+RLtGITnl1498j9FTfy8ZNdrXEMxvp8SnEzlIKytLQyNoz7a
+tPCe1od1w+MUz0PHqDO/Av3YMULGLCUgnuZc0YjZv3P54FdC6si6KFEEqotIGD0j
+C24TXqlBpn8Qqkht/0TmzVHq6U7jynOjD1VUeB/gudPlHGLs468c7HzEzbpE5h0G
+1e5o6D5u9Nh1ItMObNrjt8NUxbi2/FX/Nkm3J1Ogno0ngzh15jZUfWFPAGkI1nho
+12F8Sf7YTBizPW+sd5hDbVejJURyoj/jt6UfiVKUg9iUgOW+ZzgkbD8RvC207xis
+QoF+2Lr8mPsNabUaFbsXmQ+6F0Pn05BzyBN2fyTxRt6u0CKmLE1fqkIuQywk83UD
+hBJfeewGoOGvoXDSy0ggIkjaRCsk//Xvntt5HEmKwc/wy/1Nzuu9H3C6n7qLqyNJ
+mPhrOGXt6C4LG1JscqS87z4VmhV7mol/Umdg00HRHs7l9qKRTePdlq52JL7oUws2
+CJs/UTaBHdbV2vh06qmymtEyNmQ+PrweEL5U/neyeYyrx6DsyUDdY1h1n+aKSEyR
+eittKv/pouPSLlIiMeY/DzQwN1ifoGsfYgJRst9Ry4MdlahpCTX+K7X6ryEOoJ/H
+1IEOm2aSlC3qEABUGo50IqiNF/PWugS7Qf/JzXAyjtcgQdW3cskNDCR7JVJDtATu
+0817ST0QXBL8qT1C3z843LcY1HpnQ1MiQvM3maDHCxuoEoUrRILWc59mc14gmowq
+g5XLMOLC/y5mX5LDqkxoKhoED9eM9/9EGSSy83dWWVZlGNLzu/JHBiWa3tVhas0U
+LytNa+kN8UfTC8KPe6i8euhauunLIKkq+MUBWy6agFR+jflE0zd0Av7Ox8HPbGe5
+0fraChwokeFM44fy5cOH7zENfng0jVUUreTpDtcfp390QW5Ca59J5/5P2aUBLZHi
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des1_ofb.pem b/samples/rsa/openssl_rsa_des1_ofb.pem
new file mode 100644
index 0000000..93766e7
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des1_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-OFB,62D0879F9BE636D0
+
++iyQyk6TcPldmHOJyjJjsJ4BgdDqqdQYRzQWC/WfDLJyw3CXLquWDciAw5aCof3k
+b6R4PvJHzvG6j9jdlcv+yD5M3j9ZVHYkLL0fTZA/LEODUOTX74gNZfoz3FGarYIV
+TabFLgwQh4YJ0+Nb5N/oISaNszC+wxf20D4N445kvuHKbak7o2j+5ZzGId9zYIPU
+Jat1HygggKh9PtE4NildizyVVK5h8ws8qPWbe2/m00Hf5R2oP2YC3Afn6kqMuueJ
+RrvP9l26WboAKFED91xY3gJy8r3KkkLOJq9856BlndtgkA3USqRM31W6RvLqHUDy
+3l4ZY3wSTCdZIX+iHV6Qm3xYaIHNzYjHRcPQKdOVmEYiUSmAZmcavcsPC7sEfD7d
+OMEbrYrztF8iO90Myey/lJxo9RaL5PfWbtXqnXKUZtbcudEQd1fXM6gzdMm8AT4F
+eUSayg1/3AGEEHq2PH8kKtxnWAb7xBOgLbjTuC68f38dFw2P8iWZerG5lbLsFuwD
+YZ5eItuDhL8+dbFxisBX6H0lzcm0pwK1HCHOvSCcYfpWC4QrU08WbtI7NCqIuRWv
+4QOHU6SoNGW99BSnUlsqgLdIcsWsyTwiotZqusZV9AusdsGqU5ixwal4YX/8JRg+
+93EwnFnl1Y0Bj/yoAwNfvPlZhtjevsMnPEbrXbFEm0Xw1kdhOYokrx0hQWUmdt7m
+cFdmFBYQGsiKucvRpmInylrS41VQNbNySqQ5iGa+vDaPBMKZusvgPgwWSchotkzT
+qTQ7HNjszwR4eIjBOiBSvY5YXoa9H3irdmLn76mOyDMjaQyC9o/0tbAagLKADuF1
+Ui4Z/3WV67SuUoawqDJsYEWbOaNFX04wFby0k7oACoNxqoGFM3ITRzmxnz3ZyiPE
+DV/grOZICMLfTQ81VvE8/w+w697F6EJ8rY1yOznglP4GXrtIiXAaJbxEOhosyuN7
+HikpDQ3GRnPzXeg/Yngzpp8JMVdxKdEItcXnWd9uhB2Ok1vXH8LjhVkhrL76bJe7
+bhagz+LphPaLnkE5BPHKLUwL8bQQguz7ITfxsEFpWIHG5zCtpaQwdMEj2ePVubN8
+sfZ3qhDRNG8DdwXgCbCot16SKGuOawMMC5tsoeg3DFQ4MBDrKUv3C9nF8izTs1Zr
+3J7kWYrZg6+hVcJDgLS3t/lbFIhaNAULmep6wl4Vcp6nBqr395r8/uDroOpoBxoa
+BNjvFaztkRy3XmNHp3TOYLg5HZPWsK3KXOs0FvdTMEEsnoj3PXz6+hw0gMV6huYp
+o24r34gKiwdbrkbwLRnyh0oF6d3bPOZ9WnPgA2y2MB+slulA47+hOMcP9+WiQxE/
+eGd6TTRjMPopQXJw7/tZEf6qyVYLWfKJmI0tljsea48NocZdsek+e4ZsTW/iP0oZ
+wPDYNt95V64APcDZfNtfzydp0516KY7p624TanOXsxNNiBV6Nuqmd0dGhbmcRC8Q
+KNgGNvgjF3rhqrXZyFpnZNQewE7a87bgmO1O772QU6GmPUZr3nzPRwE/8+TNA9AP
+hHL9HtItZ3arx7eJ42obFrxj3uzpQ8WQo/cGLgQT0lz6u91xJyWi2A==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des2_cbc.pem b/samples/rsa/openssl_rsa_des2_cbc.pem
new file mode 100644
index 0000000..9dbe30d
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des2_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CBC,A48C2683D96452DF
+
+dRu5UKxN6kr8aSBwZnynPwIA2y8Dgu6Xf2vCf0JswuFMJAwFGjiHoZTmIHuAjArK
+GWhiMl6ak552D/Nugz2SNgC3eJo/LOP/g2NIJnG09GuWOGXkiagjDKNbPCiIBPww
+STIBg5ilKV07lryS0FxQSUWsjI/2c0yxk/6MGSzQ6rrAWB4Cf843u482w6Hidr/E
+euPsqXJDtlQrKQ1gaMTJiOY9Y2H81b485MBN9BnKfDH4WHp49b/akcditst59fty
+FtzwyUTee9SGY6u7oKaUUe6sRzFOeeRR2TgWG5Bs5sne1AFFen2/q59Va/7/iXRd
+TOKKUGR4yj9gA+9EIpDF3n8Vn3G9LnTDFK0Xh1m61C1mQmXgEOqJGLVreFq4u1xq
+0J1yEZKoXreZJH95+gYAW5lmG+jNCMy0RO5PsTClx7G4XcIGFZAXi8sXfk3FYLT8
+nboMgQ8IXFjqO85FIVMt+xCpov+S8yOfPMOU63zxrynaXD2eGv7y2dTpeF3Mf4Ek
+be0YrQEWpCtYUdZ9AwA4N0/vkdp84/WZ3Aw/i+KUqYKtK2agkJYtarqj6iUweUvW
+GgWvZqNiTAd3sGcxffSbcdSRpuNttnBG77qAFgFiPXtvJu4wRkGlaxhwVTyUWK2E
+HvCEsssbzX4tZ6GUXScXv4zg3YaDP6HXsnBENl5SGXK8Uelett6PJhwH7bfpWysG
+Z1TD75uk6twThhtPURGG4GUaQ6cZ1RUsL9/y06v3ZmfUBxeVGLKwyMzlr2FTYenU
++LcvzriycweTLMO6llLVQH8XwlbAZ7JgndCjZodtFXhjhrS5Iu0sO6J2D7xFvL3q
+/Ym8PhhRStcVjijX+5+9aiA8AkXK3khP14T3yhPLu7iayl836Lh1+O1BHiYgr9Z6
+DdhCmO2Esa822yxyOdiwVlF+mYQylEZQy3D3kqqJytO9pn87cSvR3WbPtFOStlcs
+Htms8SdqLAamuWLGZiycPr87mSH2By2JED//80fNHdR1D7cvPU7oL/ClFMX/F3EW
+UJAwSXswmUxqccBR2hOJ6K3OvSIULoUn3awM/qPNTQL7rg++dSzUDbIiUywxuU9N
+nXkqfBVjoJTjafgWd39G3RdoK0ohf9QFj1nqYfaQGKy90cPVw/FdjRyszJWDUBTq
+jlKXnap6ZS9PGztjEoLqmFaFT75RUR49NnNtmcKmH0i6anjwFWEYBM61jox7gH+g
+W0r+0R2yijAspXHVpuibx9vdgkq/WR4A36t6DEMajOHM3SVzbPzkHTV5HyYQKnaw
+SZLSdUk8VwYkGSylm3f64PJLxBl7TNtrQhFLgR/9QXkhN7U2Qc7WxRQzhLQsLbtL
+qcBLGH34SGQarQZ5dfo3t+B6IIW2HvHNOiT9HQsIJTz4Er1SbLNH6bco7hud6aOA
+eSifKkWLp3SXXS6wjQZzsSGZ7Mws1DRcL9gEhb4tgIvopQK773AbQ1SJDEcmBpD1
+NmxrTbb1TngaW6u/79Nng84YEUiWNDKu3ovoe/HLVZoDr3tGmy5ch0jfA6NOxEn3
+KXZCiu/PjU005SLyLql5dcGzagjnnURDi7TLue/97xtpI/ac0vL868Cqfm0+e26H
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des2_cfb.pem b/samples/rsa/openssl_rsa_des2_cfb.pem
new file mode 100644
index 0000000..451670c
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des2_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CFB,36E0C8A965F07E25
+
+L0GHzT9XVnA03q7rlchpiD4JCgzISj+B9GxKCrKSJJBC8bRTgjgrwySMQyhdX1nw
+DiCtb9q7UCxQ/j0VvHuoA3OS1/Q95mwCsnjUXYAPiXeR0NMJkLgv1hFU8EjAJHY8
+ZenlgfC1RNoUONucq7v3F7jpsqBWrxjyDXFnWwe3edSfUzkfkG27NK6LPScjqdY6
+kJWAkHGpoGog7cYVBJ78LbYYHSBR+xfeFzhVMqB78mH8/Y/CGlKvXnPFpiJCY7Af
+zpd4/PJRVubXVyANc42k+0/E2oPOSKiwiKV79BxFw8g+NxkhRzXeCDuzvExKL457
+cuPNB0CQLSVNmOWKr6mA1bIBiJXgASzijsjkyoH62D/QoBo+kBT8W3hiHooSzJ89
+flhyknT+rVuAbFdPGqriS8siN/r4Qq/gbQIFhNe9jsSQesfr7lM3oK2EPGpDxstf
+eKc+EhHBlT4S9X+AilnjK5il2X5szyhOFZQ7RdAiqZ7X2KPNNqbeS2L530ZvlL+W
+Yw4qco88cilN276QQWCcrp3YcWv+MzawlNvfOOAb4GfUlR+njPxRAxM3rGVXiMn+
+6UL3X1SqZfADJOn57S4cDoP/A0i3FUfoPTwQW77LOAIzLSeMi7brQkZi5J9s5Izm
+OMcEi+GwBrkbPl67fKMnt3cHeFGJmOftrLZCt8HpGEdiQzP5iiC828XvLLxby5Ue
+BGoBILGIHL3OqkTVjBbSODKFZTIOQdVkqrWKyXlrfoI1meATptP7/GhdQP2DTW8B
+ppmNgtwIbGLg/AwNmGPdpL2mP5SZLIDJHd81BL00xPJFCR9wxXLk3hgm6auzAsZV
+FYjaIQ0Qza5kBCKNqu8ad8edqgp5Rj1/ZzfCWEkPRHD/lZ7nj9vuC/dMnPphohKz
+q8/L1+gbp8dwER7sEVBiWDE5u3lpSbx+1qkk2CwOjE9eBh2Mr6qLL2WIFb4YUvYI
+OAWIU1ftenOEjgjvYZcdeEOYT0UF6/avfHDPvkTIwl52UUhunbnqCjQM3qr18rbV
+8vB1bC64DxetUPhDymLqJCe4QVQajdO5BxQ2wwRjHlBi94nlAS/uOFV+WwqtFKZD
+TakruYhw3VjGxtnjukruMzNjDSqxd8Jabp1oTHY57C+aYQcBo34XAr+j+PQTPXEj
+GNL19MUMHJo/yk05NZfkyf3/+YtAV+/Gle7TlWWCV1nvEwrHPE4yCGi8j6qtCzBC
+TgpXl/lxJendZgVzIGGzMDemJgyrLNV6ar8TbOz6d5GDV3S84g2S7cToMVHX4Z8M
+bR53pt/KfH27Wdn68z3Zd7sT8R0g7yCVIc0BJgRrZ1aLnyKLSUk7iJULg3+B5NwK
+JNucRiU6mT5SUiyS5WjD6vZVDjggAx7H74DP04rzgzcHvTB2gzx1hFzw6WW9wcCk
+7+RiY0j13M/nD8UjW+pp/Ugk4Oc/bvxsA2tWQ1BeyF+KSNj/zjHMwN/sp1/of43X
+D+lcWS1hCwMiy79KQudrkc2DiYKWSIiXEFlblSJGiQz7SxybtO+D0PpVmlEYWiDF
+AAMz3hM+CrWcXIFNw86mHSsJHvYsSjbCB3ydG8L9OdATYsS3tZo38g==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des2_ecb.pem b/samples/rsa/openssl_rsa_des2_ecb.pem
new file mode 100644
index 0000000..c3f285f
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des2_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE,8B0E5396F9D19442
+
+Ym7x4lqzxkC0K7f3nTtR7/ZVi0Vj36NLORWiJig0qvSmH1rhkkmMjssQqc17kWRT
+ttLj4D4s1ueQBlDFaumMrXloVp8c4zQS5jbHNmf+bUsom+HXGFHbjPC0usHm9TAl
+pPBWMCON5uUxoqJhw2mvrGSlkQhkkh3+Oiag6fxNxnN8Te/yTPC1XXCqIh7zRjCN
+q3wjkh8+0QP8ui2jK/2zrlbwvCyggs4q1YhVzWYiecFro1llb+CDCz0mzKEXj1MM
+MLyMdcooxXTb4t5PhkW87N8PSWXeJEJTxcWYbZ7bf+Bf68iHm6JChc/HTXZRLUfo
+3lACV21KTTI/614rLl44l/Ftg4HDSE4UV/J2JoenbRecljKXneeVj48Lmurc3zZa
+rj46e/pXEGfeEGmkuVnriWhRBcK8Mq33XfY870RsP+4bfxd2ykJYyxFZyoTT0sAU
+LJ4KIVZVc3/jB58CRBZDV4s6/cA0uHPhprtzEHSxp7vI9N4dQAWaUBMnDtPVC999
+QjVGYKRUUNp2S4XVLtMH3+jZ5ntvCTTabjuie/4TAxoUY45CwKjEFpWtDBEWBbXe
+zmIQYCE+o8hSVtt8DFWdz8+PGqF9QgWZ5iQtnp5hUKA4rVeaxF7+ktumTrwguZcZ
+6ZK+K3t4lcHyPZMQBoiWijmBLoRsoQ7NIFEE3sn9muV0XUz3hMCRapWsqS4fd3N0
+LRXrBmZuizqzaNBcDku7lBbembdW7EI9flzY/0Q0xRl7WjOdK6Nj4V2A2MblQoh1
+J+pvV9Tc4PANApNLcFZSPawOJVyUtmpX8QZYTe7QlXQrVIQE4HX4od1S3/ZlydfT
+DL8Atfec1sabrRFs1M86lJGnYxsvismLVH0VmkigWe+4sClAl5QrtCfGQepYmsYi
+jyVruF3FzbOCjcv04x4a4HyKRHeCVlsRlSq/njqCh0WSc7OMacpQJZVvsUYRCaS1
+7WhmzeiVNjgKXg5lPwta78Kh+XbQUtUGryQQrwOnbj0SDsho2hBTt/gbWDpxoQjL
+LGPHVxwqm0GZ4bw+4IXwltfei7MG/ceWxLZYk8ZTkc6r+w0+5HQFKZ3JuSKB3OLm
+rK0m87IybLY/Zfap/WLAmreRMUz/FbsY9Vjh3gt6NqrDhqLFYCyyUKZyKrWnVlIj
+j5vohFGbq968UYVavCZ2eqmtwWywsBXLOabypgrIUQhmCxOUBM7Mi2NVrTqn8uIO
+G5+mwzsy8imChv3Zk2/LafxPpajlu1MuC6CtMdZjV+zrGxJBEUxADaTJU7tTAWef
+lUjlZ4l/XO3vxSvv/F3yONmgKp1t3naS0ZxxYalcMRi6xTznW24r5voOAsVqIz5y
+Nl5FtPMSCBE4FONoUI4Gq1GAen2h2/Dz1Q3CMYAvJz/QfpZFu4DZ+jAUISU7URfL
+7P/lXQhg3onHVy5tgXhiXDhCCxY4pUPSy57eE32F+sIGeltoXU2Okx5/ey8ijr+i
+5URStFLeFp90ke/EhdOuhDoE++7G826ky3twqtSBTt4jU9IemH0agFU3PWIJffm3
++Ezce6LusooS8Bqs9rYXHHGe2q0oUNY3ipggOzx4Th4mwg1HzBQnD6FU33M/WyCw
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des2_ofb.pem b/samples/rsa/openssl_rsa_des2_ofb.pem
new file mode 100644
index 0000000..c34872d
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des2_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-OFB,0A4E382F6060AA1B
+
+hIbY73AFUCWIkdT7MEKMhr7+uSoSMO9wihHjhiHn01cq6kTe66Vy/z9dmTcgbK2q
+edRngIRyiTqyul1dhQ2ezVDisowHAtdiD7O2/Z+YiXc1hsuC/uELnYV1hTUg73Qb
+v760pWyH5AXNpqGsx2LLw+hstiiWVO+/Hs+CqtM/RgONfvUCzbyOQknDfSTDoVXB
+W4gEDKSDj+ydXm0ZmMS17DLCXgk4HBsJxyiK666l2TzB9pnzj6EDA6hDsiHfy3z4
++MxfcnLxWw9TJPxdLYVdw8WNWsXQd1JHQz/BQ/Hum4eNoYxLGgsV/hWQmkFil1XO
+GkPjF2z44fxN4FJjvQskrQox+5/gvnG+KamfvQt62qN16Z6ROZu5buPijxmXoecq
+gW6SyeFbnYFn27hglllax9awEEUtcJwi6OxKAkWD3REjqCfNAwcqoFqwkxlPN3IH
+00Rksn3P7cN5IqePVjSdwIhZtCfeBW2267oNxb870CDon7OlrUdK8KIjp/x5jKUs
+Pjehw1Ovtvn2YUQnTPvIYQsgdq3BMb9ETcnPDneCVweSxHxpb8ao2hyBMyYtQG8f
+LNqvLnjh7FUyRenf3XRbqka2w8B1CFTTErkMm9E0OPD8tMtDyakI+8fMJDkGhGI5
+jMwY2q98Z+Ef4wDifOi6qNklBlJwjvvybeqhqWOoXKbQMhnQPqFnLGjp5GQMczII
+m9a0anYSvmNKjRtD1LBL0KDMUgIx35U+7GKQfjrRTURYtAK8EITKUqYoWJWXUevR
+t9cikdwQ2yDuDH/C+a2eaEHJITerdW7ba/Rxzh50VdPq03uUNkN21VZEMjcU+GPB
+sLQ50j+gSFRMMzMfDx0G3wHoEJNAul8x2+umCUSpzPfC5D6kjbyREm/fWEuQkvL6
+AUCheoD7ouRR66R8syjIbeCKhjZEXUOvxxNYHSySrxHyiCGE5xCSVDlTzAutvcOn
+kivQqRlO1C6ZoEWbGr1SPoIoi0iMoh+TKZDgMy6/pRWVbELW5P9JnH8K+IreOIXd
+IgnCsqKZBVN4qRPrW8HtEwiWW7MsoXGjhpVl8wer8cNmcfPTo3x2l2+mjV2r0xEZ
+Xmv2LEtjDfIUP6yXuID4OrV6kpqSDax+wmujr8jlETKf0uEi4PZAXqhrgh/fgH2p
+VE+Ey0vnDaXcEhS0ketOGmBIYaKzWbMH9iX46YSkA++5/PavhlbCqZZN+906jwEW
+6MS7Nq1UBoUiql1Xa8AL0p/7QKZH2mgxpFcBeCHF4q6HhebbQbCpveJgBSR7/12H
+fJOIubovV6AOx2kBRAf27bii5iwMjfzC9IBE+GLCX3CXR+BLfOWutTcqbaBRdmQv
+K4yJqB/WHYcjlLKf/Q8+B6elmMc59NVUfStMszkIGlTzMFIkObLHH1NYPSC700rH
+ZkrdbRGfcncT2OcyFbWZ/tIvUER/aHjh/BvZ9s8UyEVEZzsFJI8HA66sJzZ3fKaM
+8P7nXXagyarILIzO90JIwkX+ip//QtpSDPkrUtii6Wj7n7RO0REe5N5+NA3A7WUs
+Aret+KXgmsOi2fnTmCFjVN2QgmQvOg8PGx0yYx8gxWog/NAmLCVMjw==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des3_cbc.pem b/samples/rsa/openssl_rsa_des3_cbc.pem
new file mode 100644
index 0000000..6a632f2
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des3_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6D7B3D8B829964B1
+
+mw05Vw0Y4gDohoiqd0xLN6ZKCalPCK2F0QFSyAVeoPY39y1RyKdsg8xt/qDx73jZ
+rgZb/fQLKs/W6SqCAAk/7EIBNTCWf+yD5TTdG9n8viNDSNXWdyq172rEnRV1CWGe
+beo+YjNDh6UlZ1FcXLj82TpZ9EokUKLabzNkY/coVPLlytqTSO5oZmbdreuUxOyJ
+ktQJUmGBmBY0aHJmV2wCkOFAXbzoSfo+SNPntEUNTa8i0cSIgmZd4/QS2Xfa8qRZ
+c2R2hNyVZygru5t8eckKj6uvj/Yszg6XqQby4ktK/cYfveS85CNlu03WfjfI5V78
+vY5efs3+NVJi2+ush4p4TfgT0PAKTWjXwpMEiGVlmxBoPoFGtTXY3Xp+64QICgTa
+MdrxPDDBw2yxmWAOpm58eeRqAN7Jd42qBxerJFiOUZxYPyRrQvro6fkldUlbPNon
+53Hzb+zHXv9xM5aUqfEjMO4HyprhKT/8aZgQiDE8fHgJhI/S2Ho6Fzqz2/uOHzBB
+gx0m8fM8puQ11eRxO+oSE4OSKbEQG0Uj66cHXY6FbJUhsLkGo9HdjLSGW67vx7RY
+Q3PQApOCFcXLecfkXrUaAEeRPNqZXjCkF6s8bfCOXD1cr9BulaGpiGxdspu5Tk9Q
+bLtoX5VHnW9VoIoFsIWs1G0h3WILs7ynCE2ttDSnIjYZhE6pRBiDHRs3J6dH/oOh
+c4dFaapkisk0BANJduvB7vLvvbJ0Xs42q+sRUCWzHNnJ3BqQZtL5f0dqu1AXafji
+qwxcbrEqJc1kOQ+iRAZ83nVlVkI/UgWzTceYPR24Q0PnAux1LkoIO/FWbhm62j3u
+xS669GX+GS9urX8oC3JUYT2n9dnPL8ouB77KfP6c0GVxR2hhiLYmyP2600C5q5DU
+6rdNm6fb75nrAmD0cgPxbdOB8zbgVvQuPXG8QnTO5Vvhp5ETgifIXPCIWwNHg5xL
+o2zrAdrNaio8FZUVPHOvMKE6Wl9QDMqnnShH+8VhLk7+LQpVDewBnWaMd8pK8qGn
+robl+i4HWtn20uZIDFyI4ioSa0S3Kanvd9TkchEbDjKAVi1QXdcD+q9O0AYt/X6n
+ygx2DGhkNYMrQmc+AIt7dAPa6RdZv50AAc0R3S0DBaxtd36pWugT4WIEexmuYj8S
+NbRNLuyjQMYCeFs/Ff4df0gmfeyH88YSlafnLyFhvv041LAbU52e/yExCEUvKr5J
+Oj2qVHJVe3eVW+FX8hsoUAte/a5foVe067dThfZDVp0TirozHAycgfKI600VF3Rh
+rvQiHzmXRoMptt5g/yLsTVYiKAF1n2hU9556sJPARFrG1xXoFFwhpzCS5t8ywniN
+6wwV+V0s4LSJFQJBFjLrreu9ZkYMdEOrekzqBohF5wG/BJILkN8hBmnD5gckbLIM
+QUzGTGxu+BIUi8JNkso0hwZDAKnYit+FVAs+5yU0NVQU6e3fW/+m48YI5gqFI+k0
+gIGmAyU6zaUJBJJQ4wc3+dOsy8sokqRhVmA59Tv20IKHh54zWq4ouFAg4Yc0bwK0
+1ua9GJMGTXN0+Trb7MKZQVKokyNA0RVCDN9AIfwCA5hDhJTahsO8Lp4Eolz2TFaQ
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des3_cfb.pem b/samples/rsa/openssl_rsa_des3_cfb.pem
new file mode 100644
index 0000000..129e02e
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des3_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CFB,B99E3DD88C3A9D7B
+
+4Dsk+pNUGsgEqelOveMyrkoDb+khouKf83Yt4/qxX8CHs5q6i70NLViQWwqvIqQP
+g3h8Gs8cYKZfkEAFKP6BRFPy8EttnBCzhAdvLKrKFCZoDmhxC5ia+FxPLtNaDEb5
+6bgSoZ07KUMvfMZdnG5Kogex4DedqENVHBi2Rl3Dck1pAgxwzMntgHsluT4ht3id
+SgyUT/xAaMSwIklsjclR998N6V8Nilu8TDDf5X12RHOq/MSqGZ7yJC3Wb/dsirNs
+7jsEQwg9tIg5B/5hxjN12E4Ov7orIuO/WHNVtLznx1w1t/umPjLFn100Kln8GvfN
+jiGSB5TUz4t8r3deN7oDrGjoyr5OMnKWSsIwKcMsNSh9aTdkjIJBUUhIB2PStdX7
+WbeNXicNMQeteIrY+ZDDPpMbjsH1Kqcz5y9OWnvaXso5lSHLBp1IamCv/XbQcAPR
+zbnbN8DCOYAMcUiwcRAt0U+BNc1edX8VmCB0d4RQq5BTFbjGKqzo6yFVUOVLhiFg
+E8G3v8sTqUhJyH4Dmjn0oDMtfdplk30Ywg2wZAahnI9w+cZFvzqXshL3mGdu+rbb
+h7PkiJE5vS6/4VKA7pngsVanCRQa3btL43ekShth+DXwsziQixGD9HhTb2iYeF+u
+9niDPI5gzi9IfxIpb3QjR1xDJYAzKDDBA4gHhbEBSObByMsVzjS0+dwP9N6DV60v
+3x7RfO094FXxlVWSh2SMvz/sB9fsD9dCp/gadqHxhk2aJf7lfSU1C7EmM9hxGZku
+vR3J1QcSu2FMrvHyRzFZGKozSHq3QunOLno/KmY0ja1754NEkntGvPuB7LhGBNB6
+14NvQsl7qFw5wJxmEdY5rhVdz4PxLfjnMyvCiWlku83QIC51I5DbhRP7eG9rJSMw
+b7KFSQwmp2yzDeX+Ipd0JAgd14GvtmICKJVushO352O7mVnx3Jy1ZtJsonhzySz6
+1fGIvJI8jxZOdO7q1OD0bfrXS/kwdXnxoxn4pkjw3ZN3hdFTfAerVQ+qYJ7zIez5
+0lUihHNw1C/KRsggraOl9rTUNppcNtMYwKXCJOGXI2UEn8p3JIxEHLwXyOjTDfg/
+5oK2nPAmBdGsLb5ivJLPivmaqDXf7fdn0XBQQmtYUQRotlGmfpztujt/b2pL5YSE
+Uqginw65zyedjL6Aff3crvP8/CUR0JARx9vF12R+v2iAnDqVk/yqYpRqOp5elm1t
+yGB/PtpoRFsNU1hDnPZDu7kZV9oSeXaBDFOnHmX09qE2r869Aye1xOVmxiG5tm/u
+KGA+zlJVVpQSwnPc/qk17S0dvNAlgt6MH+vYlhKw8zk1nDCuavUK3hTFT+9w31cQ
+yjPdV4/K8seK4zIqpH4LZrC306/1/7BT5JXL6ZChATHaI68xwEY2GsEl/Ze0JrQv
+WpWSN/I269rUfaBDE6eFaiSDzq1xY+qyApHSTNPSPDHbFeCXz+puqv9lw0bJFnRJ
+nLsK2fUAKNvyCF18IydyhiGz42LYbwwjlEWuVsfWtgvftDebZRIfQFlj7DJwXfZU
+zcEOI5YyuQs+wFK/8b/bknF4xRpaXwt9Il7tcV07h96TDJV05illig==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des3_ecb.pem b/samples/rsa/openssl_rsa_des3_ecb.pem
new file mode 100644
index 0000000..bcdc5d3
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des3_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3,9675E5342C359F94
+
+aqJHsie4Ls1x3Tk73mbL7VyTembpkhx/a8Mc345TuZOZEkU9XYrkFMvhEB+jcVoo
+9ydosCL2d8xjDusry+vn5yF3iwE9HFHQ52M0/a5IH3sTtJ18BzAOi72ykGb2r6ly
+FzTq7xdXNihN19wHHnI98GKdxdQmNR9uITx8VRBbZdbRNGdJopS8zT96+AV1QAE6
+lyKKLA7qbATHR7JWQN2OYz05vGt48Vmq+da+qs5liEtx+GtNUxS5x8lAC6Llmq2s
+/Xv8X6kjYmxHSYWM2JyxsznGfdXKXe9f4Xxwyhedei6JgrTHa/JN/+tvgh5NWODK
+er1tLBRRA7atlSoB2AAegJC7gJRVOxRF4hiKX/19cfEpq8hF9+6EHGYm/IQRSI/J
+F0RGcnSdiddYbEb667qTkbLZi/d3Ih3KwKGww6ZzkHe/qPi230/cDR8tac26jmG8
+qoCwj+XCNOe9IUJsCN6RmLcFp4Tr4UVSsswxReN+xs5Ui+S3AY8IKscLSo+bB8gq
+DVBvVFUBTiF5/zO8q8H8Xv2c0aA3S9UQla+l3yoZygiUym+Q204Li+tDXiM602kr
+GGDA5/cGpQuit/7O51KF2OSwnnvLdu96qz0f9X+rq4QVNAy5PXcr2pj/y88UfSXN
+GAbogEXqpQzn0rmV1OWM8hsnOpN2DLcuZICCJFJc/BHO4elt65OfBjAvbxjhFU6s
+nJLUcR5EopLex46WwuucR6W6wjAuO8ET3cDV5L9wQI6DT+XItotk+yJyYawNPda7
+wfmxZ0o3qdcpRp7aw0ohfshRGJMuLnGVgLczU4hwO2/1LgRMnCywldacAfo8Ot8s
+WnC7d0jVOre2K67Omh4gLQTzikvFoxg5kjmFFxF+QOFakT/B3RMa9mgjtOlX0boK
+HepTxOtCaS+cZnL/fUCbWdnPxqooKid2DnVTNIXXBg3S97ReediwpSn6v6gU8QXI
+O0X/+syPkCRAOKLjCdgxFXRB1UA13v6iqeja9aXgzbUnk/MrT6G4ivAMsNS1cEdA
+KVKVpbiKchEpiiSiPyo7buZN6t3m4JnupU+UvcJAEFgdbPvP/kFvxywpPBcAycAM
+HgujJ9bE3OR1lfyHHTGF/f5lXGDzB0/ND8h7Pm+Bd0AFde79rCswhnR4oJsPLuij
+Uy499ouKhoxFTn3WMF6at2QLf36rfLHl41uSN0tky8trT9SE1PjX6yQUjl48bJh3
+MWUFPYBDfDPGTddENYo7hDmwoSLbE5WFxbAeJa86wgV/P4/QcDF0IPVa/wsDTPKR
+RIy7eNqxXBYhFeOBCkTKHMJ0XCawi4q2CAwo7RNuAmTrHOBN2hZOwYd6yoEQ4ALq
+70cflG8+rITJHOdAjXYAlcuuB1FjDWJjO1E3P9MwMfiFZBnJBsYkDT6ablfwgpaQ
+z9ngnzRqxIjqAxrRY9GdR3BEWgRIiKXljUgkk8qFSRIS1i3w+nHAipreOwizTVUw
+otTU++EjpQBracFsuGP6w9vcyhHOp3K+RzGYEQoh2vJm25lzUWBHvmVpCw5BBTms
+RgurNRdm1IlN+qSzriotjPuHr9Ucit7VFV/gXtmyJiNNPjTLpLQEZOUpz15eaFs+
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_des3_ofb.pem b/samples/rsa/openssl_rsa_des3_ofb.pem
new file mode 100644
index 0000000..dad36ea
--- /dev/null
+++ b/samples/rsa/openssl_rsa_des3_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-OFB,C8F1482CB09D61BF
+
+0GfYpcSxvnnRri3s5PutcESsHTuupx6UcprKRS+B1neyPR7Ga0Z3mZ2/X0trJVpM
+cxJW4g/cU4TknCZLjIJlClYQenpPRH69yw6BTi6/pgUhKeGmQK9Oob6G1RMjS9lO
+MTb8DKz8P9GmDR4/3SvJwPU0aEM1EAmwGJV2beB2QWRhaPkAZBzeijYf+uYn0mgm
+hZwjU8tdwnNnCdUXdaHeRkeqFcL6OjJHV+U5SZaMbaky1U9lyIJL+GUQZkRfZzJD
+41Qt6yVtetTgzljtCtd4ix+RX6EYsWfZ3OVtwHGYpg28IdfJ3LVE//O9EkLZoBeg
+DyU9c0gDnQ8Dxl9VHGFwQvgdSEyJLvWDv+6RXvCX4Kb2Spy847yxqcfqDpjUhzgv
+C7FoBwswS0pkQzGXKgdM+WlBe9/GYOrzW08IYwrX88aihf50jXi472th6ILIkFHD
+6m419YsrmOeEMXGW/VIKxk8H8MGHwdvK82xewu8Ftgfx0WihfA70EyI28VLMQTAE
+MMHxxCWtdWWnmd1xiHQSX6vedPLXQKKt2AYxYmHQYfqNFMcvDc5uM5uM+mNkX0qt
+VL5PeYRYtdDtT5Xj4/acZD7X7DhqcOwvNll3J7PRdadNXKfjHR7iRP62YkIiESE5
+sCHhYXmtQqK2JUJr8a9M1QPhmAIF3FYr8wSFu/eWw8ooBaTxVoGCw70lT8LNHVql
+TYdW9sOnvUjz36oz6H+z55CNldor0tS/Bu5jNPOZ8F6j5r4xpTWi3d/UWLW7uBbw
+VTAG25EiFvQBXpJFqgRCBdD1Gcfoc+ZefLXQ1l0RJpRf1jJMkfSWvUWDRNm87PSs
+qTeDBzuLNx4A1wYcJ1H+R7ds5QK4moNlvv0hJrsqbOESpLv/XPcYrFgzms0b+Q1d
+uJEWjz38AgIJQxBxmoglzDSRx9OBh9D8HQ+aJLSVcz0dBmEOEtPjZn2AmxxccwCc
+NkMnAxXyNPEJhecTp2/lOOupQqMYTGe8aoiee3m01QPzfgL6m5p6IJdKzOKi0TGJ
+xNW6fD486B7i8d+VOnst6vnd4xiQ03gNNA654mrXIM881X5elqmoFWyup+Ct9lw5
+lxllAJGh7w+hf8P6mIsezOkZGieGhzrFnuLVM2srRDEId+shTV/0lZi4LhfDYroN
+VAbZ6bySn9fmP4Pn42zu4XjoZJffF74u8gFPo8oSFYg88tzjbPN9KAPInNxD6lBA
+cwp3vc1n71CEepmfeZFR6pm1wKRSupkOZNL/PV9rqsyP1pmPE3AEU7WYjNbf2ah0
+GE9f6dtLWcDP/3SssoSnZGy5SdqcNPymG9vOR+QD12YNxn7yA87HM3+swparlSYy
+Mhg1BuDXb5Q5XFVFdajFwAnXJblAIbuJAeHQ/mNCAnR3HNv/Qic2GF7X757MA+dP
+z86gFzJJtb7dtZ0WDQzzEVHgnfVHP5buXnHdepFLsETw9fp4ZjqPfHjLXIOvp9/9
+G9pmSzB1JL8kK8sexWgsMRnl2j2hUDYiVJ/LQjMzk2YLF5I0D5msNTAJvb/gFBdv
+ynVKUpIoJEfRaY7pxR3tufbzADNiqa8OUCGxZ8jo26j7XWDkunfGAw==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_rc2_128_cbc.pem b/samples/rsa/openssl_rsa_rc2_128_cbc.pem
new file mode 100644
index 0000000..1763340
--- /dev/null
+++ b/samples/rsa/openssl_rsa_rc2_128_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CBC,C9CEE2FFE7D795D6
+
+hcUF0vilpOxap0mbziQfS/5kPdXsFb59D6myNYdLDAvBWUVAuu5g8iDDJIS8KPb2
+xvmWdXRhbsnfeQGcGWM1rMc7brutqefFp/OAJVymI0TpILMgef0abf49PEqNUa/N
+rYs2dd39fsyrJ0rcEWT2lBA/+GTLATB+16/9aCwjHjQ4L7d4Soh1laMo2K2Us6Eq
+pB8f6an5Y/vSIlnljl4upKOlcLItd//2ehQnkuEhI2Vafz+kX08Z3+OCLZfdNEq0
++8b5GbOvygEZbG+amZDB/tXnR1HB+AI7lR94PmM+h24COWAelatj2uPOGov54gXc
+iO7NDGoouysqfkfcMpuy5SkLVW4FoCAxfOl+LOU9p4x8+iaJt7Np+TO16dvX8MOL
+4WcIz4huaT125V38Q4UiB+WbsvQXrHRM4WCyJBGBhakr+FpNFdH1UPb9Unb+8UQL
+BeddEGT0l9AiSebT/JMKgFUOInQdKxOjg4NBp3asVEUeTGLeTN3o06zUoopzT0S3
+CHrpgvpZLf+4NATrFMw0HkcUK4GHZl/Q68C67qNGTc4B37eGcxzGo8QOyjXzKxL8
+Lh+Ry3eJpEXae5xDUn9yt8eqYI2vdwjA/3+XE6mRhu1sbPNJCcWo2kLZ0ibYgqdB
+FLsXBT8aoeKrW2p82OpehslbmswOKZgrPRYmNh1GAPz2jwBFfCEOLQYXAjCFViiL
+ipFLKLGt2dhjk5RbCraN6eYRn2XcIai/7dnaYxXkjOsNH4mmPzlzjhvRh/2E/r2Z
+hbTOoa2uFUtZHWtDXUz7ZzCJErJaA00ont37BksfHDdDw1HIt4z6Ut8Jm1cR5zPO
+pC7s7ohOS5j8Vr8j947bEXITC2ozcvVVZOCcHwF/PnUE1zx48HBp2m9NAZ8Bz3LS
+Zn799/RrNtJLnkheG0wIrizk72M5L9PZQ4FXlupfJ9c9XniaQ23GQFszagceDN8j
+z/MR4tTfdWRy/889lqZ6ccNmPAXdwwijC6Tw6V9HooN9m3++ZlbPfHpboQUp6+V0
+Wwq8gdnlYW/i++9n251xBsR7mQtFNXaYwFmLUTt9C8OobyWSsX/OaeQGbWiVnmAv
+vPkr7mh6g0ha/x+1vKgEOjqItJsGdspf8ePHQ3FaTkfFwhQ4eN9w4QR3uzM/7fnj
+ql3yA+G8ftpaU9omFbs+VqIVNej5tvjODQ02BbjSuRklAGxnReCS14vLwjg9BV6t
+Ow74oIttwlZof21BWsCISgybkPmMhkIhUNAAkHexzY3AiqjAtEGnpmvfZAX9zN8+
++Kg58DxudjHQwUO4cwP9p50NndrilBShkotdYIqekXn6h0frYuhspJVWwIVswNjX
+BuEZE5B+Otswbt/caj9C5tfsyKmnGToG4fpDdk0ItxRq2126crKQd49zZybyR3zR
+phLeduyS5h0oYNwTjq+Fg2Z+f6d/iyCAE8ynfqcAPK1WpM/02DBoLsOmve5BCSPB
+YYKdrKfkGbj4J2klrptGmqgctyW5jKGddE6NO4XFYV174rsdPoErNWWcfptHEMLR
+BWfopqdN/HMrpRLTkjx9rIeBJ0F+wQEEH1JehnWExSSSAhm/gzQc1kU/wihOStU4
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_rc2_128_cfb.pem b/samples/rsa/openssl_rsa_rc2_128_cfb.pem
new file mode 100644
index 0000000..4284fff
--- /dev/null
+++ b/samples/rsa/openssl_rsa_rc2_128_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CFB,AEA62B1564D645C9
+
+NX4iex15O1Dwp6ADN+uFIycPB1ELvBDVRGh+OZnisNU9h+8dPO1cb3j2tkwLFK4i
+Pml4zz797d4I4GqdF2Y23dz2AoBrl2Lj0N0W01AlOGagh92pZ9dKjjU+S5N85OBw
+buDbADh16fSPW6Y88guWFXYBlGJ6HZFK/9D4CZmEfI2Pt9AwEIZ/JvWrs/zW5eGP
+YMFsLslsNu9TOIKF8iDnfcWM9MFpgwcFCIqTwyQ/+dka0hw33WsBREhFcNleLxhW
+NKBIMC6jNjpW916IClH5sBu7T8ps/7JVw4DUfpl8NAOaqJSicPGpZrGIZ9N9cfLp
+KD1XEy+yWc9ahV0mfiyOuzNnP2x9IEBdrk5uqJwIT9RuiFZixIH9MRuqAtrA5BIP
+dc2kw50AbXRghE0JdUEFfUm9zcRKdG366SgADnteNk/77gqI0OZJDD0XL9R/N3Tn
+uh3EI9joJciWDbEX0/751MfcLaa/EkI7quKMEyFGWvox9sKLLEKRUV6SfO/YX8ZM
+RV7ebJdW+Mxya/beG3Yb9TAYkrG2TT2+uhRqZlZllJQFnX7k5MxyfN5I+WJP7SEs
+Uy5PAkNv3h7DTV7dBFMy/gPYAooY4JzBnbq33af+w/VbhyhVid/hn9UAONahw7H/
+1Ao24IlYMza2fJ9yOn+ejLhjvwYIP5992cmElneqMdBfV+oaQTHtWUuVF6g4gJBw
+9QucqxH4JbYccwA1UiKIqkmOlePm5I57RbBw1OG/Un3SiPcAwiAW/UpI5yv8kNwq
+kZeWnD79kMBEW2pU1CTvf5f8aBmcgQykC0M8H25Jj2kVvj0EsRGx1LuQx3ZCSM9y
+sZejgZouYA1WuZaIsz+3t4fgYFiOHDxmSvPt6VtZAMJGmLB/Xa/PVI4rsyNv99wB
+UinlINhzeGKpYYHnUgN0PrRQl0LBR0TdrJ0eG1djEvflXsuAQVP7+gP+oCckkT2c
+pIVm2IzplT2wzsza6+o1SA5BF7RKI3A6IxySFEBJTeaiZnYeeJHxE2DJvU1Fe29G
+ML/lM02waLJNbIs0Vk/i+hyE1wtMwZetptG+En5TDzTkWlVSLSqW6LXVJ53J2E+q
+wypuz4akL8CaYRm4XTmIH3Tom3qSf7rdbL9gk8llZacFNqAl7x1C9zDUzKU0DAOg
+qPKAtD1s7Rtg+4p+5cIEAWD0TKX6DlXKC/EdYO1w0vmavGSvQrr+KENE4+/gIRst
+qlTCiEW2U+PPyOgpZAFF0g5y5Xw0Fea/0HwBBLfCiPKRmDHQIzWIEW7RkkNfQlHC
+iCTBoMRFDbwXJEI9XUu2N4RdmlP+84i6fSRWuzZGUACvzEnRJEc6H0FaaN+fX0wM
+Op5O2hcdA0YTGGmTLUAeajiQnqGRobC8jQL/WQRVwOiFU9rgy1K4Cu2T6eBubvVh
+gk/R12LezvD/KwLgQz1+vXa5Vgjp0xhpnLnJVzPqLG0Fmj3V4uRDc1Lvvl4uLJiR
+VFjFYlqxP6w+ToRqnrfbmUCuiq6pS9FQi2Tghd02P5TnZcyS2xF2X7o45gegMplS
+skPzTCON8140xpx6Flep3bHwzEI0CEwO8goVMc6x4a2Ggekjn/Nz2A==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_rc2_128_ecb.pem b/samples/rsa/openssl_rsa_rc2_128_ecb.pem
new file mode 100644
index 0000000..d9609d7
--- /dev/null
+++ b/samples/rsa/openssl_rsa_rc2_128_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-ECB,270AFD04879E8434
+
+u8jYUJhoDMDNI5cHXhnJJ7Pm0lF+MrOl84maQOwfwZ5hBbjpx9s+z5SMYpWfz0yQ
+WlgBuGkaY1UNBDrwH6baA9/eqUzem9ZK+mYmjKC30OaumjKVJIB7cJfJf6Itcaom
+SH1W0kJYeDn7ANdmstOGxbr2TDCr0BXa+7j8cTo2TZX1rfsXcdmjQ+8Qa8zfQ3Q5
+FbrO+VNmAQwO7HeFjms38+ukJRW30EPibmbzx/YTCZ7XtCsXt6t6ggYja9Kvk/eI
+khwvFFk4g6Dv9YU+x2pyrkquIiTUo+jm3Vqhz2m0cGcqfynVEYn4fNPc27Ekw3uj
+CrprMgnfaX8QVx/EkpDYp7gpjcLYJObpUTcBo5iA7R3lpQ8itY1Ky7u6MMwQ2VHd
+XZcsS6b06mp2EW1CO951ZaPyma4AqoLl2gZ3zH4qPygp7uxrGdFdFSqrapVkDee/
+lLtj8Z+/g1IyVSIW2FP/SCoustCHcqeDDq70GKY9qiahNFybWn49vZAPB3HPM22f
+mCcw4ALiKr0S9oofxrb8PKxmDQMZAJqjc8qRMLktYh9rJLMoUG2bmQqpKmLLpx5q
+3CaKi3wofc005VcILyRgjumscAcpbTEz4vcR4jTwMPNP+WI8+AHtg0OcF+7hE8qc
+a9KTSsx3eJNbqq5UYxVjV/DcttNx9ENllnG+jEdttkaf+T9rJiayc0WPd+Eg0XlN
+ByBG0RCPQVJ9YH1Yke9HGE0FXv7FV6x4c22ePePcyE6VUNBoxdmXw+KRhRlvtXtM
+1fFMwUrY//jEpfbf193avTVVctDTLxDSmwY6eAMBm81uDTlpUm0q7l2rRuKzdgFd
+bG/MTOd/j7wtKJbQpbUfUNFtF6zjssPdGhJ3l+8Rg4xZyHWHgU5FYGodp9RsxUhm
+8AzoPDcVbbvu5YlPP+XvyEO1860fX6iSZKuOV+owjh2i51CPzsgX6OrOEb6/1rc3
+M5AkLVl4insmetdTqb9PHCgfD6bLYcDBj7Qnf4HEDQUGcRFe+jogOoSH40C5UgPq
+F83nXv6WYBb2Y97lhb44x7d1MzE1kkzQXlyf3QuZ0ZjOvm+LuOWkbQWmLj5JhFJv
+9CqY2MBL39EFamKjmmBmjrRsI9XMLHvB7VvT1hJPzxbF3UwDZ5BsA8IXSps0EjXR
+rZXSwo+vqTa3NlvysgvuJJUjwyf6mN2SVrNaKnZZ1OGFY1oQ3bmOgdI+SW9cpGzY
+Y8eFpaG2RAiOfBZ0JIyBUoHUH1MMMPw+Mh7KzIknP7O9htwiAWEvkcjWr7X6jpG8
+sBdBmszX3TMDTToQ6DvyjVRP7mJ39dV83bLI3EA+N8bJcTOcHijCvbzQM50WzMu1
+2UA9e6rG+ouQAgwaAHdR6bwm+Zr3e7MswZ0Q8/Snd1UdpyMyJ9nb031NSRSvkEyB
+ipu85/738J/g7tAIOJwwHeVWjL4lnrLC3CwbtvWAQ9Ox8Sjv848608GzQxFwHBHJ
+0NWgt/AfLYsq4bmmFWtqvqTjWeAeUsM+67UY8m6/kxhfRNNN3zZcckq2zlF7TRNU
+5AL/3KbVVLQl/7fD36m8AK5eImR+Gvom8ryzNacbNCL55ks0sycbICulXbdb0Jgm
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_rc2_128_ofb.pem b/samples/rsa/openssl_rsa_rc2_128_ofb.pem
new file mode 100644
index 0000000..cafccf9
--- /dev/null
+++ b/samples/rsa/openssl_rsa_rc2_128_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-OFB,E5989634C878E65D
+
+6o45POmHfE72UAdMBQrRIm2+oZCd8GmkmrFZMXYnVWP8ciNiGVQqUxVJS9j5Rx17
+8qxpNrzvcWEGWcgs9AOqog7YXHkxo/s/RIOKjUu0WhY59UrYcbkN7Rjyn3wSSD8X
+kN4Z2tz3iR8LnfljD2ApbR3yEYz2NvmifZzsac58R3LvuFg3Tsl0QetPSC7PfMUh
+B7dezaycDcx8QJy+nRPcqpGzeL/VVk3F4Hppc15gfdWtVellGcYsT0Z2Iu42I5nx
+HYFajRliBukH98M1d905lk1aNLDj54BBcq08JsDJN/V6DY+mUpJCFOK4DfP5WLJb
+/HCQg0wqsUmRHK3dVo09ilZa4OfrrRD5qTWr5boDngAqyD1r1fiHxcv7uU/HOSvt
+PU53frz38BA+w1pHtlE0TSG0oBe/+741kJtpvj/1Ts7nUeYJ/DGR4vmLpg4rnbZJ
+Yky5TaDV2LVLFR4syqombb3eiK5xbnjePCQFLwxYLQKZFINiS5zDr5mdjhWbIhpA
+7wg9BKNpUeXRDtntWXvEH9FmyIicbk670riEYEo/EniwrxW9f7MFhPUpOb9ktE56
+RnaU0EK9zUx1sIvcu7LVq1G2EVG8IrOKGcj4LHysBtg6PQW5mvN4AA5PZlc2Sux4
+L5Z6mJfwgBbBB4OuRXAYxHZbnfMTs75vL3d/HIcvSPcvb+7nfvNLiwlaBxaUfBFh
+fyDurHkMG6tBgE6OORgWraNEINJeOYcG2WK60qC4E8YfYCmc9V+28A//bsyRWyku
+xIDup68r+Os5RMRAaZrkIqaH+h4Oyd5RqcjLnAFF/wLGnNwSttYT8o7WwCf9ZCCy
+NFvHDWyWMUxonaWgvuSm9YPfh9/9CEsHkKh2RqBffFcZ1ktEiYaI+dGyty12QW2Y
+909pnCZkKsm1Lt3ts/xie20/gcwfsnvUC8OveKPaiCnJxDv3r9pMCNFPdcXo0GuR
+oadhn9r2CqNCDo+l6JWVRka2t8+yCAskZC7bKJnSeKlEDyn7A/2SLb196G2k9cve
+V2qQenhzuHmG5PEVfhLWQ7fL1BmJcRDuQlSmMGrdmOD4Zb0Truq0zpFL2qaMBQvb
+58hG5YkYehE25j8PpJYovOQA2hih6v9RytR2VKlTeYNFbREf1sdLfeIphB9tlHlp
+qZ7eOFAjjVzLsC4LmoCzWMaQuwNO1f3WiNdGVvulHkWqFnGS9bBBTahUUWI5SYiQ
+90vhSmJ7R7461rqWwn34Om5jlgRV4+2LhUbp+XdOyklujQYviHsOs8/wlg3lKr76
+SwrU5oYqlJ7FJoDq4IPpOnJaxsRjkr9foecgdqrU4SJKyJJDbkHNfoYq9r/aZJ21
+ruPFv5t021gJmWa87199GlhBZD8dxeXo0PT298Y3pmaaSdQIWLPeDAtc1R9EJLwD
+6+ydhg3ZVtSgXU0zQ2SRVMGhqoEXHDUrMtjKzuaZsYL57tqH6At6vWS+xA0CJBCw
+7GkDpM/lLGjyisFEQL73F0YmJPpb5s4izzCLUMxZQZ3u4T3f9OPRvAIUf8MiFJxh
+RJq2Is1gD7M8+dySkFeAbQ1STvLy29uIxKTE6BgNng5NrY03GuK/5A==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_rc2_40.pem b/samples/rsa/openssl_rsa_rc2_40.pem
new file mode 100644
index 0000000..5a9eecf
--- /dev/null
+++ b/samples/rsa/openssl_rsa_rc2_40.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-40-CBC,BA10EF99A1862AB2
+
+/CfoFtIX0zgNckXzuODWoCYVY6NoXOvu1jt7J5/BfSZUydRWKa2lpR3SWAUAesQX
+H/IK9Wkz4um0QgrHy2fmVaAS1G3ifwgQ9dhW1EMiCEAmuNwPsT2YBatSyxnzWjHa
+dv4eZ0Snk4DsS/Ajwn+Oc9uZ3u5gKnfYk3tXoZ9BDPQbgIz01UI/AyGHttB43brl
+e1C+zKgCSa5WB8wfxCJsKHDSEHx+qlipVvDk/pntc9m4AM0sp5wsHRw3i1iirQOw
+AG6qRs3Ro3jwajlEWPmJolhbRQWyA2rUfSIajElYFlFgxPLI10m0tO5M55VYXpWe
+cprQNe/TxK+YJTcBvyhFmP4Ha9NeC0Vq6aHiECpZ1uObH1brZ1bdYUsSGodRzGMC
+ucOkFDpsp9We48TAHqEGArCsKexxe1dDe8b+cxdvyv33ZI7dyr7DfHek3X7B2rHv
+tZYjgx0cKn8SNl9qdRync9wLqjL2R99sHgphkXUA7qLP7ZdvZEeAGs5NEuq5oyDj
+4aybPFJu/xvByOEZBwEtrixVJ/2h4KYF6g2vK5CgmnYrq8SUNGobt+oLv3FywKhQ
+AK/YvDt97wXNdPNqPciqCP9LIeo0B0cgxFIbOOE3mvYgPaUoTtZ48B/hpkY4flKR
+U7opVqbNl/pnh1OCI1ce/K5KPw0rvYgsEQ8Q04+dipPdmvONYGhcgHflS52xju6s
+RbosS+iET3a6BB8ydRS8V4oezbr7AgzoSv7Od6geru87fYpVW3WbGag4w+Xgil7u
+C22epy/AX8naBOsMa2QMCZ97avi/qhMFIERzhQJcxULff0lHQBq+HMGsSI8jMEiH
+d2OIERTWasAEPdoBnELO3l4oywb4NmSp09m9imihdgocDAQEXyLkjmRqkm5H3Tdm
+ALFIaSwU5SE/dk3T+BTmnfl+Anx7QNWTdg+ykfH8VHbs10A/K2zt6RyJGLdStfKq
+VWORUG7gYcVGIQrcJllxt3Jt4sG3t3rSKA5dukM7+D1d54ExiJN5DrnaQ4kX/v7O
+nENonLRtV1KqrH32R+tIuBVA8rbmyseVequTBQpkHbG/IczTG1k6p0Qye17XlnPl
+kEPE3CG8+1RMLvflA1rTimSh1WafHsDwvwmTAgdkG5btLlfTpPnoKDy2hPS4Pd0P
+mF7OPVfA0Hl/oEqP7bqyUxuwFrz7pZXQrKDS02nXaqVAP02nKsiEUZNo2kprAO2v
+9ceOhXP3M+ItlWeNcX5jKRaaLddQvj1ntOKqDMfRk4yWm9ro8/E56Fkrq7GpKrXL
+FCJJTdrWk6EcSfI6grVjPbZGBJiA+21G4IPQWskPkr9gLuE0E9I1UAdliYKXOrPK
+F1lZ1ZBpG1ZBe9H8Gr2sK42pzJoFJsOvGRjCxlHpf/gBoOADH/hcxvQqBGizEr0F
+kKraZWJnlL8qhDzfJ7YLMqzFsOu7uYQRqfOcv+66FqT/by9rD7dR/M03YJReupoL
+lynJfffGCG6aeM8hLZ8iizjIc/RzCY0QS4lLPkRVSRNt3Z8RNX/nFuYhYgOx38pu
+6dflN059kTC5iyjsI5Ka/Xzq69kR21qCcHOoq6IQqZ7q5RM4Cj0SCXw8/4jeT2xY
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_rc2_64.pem b/samples/rsa/openssl_rsa_rc2_64.pem
new file mode 100644
index 0000000..7d09608
--- /dev/null
+++ b/samples/rsa/openssl_rsa_rc2_64.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-64-CBC,DA39EAD05DD48A5B
+
+mil5OpL9dVqnEoKF7dNjIRYLgDjCBmTDZ//Bmkd4aqkPszHaCoQqgyGYOuqWXdT2
+FAluu/fHMLDTizyr2Jh00ekcR3nmnGM3B0oDiEtq84YMHPWYopWkpId1ZaoqluUe
+6NP6Zew4DZ8mEQvOxIxBEZqk0ye6srtLszByw/dTy4i9S7l4oR8hx1i6Jj9lLXS1
+y24lC68igFNeIecggG8uwZBVmnHCldZGn6DBBqcC0b415+59vwGuvc+POy0Hog/4
+ADPuZcXEO2whVGyOjCF7CjhEFfo0CO2niwS9PiUIYNsUluwfS+y1qhw4VJ61sQ/q
+7cNHrD4NfZHGwpIRXk4c27YHS+JsxH8Kh61e/dQPoeTf5NBQs3PthFcx+hzlTBAq
+VK/4TtRRlnqTVFKRydpKo3cNGp8qm9Kvz6fr/yLb7CJvdoGDyHVO7JvT8nYL5gC0
+dvN2RySKXMrgmPS7uMAWjpnDCdNoOX4pRTRPEdBw8WsdXqnBqXM8tvrkolF9n3//
+lldN3sSGLiYM1cwD4dXlYJEJNaarelHk6vpJIU4A6gYyN9MQnv061jd7sibrTAjZ
+Rx06R0FrYFbfkp4yAmUbrPO5gdwZPBGS9XzkZmZr+S4u1fH7tTFxIlWNgxwSzsZJ
+P9LXM8Iy408gDn1AJlbT7WbdWfcFzqIsmauRIXE66TloS+485ro9zX7O27MumF8S
+hjD+cRMieUEREuAAlpNxZj5kcT3SpxfSdaAZtJv8OKeRHz796LRxlLmx3ZDAjgN5
+0H37gSCXJDP2a4YnsiI7th5fNba84t1Qt4Q36v6EZT2kscv0TB04ov1+4UX9jCQI
+zn2zxzJk42kkxRSEBP3BnZf/qV5t6/+BKmg1QGCmS5AkIIlCDjTPpAom3n7YH9LV
+ykAQ6Wcdo/7dGtghgaHbPGl3cXR1u7BI97GCU4vzRbW58ULh7KSC1xptDJrP7tPE
+6OwwYk5YZ6lmg54cLbQcxeFwYQg1dc4pYAgBppUFUB/uWeQrbJP8/FN/GlW0HTOU
+kUIz5pbI7nstb2hHrRMTtG4c0oGO1ACD2LigQo5Cl7jR0sBC3I2MB/JcBBwAHPVP
+tePpIdSAZjAYI+x7LFxxXvT7eXe+BU4ZLGLcTISGJjtsbJG1oJ/e7dPP5bLL+zjJ
+MrwoE6awH5GKOOxB0iUGce8jg8566qY4e2vbmVL4a2qRiKyLowr7Lcz01VzzE/RX
+0Ec1I8noUmsystH/57UMBuhZNFjW3LtTaw6vuTrrmFtdmJcGwars9tBtH0LPip9X
+xQbwIiTJZCyDjql7Ecgu2ncw7zHZzbHrmoEF7VEdPT4z21utXgzJ3HubvB7Agvyz
+sB+EXeUqwZHnyN0GdGd6sqlHkW7TP1XxMrjewUHjXuY4SvsosJ/GqMY7uKJXK/Lt
+0kqYrV/YDIVsJ2JqyxwXYYIqmZfQ2xXTLuESuesT7omKFh4cgwbYHd33YWRCsZJB
+7Og8d3ciguWDutd1LOgx7da2ZA+3UVz8X601GRpFD8YoZTo8QOayXFvv7L1F3oeK
+b0w11lT0npxstmeMQUkbxAyCnKrwpQagiwBzKlr9ymJvh/ot6sJ5bAFDvZBBKkQU
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/openssl_rsa_unencrypted.der b/samples/rsa/openssl_rsa_unencrypted.der
new file mode 100644
index 0000000..3bba408
Binary files /dev/null and b/samples/rsa/openssl_rsa_unencrypted.der differ
diff --git a/samples/rsa/openssl_rsa_unencrypted.pem b/samples/rsa/openssl_rsa_unencrypted.pem
new file mode 100644
index 0000000..f540dcc
--- /dev/null
+++ b/samples/rsa/openssl_rsa_unencrypted.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7Plp
+gpjUg4pNjYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc
+8BQcwHf0ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTj
+HE5t7iu1JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindx
+OSAnAxK6q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfD
+HArDqUYxqJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABAoIBAFd6vTKVVT0O/U04
+wTtiptA/p7fkDM5PHVBxh32Wxno5pj8PerIaiduKyuRVh7PvJRMJpw903BrAK95o
+847WWOVOaF7TcKGMBURJUS6maiJS7TboK1ZbUVnsg/I99ArhiVUKGDhlsl/Xd4np
+YPDYztzXLzLXpm7bS6CiuvP762x9dfVu8K+afP8cjH8pfXLq55ghZOUKidRQaYz1
+mNOTQyAQlCQdLRgKlYgqcRHlj0pb28XBJaln3W7Z7GFMWFPojkxx6LaCp8+Jyx2C
+tv54zIZQhMjF37tQyTnfK4Ocl3sCRb+jYV4FkrUnsQE9W2dey0Tms1XB31gfUJlx
+dRZu7zkCgYEA/nWcTwzot2OIAhXoJ2fnqTcpdmj05LHhGcayKjyix7BsVH2I0KpF
+9kXX066tr3+LxZTergl4UpWSl3yx/4kPBQM6np4VVRytn7+cQdEhOczZnBw6x7IZ
+fv81DSNruQDBRAlTtklW4KBY74JKLhaJSvF1F3x32+H+99i1MmCNJRMCgYEAyZpF
+h4c3pM9z+YlmgLdUh/G2abdoamugcQOFbzHbZowsRAxEzdEW9wj2McN6mt8Rn1tc
+tY/+PcYuIK+vcmk9k23GuzxRlJlkaDicHwlAebgVIulFcrStfTlSkXjpuOuusfD9
+2DuHMcUiPx3qElNB0dZJF/axpq7BjTIFENefhZ8CgYACn+vw1M1BtwEcJGW0olm9
+YRhIZGTCRyNvRKFp1h5HuQYlCPZ0UI1QMQA86rxX5xTmANcbLHXVRD2y2lJrtFo3
+TwU3xaGqsxUHZM6TzzhshDRqa9AfZzLkIHXHoOnnip5zuTTn2HHQ91ZzggCJ4Smh
+YEQ47cu+tOIQZGfaESzjiQKBgQCCfnZlDJRq/NFwA40y4fg4arANa+eNgw7+OC5F
+1HrUvQTmIx7iLmZ0Dvv1KDgTSTLJ+MRgzczexYoUJEQnhZGS/Wq2xYt06XlBsOr1
+d/KhFxOvXllSrzrhJJqaiS6YQQ36JijZr2aKQ7UwL7fUlsmy/safWVKStumX8Hmw
+9jFOtwKBgQDmtirdNQ8aKolokD/3bDHPcDsNcybEpiCu8BIltxZAs/LsN1IIxfcp
+mGP2AFt3mbblKbsRM8hDW/X9taeG9s2KGe5wlKOE5lV8YAo4hFoJYN2/0d8Y0K9X
+QAAYU3iPG1zL+a/7TFLJ0u/biqsBg9hnNbMnN/tOeSuKnH2Rx9F1rg==
+-----END RSA PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8_rsa_unencrypted.der b/samples/rsa/pkcs8_rsa_unencrypted.der
new file mode 100644
index 0000000..b092957
Binary files /dev/null and b/samples/rsa/pkcs8_rsa_unencrypted.der differ
diff --git a/samples/rsa/pkcs8_rsa_unencrypted.pem b/samples/rsa/pkcs8_rsa_unencrypted.pem
new file mode 100644
index 0000000..8111b0d
--- /dev/null
+++ b/samples/rsa/pkcs8_rsa_unencrypted.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIY6+Wgj6MqdEd
+Yq6FgH5xMgTBmFqAonR/eshjxY2C6MHs+WmCmNSDik2NgZWIaODvOF9uOEK2U0Zf
+JEG2LcZxoeIEgg/mfII2f4DLy1JYajm/llzwFBzAd/Rkcs3qwP2ba5VKn/pSqNLl
+nKHMXkXO+9SjfHDx95x2dK1dB8eGQGculOMcTm3uK7UlWNO4TSlwG9qHZ1aoM3GI
+g5C1fIpbxJqDVjFq6fFAapE3KRIWIQmKd3E5ICcDErqr/AapxnfO8UFNxVWSOLW7
+ZAfis4w/c8/EAgyQHw42R0dNyjUOZsToF8McCsOpRjGolSU8aUyqspvd8IWJPd5d
+6HBHueXNAgMBAAECggEAV3q9MpVVPQ79TTjBO2Km0D+nt+QMzk8dUHGHfZbGejmm
+Pw96shqJ24rK5FWHs+8lEwmnD3TcGsAr3mjzjtZY5U5oXtNwoYwFRElRLqZqIlLt
+NugrVltRWeyD8j30CuGJVQoYOGWyX9d3ielg8NjO3NcvMtembttLoKK68/vrbH11
+9W7wr5p8/xyMfyl9curnmCFk5QqJ1FBpjPWY05NDIBCUJB0tGAqViCpxEeWPSlvb
+xcElqWfdbtnsYUxYU+iOTHHotoKnz4nLHYK2/njMhlCEyMXfu1DJOd8rg5yXewJF
+v6NhXgWStSexAT1bZ17LROazVcHfWB9QmXF1Fm7vOQKBgQD+dZxPDOi3Y4gCFegn
+Z+epNyl2aPTkseEZxrIqPKLHsGxUfYjQqkX2RdfTrq2vf4vFlN6uCXhSlZKXfLH/
+iQ8FAzqenhVVHK2fv5xB0SE5zNmcHDrHshl+/zUNI2u5AMFECVO2SVbgoFjvgkou
+FolK8XUXfHfb4f732LUyYI0lEwKBgQDJmkWHhzekz3P5iWaAt1SH8bZpt2hqa6Bx
+A4VvMdtmjCxEDETN0Rb3CPYxw3qa3xGfW1y1j/49xi4gr69yaT2Tbca7PFGUmWRo
+OJwfCUB5uBUi6UVytK19OVKReOm4666x8P3YO4cxxSI/HeoSU0HR1kkX9rGmrsGN
+MgUQ15+FnwKBgAKf6/DUzUG3ARwkZbSiWb1hGEhkZMJHI29EoWnWHke5BiUI9nRQ
+jVAxADzqvFfnFOYA1xssddVEPbLaUmu0WjdPBTfFoaqzFQdkzpPPOGyENGpr0B9n
+MuQgdceg6eeKnnO5NOfYcdD3VnOCAInhKaFgRDjty7604hBkZ9oRLOOJAoGBAIJ+
+dmUMlGr80XADjTLh+DhqsA1r542DDv44LkXUetS9BOYjHuIuZnQO+/UoOBNJMsn4
+xGDNzN7FihQkRCeFkZL9arbFi3TpeUGw6vV38qEXE69eWVKvOuEkmpqJLphBDfom
+KNmvZopDtTAvt9SWybL+xp9ZUpK26ZfwebD2MU63AoGBAOa2Kt01DxoqiWiQP/ds
+Mc9wOw1zJsSmIK7wEiW3FkCz8uw3UgjF9ymYY/YAW3eZtuUpuxEzyENb9f21p4b2
+zYoZ7nCUo4TmVXxgCjiEWglg3b/R3xjQr1dAABhTeI8bXMv5r/tMUsnS79uKqwGD
+2Gc1syc3+055K4qcfZHH0XWu
+-----END PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_md2_des1.der b/samples/rsa/pkcs8v1_rsa_md2_des1.der
new file mode 100644
index 0000000..f60e902
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_md2_des1.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_md2_des1.pem b/samples/rsa/pkcs8v1_rsa_md2_des1.pem
new file mode 100644
index 0000000..acc262e
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_md2_des1.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQEwDgQIDKNx1mLdfnwCAggABIIEyMSJNGKOaf0rxVG7
+3es69KrcjE7RyU1RRy235ByFV3zmqxtv0QhPvIMxJwiaoRr9SE6wlzKYU0hiCkB9
+ggYeDQ7kQ1a79Gs7EPEVcevN1DpHMII4LW1XOMSfWLwffc/oETiLbkgPQxG0eEsA
+8z4/fS0k8tEQ6AOF4qa51UdORkfExRF5Yyv46fsUs57oCKtqYx/IIVPcSg8Ec3mz
+M+Zz+f820bB/vN8ge5KWdOalIZohYR56nPouPnCtc30CfHfFqTfJajFYLHCPKq4a
+yE7h/u46zi/T6Wqwrua35MLmD9ne+sPN8+Hxr3hlCh8HhYXroqr7PyZXcDbshpEM
+ZgVkrYIq4C2XXByQqXyYX0lO4TzhJHj0fhG1O0epTDuyyvQniEbD8lZFTc1xUnh3
+WNNB18WbX4Ra8neZDCNiJsIWCdQ+TMA80YPyIbP97Jo4zIi7DJciwHotSFyWYa8/
+2ROdcV65IrzKuF3w1ssJnuKtQ13Ku+UywaFCqf+0z2P0U/6noOLBx6xtDhW3KCgg
+FykZnG39jWAuwjfdh+EFgKl/m2FWVZ8AR0JZBlaboHDhbnUtcqUPLsHmlq05ozfr
+GwduBxVeMb0/v9WOQIvzqDykhd2CW7DzrnrOQwoH2NV64qWi8qyF7mQZPpzCiMNc
+Oe0/nwHPTp3C3dR4YOlLEAJTWqMGnD8byYG8JoMq1fQZcOnWZN4pZiL97hGRUFKQ
+bl9U6oWUJ37dLJFpIUqSqg3rEHpDOuJhFDRvkPIihnDV45PrvH5sbKTF482c+JUA
++aW5bDIpRIhB0Uhj+i8wDCsd/TD4X/0bDcuewFOZ7RpnJ+DkKfBiIONwAUVgWO4G
+ot2sxR5+ZGLfLgyES3nrpIRjhHDzGZT3lNtUvj7ceXEOv9LJWYGfezAAhu/LDcHH
+YX79AoI7qCITBOS+nIZMywAACOTjTRJML2RRWF3xzckhNV90vkT1vzdzeGPCXnZu
+iSb5PbLJAkWKaIcq6WaFumk6XK2cgVP231/K5+gDNN0YxwddmRHzoFZJFyOuXSFC
+Genw5ImW8V5M9SxJ6Hs2h9RoDssyn05XALMCx4n6Vj2q8PAMQoxFwwRAWql0hjvL
+ArzGt6IuPO/wE4xCL+6fCggixlAbHuu057XeMDmshQwc+nSyuQ+xujiVesI1RE/Y
+BT6ML6tLRTOWNKlNilJy2Ql1M6RoiZ66/IvMHarUeOe4IZpH8OlJARgjtViXKyCY
+k3TLPjOgRXaUkXvCmbpDBk7lCXWeDHeOMvigwrZD327G3GZ3gA9gNkS9fIx8eivY
+cVXL869yfceiZQ2DRFbfEh+bX4DI1JGDcTy+TgdFmpxLqKuBbC49AqbgQM78vY3C
+HuKPHLmnV9e2obPneMrHQXVs2PEhDOKwLJojq1W8YHJotrKQn+4z8NqJgcjNKgrs
+KOHywXzfHbzZryih8PkVtDeS/ycKOzl2D2lVTl6ZR1c/064zCJsQG5QZBuMDbaKF
+PhITFoHcmuUioS+F/HTh0tSJvwk/xI1W92WTJeM6pK97mxOxwWCuog3JmlwmCaKI
+HNhQjBxPe6R3IVjo9CU1RjqdujiRSH7iGkTR6Y48ELnqKwwJfJsARFDkXWOVy6gG
+IC14P4HAnNgLQ5ATVg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_md2_rc2_64.der b/samples/rsa/pkcs8v1_rsa_md2_rc2_64.der
new file mode 100644
index 0000000..9ee07a6
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_md2_rc2_64.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_md2_rc2_64.pem b/samples/rsa/pkcs8v1_rsa_md2_rc2_64.pem
new file mode 100644
index 0000000..0e9d9a7
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_md2_rc2_64.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQQwDgQIuhO2PlAopLUCAggABIIEyMnfUQr0i9ShsBuW
+/9RKaa9xR0WHNp6xj6A5ZjsMgZ/V2IlVJJ546zxSA3r4Bo2vEDY5GdJQ2AVlCDfA
+SWLcPWvHGhouqIvOehu7teThJp/QeYGbb25TUlwfz9Zrr7U5uDiICzbcM8jc+YeE
+5oyMQ3uzxTPJFxMoilQnr8v0pHUo3SuNj9Cur++sy0F0LCmMyjX8HNrUEctPzBdX
+QOCYrxGQ0H3yx64FaL8Kp1ZL4JI7zw1oDGvyRkJCD173uuwE/QvG/m4ym/fnVUzp
+xAXACHokmQgWsuFFSG9VbNdJ6XWMTdVMvQhBeJ8vMjNNlpvFVoAKJIldzDwROiKB
+XTPHSuNYpmwqN1Kx8QKstIUW+31Js0ZJ7WH4nC8lVu1mnhVG7TEIG3szd223IzBm
+fTbqOwOM/ZivWchr38dOYU7/tEizbyGPjP8EWUC9nxGkmJGdTaluvZ5kdeOH9r2Z
+YudYhH5N2FSKI/0em1rq/Jj9oA5zunbX3ZwdUM/poNCiSC24wq9trBjOc/CWP/EH
+9zLdO7TtCk+nBtoa8bAXwJWlK1LLQrA5lsM45fYqBhf26C07M5yNPsjTA4cFVF9o
+PFp3CO1B6BEdnl9ETaO1vyc0jB0QJE/z1ySglsBtN1HI9irsS/IqGHAQq9mt9tcv
+knAWpjO4vDu9GRh1TwFzliU/FH9UFG9yInQTzQVWMcbVgOPN5uxGfrFy2qiJNkAT
+iMOFQb1xE3MzYM4bj9p4uoKh04UdMusiIodBc0xmoXRqkNH2G+oFP2xsWtg4HCKY
+Exyxc7Py49h3yYet+IY9FUWC5Gdp8hBVFP23ENMeWVOnTIjby1MbkjFukQJrf3W3
+SqftK0nwYmXkdn3hwFX5CxAYqVb5XakrhxDJw63kFevfm5Mblpj9QhVcjGsWJ0f9
+pzrkUunLdyOIT18YzZkdVaeTTEbVbQWqNUsIFQ8n7HfaOnQ0iWUX523fcDnY1Sc+
+0vFe2NZvpnl9EtvYEQmcI2tjGpDVrCljvayKbn/xnC0ixxkI/P0PrfcqfyqxWRS8
+p/e99gBwJ620iFhWd2v/KmQ20RJzEofKI3Ze0fIvnbG/z6mPj5yj/E9EsWCXT4Tg
+svU91hsSa6xoOyeAOlzhFy/r9fdwNNzhsOSYU3fwqXZOzd/8gXi8qX2+bpBxv2S4
+3KB8fIVopHYUafXVerhsVwMEX9S0mlrFvUXn2+ZqWOR8PI0jpuvYuQ53ZFq7LU5H
+U8CSwG6LZIFiYDT+t7I2B+iH6E4refjr9UWGwWEYGvViFbNW/dEW4tMiwsCEoYUR
+iEcMN0SX/OqOqz3I++7tuxaP47NRWew6RhttnijaEAnWmtiThMO4BRKfltAXcCo2
+OLhCaik8119YAinRGgPoZtLBQ8ZvfVV69Zwmdc6xgF4ML13l4/04fy72nZndn6T3
+TPm2+t0ndyCyiI8QWA9b+JyAw6+L6RNnCHC7CknXmvczbnJYUwsz6x8oQimy05Ak
+N6QDVOJpoCUngw+gn74T1Cta5ZaxSJfGW8FK6qb0hO5wD7gZwtMzkDoo9xNbW6bw
+1l6lt//wyOqkhhXeHkJp37Eaf+XSCrmCij1GRqTyRPZL+jRySjXRrLLsIZYyVway
+81DyAMtYfjtpDDyzfQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_md5_des1.der b/samples/rsa/pkcs8v1_rsa_md5_des1.der
new file mode 100644
index 0000000..81cc168
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_md5_des1.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_md5_des1.pem b/samples/rsa/pkcs8v1_rsa_md5_des1.pem
new file mode 100644
index 0000000..f0ec276
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_md5_des1.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQMwDgQIxizKMy0aK/8CAggABIIEyAnnix29lspsrzEJ
+CN6s0zzdZvcbiGqUHTQCUKdhCmYBEns5IuocYmc6i/oONG9Gy/S7VcksLZPrWFAI
+DWuEpMKcnM/Sv7RtMq1kpAFlTlScRzxOEflaymUhr8P7fdAhjRi4DxZ5O32eHzhg
+G+yo5PhCkQSl+sClUh6owOl4zm7l3aVdqOK51fFE0EZ5RkZ9pRQ95Om5h6++c+IS
+T4Z2jF4mS2ALNg3vFABF3HQYO+KuGqrGRd7+gKr2QU6I1Zs6xcFVu6pF7T7jRKh4
+d31yJ1ac52+oWbw6P7Lwz9ZMzjlfxDhStXhl1FQ+iIeKq07J2urgXdxxzvoHfwOV
+wZakQejSWnyOvCvGZwJZJh5OZrad8Y9mAZgicYjDxWfxcLZQkZW+vUDJBWD37Sln
+8BwvYBATLdBPTqdXGgv4IyDwnPXdXxflRhHGTVi94oY3gEbhoH2yPvCD0IVtA1lI
+cG229JsbNQvH5DqTS32/mz0LJPlbPmP4tj7EZ4nqehM9wrF5dV+bigGqH6g4hfWg
+jCS+wRw//Qa/Z553XZq0WIJWg6JthiuiLlme1axOceLIO092+9HRjXQ1j4SlLPgs
+bgCiKn7uISvhxuAtir2d9jxqZ+KPDaSsLTMP5JycNwYCbtb4DYDGonwEfK+20tZ4
+3ZykwRKIyD5c25HBZ7maWbe86rc5c1a2fcvIjbXzwOXNXgNn4wn471oKchbXUq8p
+4RFw10omqTvzmKISucI3ymUkmuknRtVwc4bGAprvzpszBlSqPUi8E43+MVzc5pGu
+T0b6vGqhwYNVEYFJ2VplJZkgIDnT47PBPR7RmBak16kZhQPO8yUpVtEmhn6nCtvo
+It7wEktt0OxPcjLKm2Pus8oxWM/L38V3gADAqLny3A5c+at4VxkfMbNNNki/dh6M
+LBaLIgdKZoT6ZIwP5GIPjOn/y1FGOAB2NAHm+RwiPxCBshr6ztbMbcPJ+VhQpcy+
+z5FCoB3xIGE47KazVCUozy3JRjwY3aYqgQoIqbhvJfvxo3IfoY359x1lSAnQMGcQ
+AqsqRnjb+/PrwuPQW/vCR5SDfAxBJGsnnI0WR6nwmfDXrR0BQKjd+//M6y+GA9cF
+tm9b0gacTQDynK2tkcfbBwsHfQZJpAxWHpW6fgSRBxaMnFHq/sOqMtz28at8M0wX
+qOQLYPQw7pLTXMRuhSMI1UMs+fcTZ479El+inWZwzF3CjNnKr0LCV5ZhwLhPqOu3
+CjXeY4KOto1hGu5tufEIqNR506fehqnklq2qAwpFbJxzYyVzTADx/eTTNd/4EHk2
+B5u0lpY/xIgvSMAkkb1Y4v8MgBI6klgBAsKWhf0ojfn1fUuiY24/NzGTE5g5MZ7X
+ZyyFkqYrc+T7hXRSe+qXltLxD/4StXOTOBuf5TLsKbkBbKVHtnnrEwzhejQMGZrG
+BNk66KQRIL4LQlTBS5/rcumNgZys8cxYVw6swmvKw8ACSnihOBEvMlOqFBmXnjwv
+fn3sCuOoRmCRHNrk0wi6CNESBkJqlvstCNCuIIZZr7cXkihREK/uU/GirxAfmpCd
+jiHB/jD+FyOAoaSKaDfmjTjF1uLjyiEoBC82yfvYZBETm+ERp+6DWOR/mX9e36mT
+HQn56M8rvTeoNeqccg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_md5_rc2_64.der b/samples/rsa/pkcs8v1_rsa_md5_rc2_64.der
new file mode 100644
index 0000000..d060e47
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_md5_rc2_64.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_md5_rc2_64.pem b/samples/rsa/pkcs8v1_rsa_md5_rc2_64.pem
new file mode 100644
index 0000000..ba3a9c2
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_md5_rc2_64.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQYwDgQI6ZMXmLzh0BYCAggABIIEyOU42e6vlc8GacmK
+NOf8IXA7FZsgmrHQKimv0HLfkxXa4MfIceL4GcHpKMPlAsXtbVkucaasIkGadBoC
+7tQP4ZvvsGS8H490QHzs5Q8WMpF9dG9rDfnf+/cKTEnRJ6BDqI7RN48p4VXtOiFq
++vxZ3j9EVW4+MLY+5qjJMyqtxUy5cOENM4HI4v+V76W1xZhOinCffEUMPwrxKtMD
+x26bDOWSTvhzNDcFjgmcbq1YQRoi++F/vDkiIsl675eosdYaGfTK5NJeiIBQ5J4U
+wtX44OQhtM7vxQzkPUZoxnul6s0Z0Sr5J2P0mureb4As+lyqPVoBMwJp4g9bJTgf
+zFDM+OiIiuRA2tgfakJ9xp7Nkg4HffEJobR4/7QG7TyXG78mlKi95g+ytUYAyB0x
+YEfiuKOxHkMlBALTMnJgyhDLtqrmTofcaBslNLBSMxKvCdJcZL3lncrRtx0u4YuG
+VXa1etHSfjNs9XS1jsrCCW5kGhHoWoaq3GS+XcdNm0U/hl/txIOhs8jFp4rEwAX4
+fc3uqhrK5yjTthWQL230jaoEfHhLyNJUDCGUZ77dc/t41o3FhwBseEqvPTOK3g5U
+bhI0DD3Rjp/wfcSPZDJdb5l23EWhBsFh37U6k64QtwJkXPpewMCYCli1isCVUA6W
+OpL3+nQZsQEs/sAkKF4x+eaIvrHypW+fI/7JLP61O7twBaoACapVNNlt1JMok8XZ
+4gQdvf6BLjE50M4onV649jc524ThC5nA74cKeEYX7UPFBWYc6EyIwbCIp9yLCWyH
+QZUpgpUXxAfk4AvMxO1XEtNDCs3eMGlzcXaHhb99mdKFQ6DB8dLNoWjCYsjjRWbP
+N0f/egQZUeUGXY6e4lcxFsb1ItVvSfMgkYJfrTLysVMiCpcjvwAZTKIMhM2iHf3f
+fUZD0SeN/XuY6GUBgEIKlNpeyNS19gkE27Ykj13MUpwzLQwH+DQGAlPGEnaZcAio
+M82BLlr85Q8LxypOZrmvIqJXqBbhH+lOfPRKUrhOOPt+Pye9BNUbJDpN2oktdqAP
+mJdCp5m4Vj9MgAF9VrgN4++uOkn1QO22xQyzdCOQnWeSPpI1wqlrU/AyxxGw/ex2
+mxZ+Y13CS6OHfgsZKawrov56qmog4Bfmxra+9y+C/FzFXhXgFhJu9M70dAYk8zqT
+U3EvL9eY+I+dxKR/ne+S0siCVgZ9/ZizYLrHyRaO1AkevlsBwaqc0ST5bT8+AWlK
+ZhPQVEH7uIbSSR2rUMF2olTZNDpRzCqn1ZxATZq84aMzgTjlxxHCrFP2zQOiV3No
+BrAfHYDXXe5uSqBDTDifbAJhDmDJinl7QOd7nHcFQloAySr53g3KMQ2WNRRkUMxe
+TLNhuN6Sm1ymvi7VYlNwVl0nqUltuV91lE0RzfO/fFVhRjUQ/HTvTwvQsFUy4DRl
+Q+Gx1p5lrM4zdYcsqgD19Pw+3AiFqQrGMPknz7WU7H+I9L+ZPlufokLVMbChSuga
+2jfSzE3ozkpD4jDBhUg5CHQC16AQ0JwwVGBOHiuOkNZ3ztLjik2rqU8BR8UqN+gc
+JGZWC+U5gOIzNzA89ovrO9ozPT1ig8icW4VP8rdx2pxN5qB9ZNgI/96T4R9MTgTz
+hhk2LVnA5n3xs6ku1g==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_des1.der b/samples/rsa/pkcs8v1_rsa_sha1_des1.der
new file mode 100644
index 0000000..421497e
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_des1.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_des1.pem b/samples/rsa/pkcs8v1_rsa_sha1_des1.pem
new file mode 100644
index 0000000..d2a00d8
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_des1.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQowDgQIuvb3MliqZbQCAggABIIEyHVgem5Ez9BZJsRK
+Y35R50+mIs7AY/S9hVcbnXmfikN4VrM/PfP3vTUfyRe4tJnaA/5lEsUmTLpZxl1C
+EZNuPYWbGyqwjeDYTe6d62dLsdt3hLp+lpEF7NSFnNUCWF+ZuBujArrg8PVYGWsV
+eYvTDXXrdCUjZ3oXWSUQp7u7gVSKG/w/B8OXuKXHNwMMgdba2eAdGG5gOEN2Sfca
+loUPFEoZNtNoEw8Z1i6FM70cMSQ+Q6UL1OTshNKICFHx/RW9+VA5driUKbASzBEi
+T3egbUH6Rmv6MDANFDP5ql7FaNSaitah1O2yGbdjJlhYcGjLk5U7UnRrphvcPuXW
+t1izrQ2OtwV/6dTck7XJbrY2FKvq62N8wyNHqdidgh4zGGR8PiDUSEW9faUuW9Ux
+VS0495vOyZoophrNTX7iD9J1a3c8FJJzJAsGmk2mMAOcFLYWJKgXDRKZjMcYWfbj
+fxNz+TYlSb1+GGzZEyeiyr218tpxH46uwGe6dk0zuyEmCsK52S7g/pkJpL3paRT/
+xh+ds/Y3QHYGeCYkO8LNb3PWwhg6aO5Zcq/nSGE7l1EEvRbIiMombBYEsyvlO+/h
+0qgktSqpW8ukhyOGTXCFpy7vrLDK0qJibgaKhZ6HZim4vSXFl43kOSvHPNhip2jY
+fu1G8/nRPUf3JqxI/cCUiNj5FG8/Tm41RfXupGZeaMofCi9rKIRdWsk9w5mJ4l+W
+4Y8qrR3Tmemv0oqSm5NzuwFDqyl3tRQ/0DZ+lAEY2fZd+ntOY1vXUTQCQ1KQcdBW
+70FuB5mG8UK+ahBQNiEPxnuXkdqR7ELOazgK4VgVFvBf6biHTt+f81sR84yMOHsR
+kAM48CUZ7FULQ3VfIOfNpUthRMDo/bq/t7x/XWTaV+Oy/N84+icaqqpobJtLk0tJ
+0hHp9RXiwF/iL+u+MrEUFIyAdaQcqi7oxPIe8d3wL/q1jyftATVsRQyTClH2zFN8
+wxcQPs6xxOI8yGSCbHF4LTjCVtL/wzm7sCfzi3HezkhMtiHIKvFQjKjXXJRRAU6+
+JXztTyMokEF5e9PDuLoBin1gpJIDXQHgd8NZ76IOi0S9LeSvRFK6ESk1o3bg+PzS
+kZQ7bM+Rqt4jIsnuLwXe7dU9xprFiUAv0TxgFQI5QqX83tKllthAmBoE2t3KANR9
+tbOnC3Z+xiri2Z44kQgt789rqb60QpUMJm1eI3WSGzJN9Az3yxKL3wMB8tkd/G2B
+/6rMoC0RHGKh9LDP7IzTXT55JdmJGl0mY9ZSC9oDg/iUiFKwzlB8kjG8cU5/0ckQ
+Osz4b/Xn+2h7P1zvLyIcpH82FCRjxa6wLbOFqB1PUJ0ZtX9Dng4eEtxkxTSNoXgz
+O8TZrCC7EVY89y+vHsBD4XiJt7HCIymtwN3fLuDkqsHezcs2Y5ljJlwIcaUvzLg5
+e3kfVM4l1U+5XfdYvBHu5x1E2z0gcW2shhUFMGVzuy8xbvVENXsVYxyP0RHeqZgv
+Fj4NUPMicJ2KoC5Yej6IQlhTmFNsMy/TJLV2d3HwEFOTsG0saZHVLTCNLMpSPym4
+u5YaBOlwBsNuTlWtUMG/gBT+wKRNUaLIBJwmplSkKTWScxMILElv6FKZXpophiBs
+5AdrjrjM0jE7I8I+7w==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_des2.der b/samples/rsa/pkcs8v1_rsa_sha1_des2.der
new file mode 100644
index 0000000..c4ea356
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_des2.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_des2.pem b/samples/rsa/pkcs8v1_rsa_sha1_des2.pem
new file mode 100644
index 0000000..626dae3
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_des2.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6jAcBgoqhkiG9w0BDAEEMA4ECJmiRQv0ipIPAgIIAASCBMgYV8qimgmy3BFc
+RIPjRdYgrBHAs3IelCotDmny4mx0IjmHRqu4XNeye9dMhVnxpntxoNKc4B+Hfoa2
+QKvNj2uqOTJw08c2uu6BSmlr0UHJj9qyAergV0hh9vzIBD5tCr+hGwWIRyR3l+Y2
+D0ZaNPP+Axei6eLBV3QvRJt0AdiNPY6u7+SqdzKAwWj4iotbwVlcYsKEdMZQB69x
+x5fz2PZBHKMcg9EzU5coEOGacoKc3ex85v4V6ZA0gjSsmj4ldSvb9t4QfeFJWPsr
+waKPvFa+y4TSgg1mIrW0/+rH9QzrKAUVucLsM8SzyOXayWPQUmieNiTcMZJ8MOvj
+eJVyXOZ51BRLW1/hyGbJhgZEgqDlfNNecFXAFehFA8HEsAwm/KjiRaTM2znqv/jT
+ZA/rEeovoyjTQ5BjbLmcHIJL548EBHg6ea7Gs6QMoZU/0iouYKhHAgIrk7oIK+D+
+Y1kTQ+WbvQ6KpEmgySvznKzT2THrI5hny19dvcbZrk/rUsnrxicAbSbPmdaH2Rlr
+3xRi3h+LjPbuxTIIovToA3jvHprheeGiRODnoFzjQoUG+hROdOXyGz4/QQvIK1Ry
+AWGdaeKehzWye+eWB2p1p4oJWFDVgXwMIt+CXJJrsFVNp3n1f8jw0g+OrI/iHpOD
+roh6uaNCiBkqUSG0fCrOpKpoQKg6EcqV92l74YeXKcOwuLmSse3bxz9igof2jq+h
+NGoozV2qc5y4UqOjSGQsI12FMDV9t1np3GR413AjsXKbOHl83eTHLB/GYlpPkdNr
+obu7Xj5GVYLX7A54yof2gwBXH3dbI/1WGu9QU1JdUdnKL07FFs9BgtRqsU3MSHtJ
+EU38J+Ezlz8wW2eMyIXSTQBYshluIko7fzAkEVWT/OCL3RSJsB0xKB9OpgKD+p5z
+Q+AxibHxUBjxddwjEgcsX7KC9lEyMb1vH5XQxOO1vdup5eJZx6XL4+V3GoiZt8Im
+3VSOciynMLAkz/AgzcG8b4XdIzf7dpjN7dvJPpz8KKDG3hztnD0SWkZEpLcODeGP
+RJcki3WW70vy9/DDqbE749511N+jiLDTxFc25Jbd01XuPZSsONCB32zjgJZuxwax
+n4/+EWN7+H95G1a2IHJ6VlteSRXxRKrZ65yNju5eAIVIJk7REXA8FYx2mvNNuTeW
+FBbBT4hn7f2015PX4zJPe8ot0SPvC8GyxpLANCfbXCp6f5LAj/bsn9CeYh8yGiQ9
+WrMCz3RFt2itpvIEeO2W/MGs862GUMjdk8qrZyeRCnFjE7wja6CdcJidPKwp8dTd
+h+fdBJtLbB7BfOXn8OGaafCwFdGHvpogtv/GSyEsaT8Vp4D0QCWlJoABHchp8tvq
+8LjIfcA0kTP3UKTkvsRd3BJSZH7AOCinHF4IiC8kkvj0CxSseCsKjjBcXdb5ZnU1
+YUQirDYCwrKvZQn24cn/kp402JQpvParUDXl6gqoiIgrrjnsgcr75cf3AZkpLZe+
+f6zMPwg/M4Dg9l30F1OExUWNgfs78QaxByCKuXP92y1gZ5cDAYZoi+ioJ0pMTG3t
+egIdfMfc/kO36Pej3s86sJumMdWI7FTU96AZf5CM99Cl483oN2PpUXpj09K2et7G
+lwXMU9H/9aJxUqvZ+jo=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_des3.der b/samples/rsa/pkcs8v1_rsa_sha1_des3.der
new file mode 100644
index 0000000..df01c84
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_des3.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_des3.pem b/samples/rsa/pkcs8v1_rsa_sha1_des3.pem
new file mode 100644
index 0000000..6dad536
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_des3.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6jAcBgoqhkiG9w0BDAEDMA4ECDFK+hyHRPJSAgIIAASCBMjG2lWovCpivpZ7
+eXZjRQdhN/SrZCajGzwAQNtykElbBlRpObRlMpJUEed6kMI3V310hQDg/0imf+PE
+ff3ihc300LTMb5woiqadncRU96+WnheFLO26V65R7/ax2q4Thuci/1hD6bqNIzVb
+rBxyRr8XX8AwOIIkfCDFnNBppvvc8CT9vNJ7ezx4q87ALkuHu8DAo4NmWJZrOXzI
+VKv8TvyE6eNYRp5tiWwOloj19vRMCqU5tEjNWi7PT0FXSogMidpejhZrMb2N7oKg
+XHaaFlqofZz6CX586B9dRgg7EPoAE2d1R25o/jen8xL/mQsWa1WkM8hRsjIQ0Cip
+ng7gV1r7AwNQgrNoQoPBPHSAhFXGnXM9viTt1kHHjdE81A/JAsnw6OaI1TEAkHMV
+Lcu6ZDhKPBa798PDWEcGkYPa25NEJmV7cxFwZXH6b7C8h1S/FCLPuzYvhae2YSeW
+RgMb4MMweQHf9q9zb1Y7LyOiw1kO/vPiIFgS2KRxMwg3/L+FCK+D0NJaETB2ycM2
+gvn8U0hDY7lfTtog7jiInU7uZ0eXRF7mOyp5WdIQpmeqUNMBUteRvHscGm2jOdNI
+RUTUhLjKzfXGLRTqAScU9IB/tcin7X8tOg7rJkRQ3Vs6JcHd0U8Hm/tci9wXc7CZ
+MZBKEwPZ/+KwyzdbGbBp0Y+mzSshmOTyc2oe0uUhDhMKHw242uyaEj+1Wp3y8NmI
+dEx7c+A/KmeynNfwYabZTQW94IWkl8v4lr14hh++gyu6bBCeSVLe7ui9L8xxWYii
+g4n/SRFXnicU9Mt9m3yC1Dybd5ArctsLE/GnKIRyVJSwoUt9D6MB9m/3xosKG3YC
+525u05bpxOXEP7Ed9P3AnuoQpBgJQupy0CzZ81dy4CYPItJT9EgiPjF/e8+7YiKw
+y6ySR0LgvCb7yOOh64+xKo34dSs4C9l3QnBQ0hNfeT4nqr7eA8VLLjd0K1MKVjZz
+GBI9gsv9Uhj3G6wtVXITkMyHMIT0KPeUwyjSrFNaBhlN9Gr5rU1R4gHZpIBPeOt3
+7JfaDikpAphUx/wrywS7KFvVhb8RXCDAgg8xvtLO1vLTEUg4g4+XgKysuPqq+DrA
+AnUl48GNbZh+O/mJfpuAP9Y9x1a7ZT19iXXYdzrLOqfaoAsT8eGIbDVFo3GlB8B5
+mf0WJ+ovnzQBbGPxSYEVn3M/CLzpA85q8R+FD8ZtQIYBhGETODDGguUKnHQ6MI1V
+9pxH5unjulZWlhYo4VJGd0gmmFXMuLyBPh5w2xvQ8ZJLrJzAxMc/KCVxtTmTWJjy
+nkh2N906ZiChdecwvqgwq68WkDxcAbkqkNNTK7U4fDmeJNAVDrNTOHyL3mYryw4z
+pCjreLjxSOv997TappTy9gN5mJnbzDoLIq+vzFRHQGY0At6gcC5JE4QtwDWm4Wc6
+w3lMHYYqXceZjsCuIKu5To2racKl3AoxySnE1JQaZOKCt/xsSaRzS5TSmWyJp0Mx
+1YZwPpTGAaX0xcQVGihktpIHwLoxngqkzjXmQ5LMYhodfW8BYVcIX034D14RbM76
+ec9xRAoXQkDaIp/aUi1hMxyr9aEo7x4fVPrgHO8bV/2U0/qu7EZ2Vyg4/zSPb3Bx
+XC7kbX4PMsWZby737HA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc2_128.der b/samples/rsa/pkcs8v1_rsa_sha1_rc2_128.der
new file mode 100644
index 0000000..979f216
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_rc2_128.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc2_128.pem b/samples/rsa/pkcs8v1_rsa_sha1_rc2_128.pem
new file mode 100644
index 0000000..989cda8
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_rc2_128.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6jAcBgoqhkiG9w0BDAEFMA4ECOkayjIA+6pcAgIIAASCBMjjgTgBAlc/31JE
+i/jvM6IuCtTToO92d9Ut+tgT+b4u5VD+8KM4ayz9L+KIp3mvowk8pUKtsIWJPqFo
+Kf+crAWSPnYg8Of+ZFHu5s6SYu9wOQ9VOyP3LwHt1/5jnqhuBW92Buog7GvauqK1
+sdEsR3zuT7cpbq0MYrB6Bp/HI7fGYMUPwy1+T90lejrmTSVAyK7dyk6U96bkWVCx
+p5h0Pc+xF+IbtSqctCaw+FV8KdZgxV2e8GzGVlJpDa+J8xqjZNk1X88JuzrrIayi
+J92szEBhWIXwJdTj8mXBFjVb8w4khEv8i30ABxHxfo7eWpt33R1riizwt7NbbYbK
+2gUXqHmaS4MVKbsxb/NMiC2KbJ6Is7/tPYXvIiCqeKz1IcvrwbVbPJZBon1Ybyse
+JSDmcf9wwHt0zlZ7598OCtxCCy1JrUWooAmzGJZq4hkg+3+ell3i0boj8/2s5auY
+rD0ProInuCEsJG7JbzwUSsIAF7wmIxSLUJZBLbTKDs1XRIYtLVQfvT+ZQOge/d78
+sJh9BRzAlSpOVyEtGYYW4WZLJyJaN5Pt9+zmfSo4yf01VELmC40PipstDUiNQ6bX
+lGJbJLY5hEWPcd61lfVw3KdbtkzrUmnY+qZy8W3R+8zP4UV+IXWCW0anxrNiVUqJ
+QQkucC3/b6/AOjZGz+wx5RbpxzsSXx1P2pDdbxAXXy2KAUql+fM5ukeh3Rj7ih5w
+gS19Fx1XW9jikJg4GZEOs9LkERHcvhBHhfsSYUlgyzA7pcliFsYLSqe9KcfpvogI
+xJjkRVqc6hKYejU8HxW20MTdh7yDT3PEYBrkqmG2QSHVze73w40uyEoaTWCiWfdV
+VlLW9ddq6rypW13QK0zMcXizP6rrsM0PbDHvc+cyPGk2eWaBNWX59W6ewvQWVyp1
+hS5B5PzA5JUhUyW1/qbmNgO/se8jNT97E446bprQ+SGV1h6bd37SCplEBSsv8Gm2
+sYWAVT4IY64pFP0LO3SttKAi7QGxdcNXSkqzdhdu6A9+ZnAl3ssiGU+mj7rIl9ND
+aAhyIZpqdBYIOj4nJ+jwlNNxLrvhBTCocpIZE66uTGv8c5AGbyX43USzMTyx+fVl
+GC6SVPIoFLm+YNu5wSpLS9YSxfNr5AIcM8fkfBpNJ+v0gKi7Ky+n3Tu+CQyzxVXd
+k5Dy6Xs1Mw5fh9tOO9gJFXwIcAXZkEtbY4bjiA3fvEdLrKhzWaNOZKA9pKo7Zhdq
+gR3WA1A5iSDWTeyWkjJKSVxN+K7AkE5hQTI/6q+Su1JK6OOfui7BQvGKpgNiJGc8
+swHlwprbbNDqqeHLwp1+XTIFt9p3PhRuS4ooqWhhJTRTUxERI7g7J2oCl1kYv8HQ
+YfROPqOV/2d1TK7k0BSym4qCd1uQg6OewQ+C6w/QhkGf4Xm/FAfCkv7/cw51c4oq
+VJDJIX6O6u7rg9F00jb5e7DTw52x+afcMv10svlORM+LR/70gTwV7jV6DnXFUp9/
+ZDEq4qOqy/lCIgFTlziN3zjapfLYkcUppa2QHVgkNOEiRfwKQDXVwgX/kRkW9d6G
+WKgoxjeRT3A9VDcTrL4E+OtB2c4ykHsNzqsWunGGLR4KY3NyAHs3Qn2Egq/klpKp
+M/3VvFPU7quGOcbHYvs=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc2_40.der b/samples/rsa/pkcs8v1_rsa_sha1_rc2_40.der
new file mode 100644
index 0000000..f3bb093
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_rc2_40.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc2_40.pem b/samples/rsa/pkcs8v1_rsa_sha1_rc2_40.pem
new file mode 100644
index 0000000..7537522
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_rc2_40.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6jAcBgoqhkiG9w0BDAEGMA4ECEmBQOdpNXpwAgIIAASCBMiuvX4e3RsNqkgh
+TxtXZRqXCQN1CB2fxUhDKMW96szcVTZKBr1Doli85mdP7kPPbGHyouoFZZF+z76a
+2axtCvgx7X65MVB8G0MH6tMC+FPRcy8vLnGuibmy03vBfuw8aVrvF2EjDwG0zncl
+FdPUWutO4LiQbWT6zzfYbHOX3pw/ccIAgHyr7BBv0lPiyZu0+Xv8wfhvc1aAtg6V
+yM8Fw22hSMz9KnbWvdu9NcKJuHRoh2eLC4lXha+DN7PSA/DXxyEocx93pgia2mj1
+mb8oVkX1uHWtcLEPWBS3CtTAgskO6XH0IAL1M4FZOXqpf4IPAiWEanCjdVC8cO7T
+jEphF7E1aYgrCuZIoWiE6bkceA6rxPpGTtEafrUAJBSIeu0ek5bl6EiRBZdGCY+c
+DT5Oet3c80xk0+rz7L4IBUv92aHITSRs8E7CStMRWAIM7BuqesfOwz6uDt/SGW3I
+wNVBbrEGNemeHvT5QdML1mXXRZu4iMaNE3eoqT5Jcdq6keRZqihR/ZdBs6OEOQNO
+Olxcn3QgyCwmxajD2/sF8zwFHE0tBPwbgiMVBhTJooGzJ75LzpbvT0j/ly7JpIoz
+6EYWLKwBmJ48xQRWTGksb0/n6Pevq0OkFiCtkSn+S/U2V59RBMSWhIY2hiKrFsh5
+sss7GIDPLj6eneAnhjNFt7aAiZrX4bg/Hhofl65BxO8O/HFww5h/qRRslbwLIkjw
+xy+QPM3mkem5GaFyDT4pBeT536RH+NIXewyeMub/Va6MJNAT0JLAq6kRPr6RF0uj
+gqSVetDMHVXuKzBc+tkk3mEH2zt/tdOAOEtp/uh5kRyS8lzYCYbdMVwXG2b4tmKW
+c9pIPCpgqKqzYtLq5ohp4qbs+UKFnMfef4qxXA5qdjeSjLA5IfwiQ/2sjm94pYsp
+rBBv+zULfr1iQlsrPDpvFkV7frH7lRV/72iwUbXnMFkY8yZYCX7pPeMz8Mn/RKEI
+MXFXb5zYExs8oFySwOAIMA+f06Zuzi/uPB+DAek2foZ5EPTruizi9GSR0q16mtrg
+6iGU0fYiOws9RRfE0q5y7Hs0JAbG9ivsnKs30FFtHmK5icdQWfraIGVCR2QiPPfs
+N2lA/PkeuF+j5ADoYI5zQSgZjo5TawJcjtXzp79yLAsvoRk7MDpmrHudLHQucKz7
+vvOk0w9pQ36E1Ytkd8OLm5AX71/YZ1k74nh2gqVu5NIPLaOLUr35mD24+YwX606I
+OIaQ9auYDgZN517MD0knbFS0f8hCCg6yTOj489RXszjRglDZbKnrXRMUmFKBA3al
+g8RNupq/VUfXvxPIAcselPt2br2CCoJaLskZ8VKJEyqi8bnZvAxuEthnZDjX0uAn
+JQHDIUqdnIrTSxIihyNBzcs3O2WGh4YEsP3Y85o9KdYa9JT71w1gT9SVBXVHKqve
+e+HkohUkcs/qQMRwWFhWX3XoZklvum1czDxmVbzt2S9NZ2QUg52ga1MGfHTCyRXu
+IM9SnveJyXWjEJgSfGj2phnfw5oVy097FlrGS8WF+i6bRWVdJrV/0tnZ5FdB7qWL
+uDObQTopFbkXBbnwlJ68UYdkEDbkAvy7QOtyFEYOTYQOwsYglxd6iWI/M/a4ciKS
+TMOCQzxIRUPAeJENBTU=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc2_64.der b/samples/rsa/pkcs8v1_rsa_sha1_rc2_64.der
new file mode 100644
index 0000000..c6356a7
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_rc2_64.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc2_64.pem b/samples/rsa/pkcs8v1_rsa_sha1_rc2_64.pem
new file mode 100644
index 0000000..974828a
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_rc2_64.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQswDgQIJu/CJ8iPmbcCAggABIIEyIFkDgXMUnmd21JV
+Jf5mVH17/NAPEUob1P1nijVJkuZlSx0Vv2ukPcotDLv5FQltgRMx3TS7xGI91Z5y
+vzCVrOsC8xB9OyulD6MdACAavDhy4e0mXu+6OiiXFIp8EeEap+dHszzl+G3vz7mf
+LCZMf8BkaXrl9RdDNDD10ich+vtuzllY5uAZzQIt/0gHVz048qNywoscYV7xniuH
+4AOpOFHo0F+zo5oxfK3ouWzhfvOhIvqxgK7PFqSMixmkIGgKkrhEYWDp5hrLpEyr
+qfXCRtpe5auOwt6pOQ7MvCNY78zF0WgHrmrmXiWcl0eBWAVzBZGefBl9DsRTeW7a
+83rno6bWfdTYZMP32XvDXsBlFaQu5xtC3wdvI5aX1Cj081KcRUdyVTkWe7Uz8DYZ
++3NZCbw/2AQ4KeGB52VVWy7R2ZGaHyRObVvT0MheEZN7iucMDlrxIRJLLUdKkyN7
+VXY5sLcN8JfSfKqLaxQp356IxJqdG2jdBbb6LqmCdNwtc0WrFErCGSS2PQEwTfVO
+s9u1WsReM+FEWW8/byoovbQvP9BVFsP9MZ67cM6fPMErLwmAaryB8gzajTHW6kh1
+i5RvoDl7XaUDVUVVAujsVA8cvwl5GU95XXQUTmPQGyObDz3fuwZKRPTYrOm4Mjvb
+tI0Fuc2HZ8/2a4OeB1CnnxfkXZW192tgriLUZLwfeE4nHV8Ik5C/iXC9f5oKB7Oe
+CVSJy9ZSszgw7Z69YzRhRbmxCbG+M1nUUUdIkEQbXKw4VtMx1HFRpZNk4ygvWd+j
+O/8h5QuOu3QBDXzGKUVMRhkOprKXqPRyO2EnqgV19FN7XSbiCwUhhXTfYfUxHwgS
+cvWeF78nb+eYGLTp1rDo+fbttc3hYgy3fH+9lHMV3uibdnVXXMbGvYkTaX5nwl04
+H5fz6EyYbVH+tg7C9lTED6cVAg1EesqdoUTtq77uVT61inlCfdPRr8iXa19KMTA0
+ICszvPEp1uISnA5DBSoLZeQFShzgbn+WtgfNqrE1o3oqsIi91wwpPMCirYhtBCoT
+sg3qPhGyr7ov0rDQRcDqTL0pkpfhF1xRzP1vDF5PwZhqujYnFTkcMfjRmUdu3Pjy
+VtMbrX1yb0Pyxi3Tdr51k17rqm6PM2QHmamy+8Mhz4Rg40VzwrwJd96orBmoYq0C
+IajfA4tnQ8eV82N1HnMa8WAcoKmjDwjvzoZ6IwNov1ddOj4+stcjQlkArp3mUIn+
+k2G+wxHkRdcqjrsht+ntBsDRE9MmMhbuDGbyZn5XrcIeUjSNt/Vv+2jHNXSV3Say
+rkFAGMgOpk2gUZEwYVZFPuY+crEgxu7ZhmmUXr4duTaEi0l4Dqod8EmGhrBun3UO
+690lnV/6dOTGmvDo9Afa4EVvpC8BFmFrGjEmtIz6cCx2RDSTg8KJI4XBw2YTCo0V
+/E41iA4lWVfGAxvfCu1Cm7JDfvVrFEuqEbH/FbDPYOBXYrQLawGWc5jd68eRToE2
+znCtxSHRwnKBnHpsZ6zIugpjxM4I2QinAts3bqUhLdU/h8YUC6xzco+XBc+GVj1D
+PiQsopJT2Cut/uY9jRHsZrm3HvTPRaFssjqEhrUjgcQgLijGDx5p+y1bvfFMI+q/
+18+pWzqjHQKpi4VIpA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc4_128.der b/samples/rsa/pkcs8v1_rsa_sha1_rc4_128.der
new file mode 100644
index 0000000..43592e6
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_rc4_128.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc4_128.pem b/samples/rsa/pkcs8v1_rsa_sha1_rc4_128.pem
new file mode 100644
index 0000000..399da95
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_rc4_128.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE5DAcBgoqhkiG9w0BDAEBMA4ECOEwJ5V2GWbOAgIIAASCBMLjTg01txxBp1BY
+92SMQKEA5tENp6zTFZwB4L7ObAZsJJ0p7sE/vII982EsrVytM2V8gTjnRpk1rlG0
+Kow44HtQX4bI8DIlgnWdedP+Vmw8DwpiVBDC2TFZULlEXp/54pKEEcfWxK4PCTgM
+Ve5PDCPVJU4Qt+xPopzL7/sg76XI5a3OWhk50/TlkmC+IFPSqdZ5bOBQfiU0ofLv
+Ty4oHzBUdZ8X5U7B/FihGAzn+RExxgeKXQrLqUSr/ruMIIdon0s2hGGrxasQPJWA
+s7Qh+hnJuKQJPNqdXIECiZR0iBx1MfDCBlH4kd38H8SKr+J82DtP1AxJGwbTLl0u
+WQgQiP52KCw4jMLe62pKW/Pf/F84YSIvMDEcMLtn9CoSfOBvjtaNRggc8XWKtFnp
+fu9VAYgOVQWUglTIQTtWtX+xzpErCEkM2ceHKxIFdS3oYnrVf0lluiBWC9N+jDbE
+ciSor3Us2hM9O5IW5A7EKtjX45jUEexqq+66hLngK7BmzO2jXIDQ9DhkzurbC2GD
+SaUmqtWFRSOEXrXXhTK3BrPRPXCri7C5wWlQZhQi1Oj+glHg9YWp2dkcPdhUDsiC
+Bg+NL0zx/oZY3VXglHtQDP9wI7si0rVssCFDefO0xzJClssa6SEkFW6iYMkAYS1p
+ptxzrCXOVfeUWBvOttRKXhc4BYrktCfKhQYVec93LFHIIM9giS+mGXu3PAhrIuQm
+8dbXZK2VjsKP1WqS1Ao25+VP/aQZKZCcNA8meMEw9TYGfAd2VnzPOfDVEiU5+/ZJ
+9DRn1JH0M1z/iWkbH4cSipkK18BVcdOqzqL+BuxM6d48RESPof2155qOWWfHLYvq
+wAkF32MbTrkObKlmzr4ikEq07vhXAUH+y2I0vaLObOtvjL5WVMNyr29Z5DE/F5WK
+SX/BuXwQrsdqXMdunFxm3gYKgaZqvS0iDMAXBFi4JYPX08LVuLNG9KZurn/peTZ1
+TWDlVEmk/PME22Clkl7ya1H73o7u10jNCqPgVh5M+4JWmKSjuRB5F3NmyISdjxYy
+2e/YACDvole45B+SNgwKqS42akK9OFYJlak8Uu9Swycwt/+OIk8TLw7C9Jyt7TsL
+QSLBpG+mDMimwT/skpNbEn5IBFM42Ldde7oqc0ng2Y/xWePwFW27F6aisYoh7T/X
+nujylZipH8vUkeT41XfAWid4G909sirR2/KYo8IO8qbzfdKKkr2MSp3Wa9k5lYcR
+o5VQrzxcgy/x7zl/JOwOC40RGA5iojGMS+Y0dy+W6p1lN/XdJlZmGrUc9/yy/d6r
+cJ3nQzzqkrT/Vct+XAM2ZdBT+I30jXvTLw/959dyqOhejkDYuPG5TpsEJkCLr786
+k3j74NXTBRns8LT2NUQwSLQnuW5B2cKVIMWYtmhVEOVRkP4Btxs4d7KYvQTUsfU4
+eKGijUHAiPaKRJvgfCHxi84hFc6i8eGZyCS4J7Oac0Zpc5kni9VC8f2AURa5+7CE
+b16j/4oT1QvGRzjrbnwpRXckTNJJtyfg0LoIWHe03kB3YxHvbMJLx85bKo5x8tjn
+STARLMlqqgyN6KmvGHO+YIJRVAy/VIzvkyhOLkngWT9JoHw76mDSMvFlDKVa13D6
+Z6QnJfmE9gY=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc4_40.der b/samples/rsa/pkcs8v1_rsa_sha1_rc4_40.der
new file mode 100644
index 0000000..e88e6aa
Binary files /dev/null and b/samples/rsa/pkcs8v1_rsa_sha1_rc4_40.der differ
diff --git a/samples/rsa/pkcs8v1_rsa_sha1_rc4_40.pem b/samples/rsa/pkcs8v1_rsa_sha1_rc4_40.pem
new file mode 100644
index 0000000..dfc3a7d
--- /dev/null
+++ b/samples/rsa/pkcs8v1_rsa_sha1_rc4_40.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE5DAcBgoqhkiG9w0BDAECMA4ECNcyq4Se/97zAgIIAASCBMLQXerEc8Amz1LQ
+HVVV57nwrBN+wGK9b0rlWZf/Mj6L1zFTAJFgoswzEP6zogWyrMciX2WIF2XopbL8
+GYy3VdUyIS4/rIHVjXZsVM3BqDwhPyPfzCPi0pxVVLJtJBH0rD04U/fHMTOv1Gox
+yWoLK3eyv3u6akZyTZNOA1wudOaIVokeQbXbpgYtN9JY/TYLUe7snv5OQSNYZlvk
+GfAJA4JIaZx2CpWt/kp4GaAamrAImUgvNLrMqvUE3YHh9P2JyVCR1iOCxMsMNJo8
+ckO4MsL3a5urh+X34HHDRAs7Jur7VCZJmnt5Ehh/mArLRdJKrpwuPVDeRXE6jU2s
+LJunc2t1hO/nHedzBE9ZfUUTzNLCLIPtmstMdelgt1A2OF6ZbOXMhJYwt80T5HpW
+PYiMa34qWzynTzSBiDT/F9foAT65xTleftIh/IqK9rkvJH4OjLiDQEtv8ffXfyj3
+mZLBOTJgIMX4x4hihXGT/W6aF2AAzgawlThpCE/o7BGJxNRuk3vEQ9K22PKMbMrM
+lQje8khpKSK9nJp/BTRIc5HDM1tVlgmcW/5RUywyzQtb35IOjtY+RAGII0U4q5YO
+lJNLjfy/ewftx3TxhdBNWWc6ODHhmqZwgX5QW7A62MiFbjs4zqfr0UZvK3ydOeMk
+ALk4OwmZxAENS398Vpx1mNdvuxi/wWjJ3Li+4lz3p80Mkisccfv8AezcaSPigUw8
+DEfF1DfLBBVFozRCeNIEV/qm0x3wuSIO/+0ZcriiJmNNm4s4oB/qDDRDAQ9ynCaL
+ek+xvP77CjXNCvx7RyYGE5ZjrGDHiRc8t0SeUCb9KslbQ87/SyaqaKWS4Y8RnSOq
+LHzAk5xIc6YwJXMjE4xH3SyUpw7lmSwv30a+c5mFfI6Ddu6R1GhU4K4t7CgXOMXV
+1TP+e8AEMpdrp/KCETMQDYwgFc8bGUOTojmkBdouLwphfB3as0ndikvsESZWJp2m
+rPRjzKhjFO9IGOcDKQgMH6lbov0trzN5qbEORuz3MAMmBkb/+64yqrSwaFh+a6Mn
+LroS1t3ng8+rilEp630TmPIu1XVkkLP1PCKxqZxX3nG06RCvMh7dGLGxS9U4O5fF
+7qCqr3eOCkg3nQIOgCohP/fIILrKRiu3ronb9oEMN1lh6bPcLaMhh58iE0nVNZeH
++3VoZA6p7qbAREgOpimMNH22yyyyx4naFlK1ajM+jLooRf3dYqQIhcTWw9HNMI08
+bHxYPLS1CMLadpxlfRJZOcDgwwZpVju08RVIuF+Pk6+knAe04OVhx+pPS6rLfDyF
+Tozrz+p5k22EffLauK8C/8PKbQfhSRY7o24t/mfTqjWXmQlC62b/HWvsHqWv3z48
+cmcB0tRBEGIr9mWuCLVCKB/2crJ9uCRCdz1y9egc1Yrplcl4epvjtPy3dYBl7ZGP
+7O20jZ1XAdePAE6DiPS9els9BUIgOXPPhKuUOI9KtnPZ+PuoEYR3kOUCFBIJuTnc
+1GkFixrlP6HrkLnM8eGBBlGzcCb9y33G/JoVe0l+fj7HIFE4WLr7Xvfl1GH85SAe
+66O+3K3ZpUoIXMN/tAaTHMj94e0iZua2+9v38HDHrVQ21EZvraonDe9P139lMvnz
+bpNCuk6sT28=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_cbc.der b/samples/rsa/pkcs8v2_rsa_aes128_cbc.der
new file mode 100644
index 0000000..df1f7df
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes128_cbc.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_cbc.pem b/samples/rsa/pkcs8v2_rsa_aes128_cbc.pem
new file mode 100644
index 0000000..651de51
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes128_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQImXjLGxzpmkwCAggA
+MB0GCWCGSAFlAwQBAgQQf6Bn85WfZh3mHP1w0yubaQSCBNCS2Rvfoebwb7/sIbN4
+uBS2v30Q/fOtUsqbo0JGjJEZ2Qe0kRDoXlDdf+tk2dQaI7tdjhxCcIeJOuiV0qJ6
+g7y7tmcUhyFHJqm7L4ODpdH4jIGhKFod2szydrQ0lDQI7ZYjucRGd5zxb+wMphqV
+dDcjEw1HPsVnG30WTjMSJ6lKs+PXLv+jHsf56p+QAxmiy+5eD7fF/C6vxCk0E0wf
+63ZkSiprIYsmbM1kDBGnJwsH0fmTGi5XD3mXb6zpm3dc47VootC3jL6dG4259B/q
+gqXZ810mBDPaupS7zc1D7MQvqHwSAhSDFylfVxpwbKx9Lke8e81AyfZsmuUe1QnM
+fqqY0Ciu9LjxkE8CkitV9/2XwNkusyvQmTFALi735kO/l6bieShFl7m6DTK3R3E8
+iSx+ZB4dO8tH+/9DbXI8un0DptXFKER2goXBDzv1MElmdBdAQ94j14yT5aTX0oTU
+C7gaLgfzly70sEJAmrlbxFhgyrcdOZorFgga9qnri2w/0KoDjQGian+tH452pWZe
+0XadQcrAaNviFJHw6/EmjDgHX970rWj2ZXrbWI4cm8scc3BcPaCwTDP8PZrxVhLG
+0SJeAjEaME4n+Y7CT3cSdOJh6MiAzyqqTJxFMEovhDOTnyUKkJ56VONG12P9JLiT
+eIpQlV1ywkH3hTXPMe4Dpbmvn6dhy5dRdOAtRFHOdno4Ri+0+Kne1VGhX1t3i8nP
+HzRSLUg/tq3/hAwaMfHPtnE+3MXFteQgGd2eVzHiwMwcLYAoy9ewWW7+wvXjbDaS
+gQ+Oz+gDCm/U1dOMRFp33lSN/eAKluVr9ZNewJ6r8WHg530CeSMG1rp4gq5LX2vk
+SDQ0RPPAf++6G2tw79GWsCGNFIW/6xHIrBx37NT/zn/0P5/NMD4qZOrzRPdy2tBx
+ggszbUK20sXAikibVJp4YWHAZMpdexKLWcktPE41FylFc/4XI7+ddRyvcW6re/FT
+OCZFm0JZOmiopz9rOSGOgYklrUNWqAXWrkAiBo0mco6UdvBjGVFvk2Sw2b17S4Sr
+9glXPFBNMHLy1daN5mvWq1uBob2us27MiSc4+4Biz3S9FMO02HhMKxC9cnFw5ZZc
+aQHo1+USBQ1qJuvA0+od7JwCC5XEm+qunlnUDqDt8bC5WLXADDsVptV3IFIZ9ZB3
+xM5y2K2TBpXzjR+fVg0M2qnbQYv6SVszuLlPArZL1mrmMUj1mmddPBJQk9Sl3lsx
+ER2R5bDdLA9ct4mVLFjx2u7NNyYQqyvNOKGt1RD0PAlaP1nynVzuLEpnDAKrjCQI
+IDivXTsjc3UyVx5C2sc+L7HuUibi8726sBYIrlG6eU0rf4wfgstGp9l0A4yBlbRB
+cJRSBPdKN780IpEFx+SfzVeBvYUeVH0DFthaJfDOWAwD1XdQoxaPUhSel2iaaSCJ
+WK0eaYETMc1z1P2Yzr2BCHTSxOrL7YJEMDYb1Ii6MvT/xaNSk/yuqhz+rS8zqH0E
+qalCGoIi38YJy41a1Vau7MCjkxldexn62ZbI4J4dO0W2mX0Fe8aYxxGtL2EpCqnz
+9c7BBsGqGC2agru0qTkvwCKtk8duMg5RWOXnW29tBYuAyT2bmwmco20XOdTgXIUJ
+qsiX6xrG5S0T7vFExbxBIX2Jhg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_cfb.der b/samples/rsa/pkcs8v2_rsa_aes128_cfb.der
new file mode 100644
index 0000000..73b52f8
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes128_cfb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_cfb.pem b/samples/rsa/pkcs8v2_rsa_aes128_cfb.pem
new file mode 100644
index 0000000..1e87d53
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes128_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFETBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQId8Qhy+607E8CAggA
+MB0GCWCGSAFlAwQBBAQQac2kffj8EBtimaC+HXnM2wSCBMKaK+sjj94S1ZJ0El82
+Wt+oFB7t0Wi1oE4fCWofX4T04VGR+6NYzj0qZ+LiXS/4rw9AQjbCfkYm+WFhMs23
+b37+/jfwZ1N8WYMxfQ94Q4YiN6EknPouqBpKwUqUgXL+WJbmAzMfH877ok3Pc9YR
+5LKwShKJLAQkHlxkDMq6ZWRZuCSVhRzDOvR4bmrwxViE5nmyWJJZmdwz8uI2eEbz
+WA/hCON4N023fqAQrhFMrWtklPVvG78HtCTo9r9x8kNjdOF2rue7eE3TH7ysdr5J
+/xlWVDXjSOVuPzUOdeCmUusjpgC2vSqq+oKF+MsYDN04sUZ6MksZcJnt/aOESc09
+lOHmxoEo0fZ210HCKaCU8yDGvQNyUdAmfmoZ+yDoT7x0AD2WkNGPab6jsCOSaDxN
+RtMoQG7Py7OUElVj0wkidKd7oPOzxZx1WdNG1V/PoGfP/ITAxeBZhM6rq44pLvtL
+nfdkrasQ7zDHwbDO4f1K0KcgDrl3p3Gbj09Vh9Go6ENfImLoF7N4a/Vmh0vtfPJ/
+PsPXUv+fLP/lKJgd9fFPdBbaR2LWcl7sdDSxuFlgFkN0Z0EKT/9S4hWA2IETKGRc
+7lmq+PU2yljkISz6LgJOLO9LC71HavEbDB9VsBmfnj2RkvfXs94HpBQVATG3BF/o
+maTznQel8aMjglxhTZPwB/bGvxf3BYd2zGtDdbrBB4huhgKygyTaHAQMbb9UaIGx
+GtrUyD0mJ7Zj97z+WIbbTcCkqINeDtbatI00SQXCaldN4luSj9cF0+mHIaQJcEQK
+5/mQnDVYD06INUR7kOVI7/4EsBQ8TXkjwwjTAyRM9fcC2DKCt5RJuS++6G2eXm8s
+Iep9neO0YKF0NXARnLw+3qsY7PLUfUeWtTTpUfOBW+i44kW+mw3MqwxlgICgZfp6
+OmkArD0ZpdaMrIJi/EcAN/hqB+DEAkO6qd46cDK3PJkNGDBNCEM48bwNeRwzl5IG
+Dqq3gFyek0DaPpdiGBnP8W9VdG/mfzYCZkaMptRKQg01iN3KHujSZpTrJ+MPfwFc
+eDCIet7L2z8tI4p+Xm+XHBU4+7V4aiplXAqY3Bt3QgnyGe5L+r73nl21/2tpDNGM
+JdYvLecji7KK/uoSE7icYKXuZNM8F8vdEUE3UvSkv3UVStVijZdchV+0nHeTBo1k
+fD3LVWLTUw8SrrOUWpkFAUbNSmuoQxZti9vl+0cBaCipG1cc28opKuIEt1U/HYl+
+GTxOO2W+9vJy7nzm7cw7Tf+HC0ROAbrG0tPOFdePGAp1sWZyq+ox85PMcjqmeMPJ
+6SuMUXzZ/zeRa3MjifY9QywEJY8TsvtMadPAK+jm6otDxOneXcZwzuwHnd5Sygxo
+A1WwlcmrV9eq6748wopD330EZj1oSqz++6givL9nGxuk6IDi+HMmJCGgX0IXnB1q
+pqt2skUTVX5oWTrGnsbGb/JDBqmMl6q0NRGQInTr23GwRftIsBWPHIgpplqpBWPs
+lUXhdZWukX+RJX5oPL6esik5XJvN8d7souKmxWQjgPwzocn2FL1d9l+SfQeVjJVL
+zpyPCACnXFCygpwT6hqfYWz+yXSLQwOFc6CgHV6SAm8Sgz0CIfBVev8PYSgeuNFm
+momSCys=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_ecb.der b/samples/rsa/pkcs8v2_rsa_aes128_ecb.der
new file mode 100644
index 0000000..466e861
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes128_ecb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_ecb.pem b/samples/rsa/pkcs8v2_rsa_aes128_ecb.pem
new file mode 100644
index 0000000..8f1b2fe
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes128_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIJ8UOV80biOECAggA
+MB0GCWCGSAFlAwQBAQQQAAAAAAAAAAAAAAAAAAAAAASCBNCnRcJxfi5+Xp/DG1nc
+jvQbvUTu4nlM1pD/5wg4D0rCuCLbCWv5/o+KZB5ASdJ0SjaOPx7TFM4xR7Dj0EzV
+/FePoNNqCiaGy8SVFz+nCWnG4B++IOKZgTRi/zMSNccenl1HkAFdUqEfwFcg6kMx
+TlWzYUR0X4DgNZzTjm/BhQpJFduh4wXkShzYQMV/LrZUaY9JZNWIWpiaSodQc9X7
+1rjftKvPljW5kSkeOgQCHeL5F/6aTHOdrjTGlzgL4ql9JbZccCs2E41yJ1cjqUNY
+zdh9fd76i/vfFuqZrFWI/IYM/NOmD9QXO5wKIe2dHDdXBaL4DrhPqV3w8qWoVEfX
+xBjQ0uNXwfTb48s7G9RRKoWf0Q/ehVlNVxwSJ2JAmyci68C9gyG5lZ4PLsUSwLAF
+HRjozR/LPhSOZoEB/z9nY8fEFQH3q1j5he4v4j80IPFv3xdd9b0v24g2SeAoEBgh
+9IHSVEcsx1S4cvICX7bOWXIGKNhq3TiSVD5X6VmKG83bNdUivbrmSWKOt8u3sKXz
+FmE7CSHFrsJI0I1sCfNEbNS38GZBYkQ1X6RJ2p3umR4syTSxfl19S2tWPE0HEpJi
+uD8WFm39lj03o27ujnp9yVPUPGTAP2qzIivG1voTUFJ32z+0rWRDqxP5AZfrTQfE
+DgI+uzsEBwCKLmnWaMAuHovf++7n6qhWkM4oXzb9uv0xUSfZdk8/1pR4zxjNazz1
+JgNd640tgqAoDrKLtW/4hP/N3yY1C8Hjwqt0GnqIK6UdGnju0n9zXiNfBLv9Um6L
+O0b+N3nUZ//RAkFTT5ZRPZ147EtrFIbLhvu3II3P76cJaJrpZ06/sYUmTjHn6JCo
+XXV8u+EXr7+Mt+Ml5GqewAOxs0yQw79bszmTS4U+aGQObSxMKFQKe2N0biTo8Xit
+EoqggCtSU9S5sukI/VAEoPEhojsu5kwXkdN98GibNKCg1A1e+wVWari1R8XWQtB4
+swe1jO9iUTWc7zc5EedzVyhIv3Yockxc2smNGmco3gF3PImi1kWtgMPKuu0YTdvE
+R+Elawccm3w9wmeCHDL8/jTU7vwGNKAN/MJ2RePGLXg7sPSruCwuzNz4TzRrHuqn
+jZGslqClmz5ASjNihun16ObAtP2q9nfnvhJh7I5smiSoAPbt74Fg8uAZfj7pJONd
+Z4QVs+zVlF1gi7VQqNrVB0zKnA2xDeobqZG8PonrwdfwcTlpwPA/olct8EHP9XAq
+kMRv22iKPIpfs2cTMDNj/1w4r6RkzWe5pfRe1hAwjLHlDKTiOJgAAOX5b+NbVwdG
+iwbd8ajh7sfn7q4PMxB9O4E9t3zXphafaTNqELAGndsmsOFuJGwmFvw/mFkbhxYg
+fbBIFsaxV1IlBEuxSKYymUnJqR4VVrhSEemB9HfAW0sgdPEJ6Lsh/c01WzqyzVbG
+9ElaC/YQpLsAqmpg0JrSN+4vbMSdPpVjWn5CYuBeTmJdZBLgYHitg3VSqMTHwUfJ
++P4oQMWHQegL5nuOsRZ1oeOlLqQhIYVyGn/Kgas4UWGvv8NbtoUXJhhIEo0EfzRy
+YUCB0b3yCWdJ3ZyqLvaCMmM60fBC7FHPA72oRL4OonUwRdbz9hY/k7XNxcQcIaGV
+fCkBBoVYSzzr7CdssamJDBLLUw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_ofb.der b/samples/rsa/pkcs8v2_rsa_aes128_ofb.der
new file mode 100644
index 0000000..7bb364b
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes128_ofb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes128_ofb.pem b/samples/rsa/pkcs8v2_rsa_aes128_ofb.pem
new file mode 100644
index 0000000..4b57254
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes128_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFETBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIYBTitmleS5QCAggA
+MB0GCWCGSAFlAwQBAwQQfpTMeedMDwo4LcSfu3UjJgSCBMKtj63O160n7dTs3+YV
+ds1bZFbJ/8TvSMOVbJn6VZMy6l1Hh92CcGuGzLulWLz/XYYgIvsk44Rmi/gaf/Rl
+5Sv6EmfGmxzwb0RqbyL8DTfQie7wu417qwPOqomkFzlJ9/Ku3hfgFDykMEkjr4bV
+EHrTHB/PzHxhY5dfFoH5rGR6yoCbbOpg8p5TguKxAU3PdPd2xGHI3AdtsdrWFEES
+HahIa5TkHCjHQ3M7QvuVY9RI00gmf/N9OXccUCUXusoV381W8U2WBPuatQ2Az3aW
+iQF8XrY6QpOrvIDdiM84AabbWYk83JcMDL4JGjEyYHbNZA85fw8mD/OTeH/fPMmt
+4VKuA6mRjZuAyOpBh++4pWk+GF3/AiwbPFZCM1Hyg+Q4ozHgNOW8RmwExHfEFsQV
+cAgZBJS3j6ot6wxoc5R6n7cNJPTSSRceP7Nodd5nNyj4bB37nPZNgJm9FprsilEm
+LCM7IfsV+gi8DzrtbEi/e89ZMkm4ENTD+9lRjLdT1g36Qf3Kz6gUI81lAEoqEKSb
+yDTV3jkA/KOFdqzuqwXGIi6mD80X5cLOmVvjWmtQh76odSyIAesagWwksoTuMJsa
+/MmKsSszUy8/m2xYKTjQKADmMnRrrC5ZLpnRdpwKPXgEXVlKkPQz/Vw4lzGq4S8b
+m4qvVrtTYZnQwqyU/8TC9UMqwxLjRlKR63oQuqfEw/3QAQXPPtGo3P5Lz+bvtZ7h
+PEZr8Nzp7Z09lqEXFWww9cTQH8AS/Aq1jr3pFIf9yh/Jdqj0ZlEm382PNC8avUbc
+pS07LlgOeGLrTWZQhZVJSFm5X+y1ws4Row7wfgoscp94KczkvkToTQd7ckz0n3gp
+N1JuSCloxLzgnE6iJnELc7r3FHRqW9PZy+QhXTKkgG12sRpXeL2KTmyJke62vwTs
+MIvdXV5qJUM8LoqStkDFksqQT8q8Tmp3/wk9XHuI7b4omK+LEZT2MrK+Ot8FLpbx
+x8nDbXlnDt0sW3MjaEcfWKj6azitn7RIqAvIdgptj+JACwFHlDG+02v9wP/Scsfw
+s1NQgpPnBD6vYU537J/faWn37kp7ai3+8l3+9E+cF3s17QI/MBiRF2ZIW5Ps1aP9
+ZeqJF+irwEOs37DdkWpfZowXkW+YuFUTXUtRUqVBaAe7ZCbaS8e7jlS3+tKZ+yHp
+30JlArAtBgUymY4D5hqIs1EXGyrb7l75nxCuKcfnEz8l9BPHB+CelhWN7DJNE17t
+ncqT8wRF7/d+vSXxC40BQo4b4n+33MJ14RvTIamhZcKUv58lvFhoaltxazNFDx+8
+SxlCpuP6vK03t0ZufNpNJzppj2g6qSxRARkQTamQkg2SuAjbt7mNXIwg+VW3U6El
+WEyHJ+mewX91T4Bwidamw1Oe4uhWSx87vHJqcrvhpPjFACrZXxzBvyPoyDk1Bmln
+SH1p8awSS6s/8Agrng45ZBaWolez459R6xscXDqUAFwqe9In75Ojlj8ow/HJJu9Z
+kxLf3nWrrey+lug9E4p+Zx3CgpAVPxm9iJtCwBDFcOvu9VgOUleZO1CvKjDDFOE7
+z38j5mSmQcW2+1Tx36JK9uHoD6+p8i00wpBzeZiY6JMwx5G1vUYEwaNd00fL66ih
+TzcIMpE=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_cbc.der b/samples/rsa/pkcs8v2_rsa_aes192_cbc.der
new file mode 100644
index 0000000..92b4c02
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes192_cbc.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_cbc.pem b/samples/rsa/pkcs8v2_rsa_aes192_cbc.pem
new file mode 100644
index 0000000..16ce386
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes192_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIFf5BlNNsxVkCAggA
+MB0GCWCGSAFlAwQBFgQQ6s1KV3GWRHthTWZh1wm0DwSCBNDNscsywNkbLh2xD/5h
+vn/IgPbkjZG1en4QEiX4bS0T06F7JVHNtV2nu7zkbDg7Moh3UyteIyTeGyTdqw1g
+y7GV4U/RwDU3QDY3k0OJJAYIosUxJSyc8g8aUSY/Q9CCo2XPAZ4wdAP6yDcZtYRq
+PaXcQIAKIKayKFvBTr/ekV5BY1V4xpAoVjKNDE5rICPY2M1M8qLgQJzvTdRqyevg
+uF98REPA7rSiO+Uj5bfHkNhK5RQx7pu+dM6GhOiItKgWpLBEfQN9Z6Oa6MihUtbb
+eSbNdkdx5PdztRPRRMeTxICG3fDReYdvaNAh1T3x/qfYutHlkToI+A2jYMd/NoVO
+eaHlpXIB4o4d4TKsIbhR0YrDqK2xJxr7dVbEkc1rY7TmByL+Y8fHw4KXAV1etmvU
+/9SGCEIajdyeVN+v3RiOJPyJvfZSSxiv1fRfmoUTpCyLkdZVq15yPO7bIwN9xDPX
+pg985onYKXxG6xy2Ck9ErVsX5iLb1wU8f+k5E2DAxF+oAZyIpItnH65/FEkGdAYu
+orYilxbOvtB+lVOZVgYuE1OIsOy1wc6GEtoZ4UKo8qkGHTrqtBypJRhUQanmKPOG
+DHMptPj1cyrLaAh58ZwebGaSi0gSVtbfmSppZOpc5O0tnEFr2+uAvKnP/tSyh1my
+SbTjkDH549C8Peu5T74TDjM+1ogjrecLWOyij5ZBVdFWp/s+lpX2Q7MQLsXrptd0
+nLrnIsMjphSXXCFLZHm/hSTI5fcZKVjEwNCbVj4UMOd16oO5s66KuIX3Wg2MG/8U
+isSfVsga5E+kIyChlag686on7p9mwnYVBNI2oGu6zXhSqjiGdwRmUvoayloGDR76
+vtIVB3vPQCJTMMdbDxJ45E4Avr43hngWCp3X4MvzXgvFnvbEmiautqnxCVwRXfFS
+dDWlGYKvb6dKKBrJ99muxYUik3iJ/riQpp+BiHbj+/Ox0pIJKpGhL41vkvuUCaUV
+zri5SdrPL4OPBPZwShrIglRSAgd6Ot0X7ZbeLV4hmkqE37hPECWS4lYt1wRyC7pz
+cB5DbKoE0GRCox7pOemWRgi8TPFtvMcMdUmx+bCZ+KNSfzYzLziAyBm3LC5iuH8C
+9O35aOihXyZ2pvQuQCQ37pSuVzm3ySQYO4YTSgY6o8J4ypi+ax8g9/StEJWP8MxN
+DwKMxHzW9rD8YKxgi38yW5gNQ38lqEyxgwG1PGmkfqRtk/2XOTJj6Xu1h14edYK+
+vXxeESy8iwBFoHUqBQDv/tPMXTvxRYnItODQY9efVLVAQ6jPOgvoiTubeQTdX3JR
+J7MBVHEqWDY1ZWi4RIJew1h4txFDC85UPHhiRrjff/EMyrQNzFoyF9ixM4Q+Wwof
+MlTrGI4839GtECTRdvonzOSNfyUGQS6B6v1Q49ogBqk+m+FNjfx5hYYL7rqtvuG8
+VVbQiV6ImkDRFme6gbmiNKrGMrd6Ntpah9tAD9v+RQJu4Y8TyNBeG5Jvta7GAk1Z
+PdUNF1Or53aeVIZ64pS1fruTiXB+Z1CnSHo8EareYFjnBIvTjU2Z/OJcnp9/vL7X
+GJXRJWcrnRcBaiwmKPqQ905mATsr/TCR57yWHhH26VWd5bvb3fNbtmbf68m+godP
+PtPPRfTKSh55tmrSvpQ0WsIUow==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_cfb.der b/samples/rsa/pkcs8v2_rsa_aes192_cfb.der
new file mode 100644
index 0000000..29becdf
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes192_cfb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_cfb.pem b/samples/rsa/pkcs8v2_rsa_aes192_cfb.pem
new file mode 100644
index 0000000..942fd9c
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes192_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFETBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIwocEWtwMl2YCAggA
+MB0GCWCGSAFlAwQBGAQQEQR9w2BnPQ+TOMmn5o8SpASCBMLJgyqgJCp58K5DdDod
+wKj+IZVKl8KTgtYyYvhfFcYSYbpNamV1hipz/answ/ECJCi59iHlo9m5p7bYGcMh
+rs1QT757PUMVGHwGv6GUC1QDr4k/DTHJTcJ3Lk/vo6HkOUvr09XEiGL4L567t405
+Z8iZgvoCoCQLWmGvTAtsYaR+hk3foTii32fyn0O1uK8VKrI0Uf5X6mw6yGj+NUD2
+4+hSTU4ixsPWxEa3El/CPuBZ0JAxGr7IYMMLmLulQKW0hlkbGtUZlJlVyoopUuMK
+PoUN2GdzOnupyH4ekLSgnUdq6oFSH+jitmpIZeiFjLRP6SRrhhtVPVkquTUzV8Xe
+Czo03yGr6IY+HU4oc6EU13KrtQNL0oOzM+AnO4Wdl2QXi53U0z3Fz6kKDaZUGuQM
+rHs+/aE1AV2j4B64vQs9pvQWBLx4PyprYi0Grki5gaiDKBA+B7Qa6X27hB5+5y2N
+wZKQml+P0h8sOMOwovlh2atBSzEkiVbNWmTPW+vqiaGD4TPIMH5RZlpjOwkTd8mp
+IxHu+Kdf+wdsy1+rjBVUKuz5pCI8yLHqVqST6q41lHYsEZCpL0otz8AVxTNEQfio
+I56+208nZkzk6862uu/n1IfZvuKKkcNls04Bydj+Mh80Suk3ETDHCqzHI0J3towu
+HnS9DhjEB0yEkpIJJ10xxbQ2yj9i0eC2rmc0KlWhiWU/HHYfaEHoYJRCfs/cQmTv
+w+Jjxi9e0HYWqQ2givReDhkqVOSKW1jQiOFh6iTdq792NWCGPr6+sBNYxE6jCjU5
+4etyxD68NUuAWdPss6emTJzClnaNvhIt0oKidZME3fycan/Lu1BiRkQhw2wN3Xq3
+PhMFgiO6OL6VUqa6gnwed2s4kUXfvKDfmLau7VIYFMVDXVTL0PAC0+KM+n5M/2Ou
+t7ftFmbxrjZF4Yrj8pe0hgAad27ZjvnB6dr3Hvcf6s3/urQxF01SlKAyEgUsvG7m
+DJfRj0IU8lXkVO5kmUaW9nsjqF3mUiuqJ84/8su+/pQj2/3zya+8f1DXa97gStiz
+mH7vgbUir1Tea5c20Z7htQt+8sTVNWvoW6/9fJmFD655pmk4vJ4DK1LV2w7sJ37J
+L3gk5CjcPsrtswDiCg8s8gUh6NZvaKW6TmPjrK0Zttoam3dl2ypEkqnmsoSFCvnG
+Vbz6tfvKXwDCeqRrxEEmvI0Pr6UfedBcFBtlI+o0OORaWFstwS0UFx0mLCyusPzq
+zEBHdJyMKomPr30o82RQQdlFgo3O5ODaB/tXH+LzNC3qHaGSnqmJh5WLHV+n+Vne
+kkov6IamjmwBmYZkOgmHRkx/0ljpnpb3GGBnGOtJrrp+O6Nlm0C1iVgtTI6RC7Sx
+DC0n1E7vEeofQWamzPutmMrKluqHpei2kDBdcgk34KIbyQEwopjXosO/bRag/ekN
+akhogLBfYs3LR2R7PWgR1L19w1SdNqfaqJwRmq2svBHQaAZmsGvL/cDk01KDj8nR
+eic0pYG1SwPMFN4R4Iv4uYLH2Sm3oP7EpCkNFZv2j7UkRUXXA/BhdQMsn0f6ZBEC
+FpVcw9rwqv24nZrC8WLqSDuAdT1QcpxSBHeL0JCMVD2gNGn3n6JbAjJCGZ4+BzQF
+mXJqiis=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_ecb.der b/samples/rsa/pkcs8v2_rsa_aes192_ecb.der
new file mode 100644
index 0000000..fd32604
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes192_ecb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_ecb.pem b/samples/rsa/pkcs8v2_rsa_aes192_ecb.pem
new file mode 100644
index 0000000..412f57b
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes192_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIpbFYsS5145wCAggA
+MB0GCWCGSAFlAwQBFQQQAAAAAAAAAAAAAAAAAAAAAASCBNBLAAueXBK5nlOxXmUj
+VM4UZJn2bfiK+3iLmqlip29aHS2eCHgieVZoSJ8wGSzERzNyTYefKGlVhSQ1az7L
+88sUC+NeT1jb6MdpLPiFprRuh/nWIBt8PzmrJnhwWVLiaSR6cNPdiHw0bkML2uzK
+zQNru45h2nz8PqaxDsyOAdpc7Jpn39aGXep8nZ2qpuJ/UV7zxsKWGvl6WBudrH43
+4lyM1ZPQJiM94UOX0YyvtGQkwWKdnJRq1xC3DLzW05NW1nhHhZaQZgAmtk83RH9s
+g1o4eRbjdnoTQyP9ybmzJT+LqXwIYuGXihL5dmrvUqA1LKthVrDyKrXKBOYNNPUq
+v6HFWYc+Qux3oQETeDVs0kjDbWbIwItFY9LAaKGINCJxnqJ8KaUbHapETj06pvSa
+gY/dEvICQp0NB/qS8KZRnbHsLMsosFdF7vFmtkRXCyIB4GZf5NYfndBufXT0i0GR
+Pha4lulIefrOlLCi5PhIN/rVoQplk6MVpk+wz+/zGEffvFD6g3uQSIgSEZOyr19a
+weZNIKf74ccUVqLVb93BL7nwOebBB/kiiHvLa/ubHpprFUtuxJij5g7odNQsDNEG
+MrFtOZqAaL1xDQHavIUcvyHPMfkskvToqdNNNXvwSnOBs5CtN2ErUxo6X7ZPoWGx
+O/1lBARNCEzjer8/zXYrU0WyzGdTm3hP2oO4aHEayIjDcbrnPmf6YMeQ9Z/uJgOz
+xiy9wL4DyFy+oVrBEA675jjXRAMEOpVabtG+DPW0aPnZImbc6kIM6hEKMIOseUAE
+t2zHLTyHS3zv3VseGsJOk3JMzrT1LHc21x9UUWLGiXWCYDde6FiCAgT4upvDyBDN
+Bv9Yjt2ymEjWkl126xDF5Eq0ew945iU9xD2caYXqpvlk+sOCn6jFyi4IigWluaui
+AGrFdeT7TJI+G8C0MRSG0eq4GwNg+2VxhaepYdKl52b4nVZBYcVCCL2ijBjWQdET
+APvb88WgAfCaOPdvRQ0qj6ZdV7HwhQxPgrc3GM4lgTlu66PtrYfZt0tLYp8lSFoY
+e/EMy16ZkJ5uIqzby76lPF6JSOaqAh4lrIjOISXYwvyEjfJMAib6IzgCnHrXHykq
+21pmZrrLaFHSILizQrohjPRnXFkUYWcpM5kl8NytQwpBpXBcxGV45TLJ9ykdsXhF
+UMyHQoyv7CM1xhYpu0huEKkm4ee1CYMDXU8j5xV3l44NwXc1UjACrL7TfAX6sJuM
+jJOG3gJLBnSCn3G1356nD/wXRkrn41DlbJentlGRh269+cqzwOOoKQYRgc7ClRVP
+L7g7XmfXm9BCn7IlMKVXfr9zkjQgkE9vi7Ann7EQeP8XL0IiW5zYD73tgFjt7Mzp
+B/O48zbBtT7vC/JyW2fM8fWhafShuML4pXFCUcwyhqP7Zri1X8cyNYfQZMImECD4
+HJzfszKGVSQAlBwMdma8BdKUKTKm83WnQqDT8ZxItxeHprYvK3ZxxKRNpHB44Wkn
+nUabNOeviSYf7LljVP5X8fGL1GM/HHcUs0FSniL0Z2g3lCS60ntEL4NpNej2EusZ
+Svfb27XJh11W2jLHsI0JaCnpWH3tFNgdcfohgtSLLDxAaT+/7dWO4WE7ZwQgEL3U
+6GiW9hdkhEsHoaYgEALVs2bsKA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_ofb.der b/samples/rsa/pkcs8v2_rsa_aes192_ofb.der
new file mode 100644
index 0000000..0f958d4
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes192_ofb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes192_ofb.pem b/samples/rsa/pkcs8v2_rsa_aes192_ofb.pem
new file mode 100644
index 0000000..2b0b2ff
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes192_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFETBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIAFIDSmTxSqcCAggA
+MB0GCWCGSAFlAwQBFwQQB/dDK9L/TLCwZUmXSzErFQSCBMIVw25Vc1S5+aa2nzx1
+33rZJL7h7UwaJJifFw1hCXLeOodR9iNSdTK0INnRwl/SQGB45nxTQ201o9FTNACX
+UowUCQP3AFr8/etdkZgBvv+Sc21o6VgP0nxQ2xE7tYmt6I4vWgsCdfZX0OjuXJTn
+X3xRFvmHwjb40iZCnxuptVB/kCPKQ4LqNBveKRAsV4MtODLtns2TWZaFy1u0zEG7
+6XNaTHzT6KjOlJCbEcYuKOrn6eUZLb4W4IBM/Chq+Q83yi3G5vKxc/MGw7yF80do
+7eEE/wnJyFt2EgAsutxDwOyJLN/cx2W827hIGPQY3N7Sp95vbpOBWGvBj/qw8hca
+Iy5quIBbkC86MUebqq/5eFYa6Fw+ArUpCkt5kmwGiVBBkPppxsqtW0SsNSFAyuEu
+BmA+/cjPqGx9rsqJhXCve6/tUOk8eTji3zyHPH8hGe2tkSfsN545yKOUPuZML56b
+deZCi5PjzUEGX2cLf+8KE63/Z+vqyVzBd2yGlxmwLoY3A77r4zefTwdu/ogoVZH0
+l4sPh5pRLfx3334hcglZ7ezh1M+633d0V6dhlzEFXTit+jaDXTIndSBwdLDgYHgX
+SEZOgqBtTowFTLMb5YPu/RObiDXucm1H/DKQZXOPM1th950Se/XQQq1gkQpqxvGv
+/FO202PD7PuZFE0yYkjb542YodXzuVKM04CjliSWjNlgNu36vE7yXyz1JX4B63OR
+kC/QbP9GKIwA0FLyusDs65wO7bJtW1IAnfm+HhjRgH1xh8lMb2Q05UhS458raJxb
+DstoQbgpW8FS1vTWPkJmRzkIDC5wuowgKnvrrWq0c0EtHH9kFmRmcJlTI0/di7Uo
+7rCdvf6Oi+lDM3/oTpiOKCN7Bt0TWz/HqWj4qo/OCaYOy01J1kaL/VDlbTkW6Qlo
+CpRtFqAVw+BpSaChKRAwaICvoPpSgHpc9kcot2Vb88Ar2PtWdWrrMylg7vMwlBXN
+Gp0RArOLybu7SLTF4fkONm1lK73f4ff5AB619FZFyytHKhj45QWQXIPAiuYHf7eN
+cpmBjQG6behKgMs2UbzS3pttrB0QVuF8wsE9K/3nC4WOclTrO9niwg9iQxRoaVAS
+0hR6fG7wN/Sskv9E0wHUIv1cZWouDxj3gxkav+/4efwi95h3XhStSVa824XmEsTB
+IG2bqislVvZlRl8kYdxcjSH/cV9iLnQoHU5Ng28VKFjIr2P1HhzFjtZYT9Vxecii
+urKS/8renQA86ONnJUkCIcx+aJtR/81+aNViX7ZBO1++l9I7ujU3PxkbGWaYFWjN
+papweOFGxUBDUF1KE5f0b3u9NfBx7vpzPsz1iKhkYrKaWUaXF83uB23zeWktnF9J
+xKeObzzTbLLg/xiFMDrJiqG/DLRLjXDOhqTSyWCUanXtsqlHOQ+nLKx3bGz0/z/N
+F+0PVBzPe/r6tU5l9ZAqjAbmpOZ5/rv9lumq+4BNSVvx6+h2HCoFWkDjrn1JPZ/B
+LQDMNwabOZ6i/Tj9IhMRYMRdN8wqRWUysX6s5auuNcp3ujZXVVZ0ot3zkhX8sXYo
+MD9XnXHzu/obCd68rl1UpuNTuXSplC5a4R2U3vuoQ+6eFGBKh4YTZN5xZppX4R6D
+J2IDxik=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_cbc.der b/samples/rsa/pkcs8v2_rsa_aes256_cbc.der
new file mode 100644
index 0000000..0e810ad
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes256_cbc.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_cbc.pem b/samples/rsa/pkcs8v2_rsa_aes256_cbc.pem
new file mode 100644
index 0000000..8ccc57a
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes256_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIacMv5EvHgDoCAggA
+MB0GCWCGSAFlAwQBKgQQCp2dvaZRkvo+B1rVXRkYBASCBNCcbb+6XB7kPjKT0wp5
+RsbuqnQZP8X5pdlCjCvDoIIpXtGFFgVu58tSO/VbUhvsJxm/R3AB/rQNb4IyKnnE
+Uhgo3DoqYyQQba+BoyOPz0JP9fEvyBGFxLSPxDfDKk/PNO/CRCHra8eX6+eKjKgx
+yAwQOg0PRgkugAy/fKwC8XqTlgpiKrWDmpPK1JtwfYFQmDXv//67CEyS5dqFEOVi
+S98BkbH+8doI7SWsF3sdpzI0ikv0mkpJwRpBjwLtMaiuY2ErYJOPzqkR6BVhd+FE
+OvRcAVmLjU2Nic5qYg6gNERowUTPMjOFjlOeUBJZe0cImQN2A1gTsJIokohootwL
+lZe5IJajBXCDA7Ps3LagWK6+WDZ6i+hieM6kH6UMzxiRyTqmE1HSVkOajUYJ57RY
+hicAp9lV6lmc3gTdvHWTPhidphzy7pdaCxLilygvBRPaIWlDY2lY3Wxfo/qy1QlN
+y42IzLKSsiSzynwiFVSWtCSEvxNWYCjuFYMeYpqZcauGA+tWOXPI51ys6oxYxemb
+8IDP9dwgjdbHrHavE2PwjoM8LQRBtb5+21UY4ygm5GFerTeGnlao2FUXULm9cnqW
+y5oKk0ghpGRt8lbVUUTriGWN88skf1fBjfUAbCBVcK9g3OiwiHLfQkaItkSP3Qq4
+qC2bQevt2iDDkoW2ilJC7eQzrkpuuA2n1WTmB7J563z8A3vatMp93tZvtCr0/tTh
+i8oXuavrmZTNcG998RpRGTydCP9A+YuxvEKg6hU89uzEEGABt0+ykmQ/6COydics
+UVvFfSph+aRu/QxFNCkrmuajCbDtFUzZRew4kYzS+ADrMhOpHqdd4qYWM/9KrCcx
++tz25jWLdtKUKLP/U0p4QuedBO2ncDeJVnhVYEh8NyOvDS4K6Q0GuFqMDLQzTWMj
+MM7YSyCcKe7VRbWrlzBasUTOqoGfz0qB9Cu2iy0FqMnJo7X96iRXRNvATFL5hxm1
+1+LHsYmaO6iAnA/SNOmieXJ8Ywad4xrAd81B8iN7K9+d/pHxGDQ/NknPRyTAUPBP
+lSzeqkcKdBbHKeo3dWGgJfWceTeVGGDt3gxgjVkGALoogxmHlpF+D61tkzrphVK8
+MqIuCAyHB6kJfOfOern/GuRYiiU9N8zNF6zQ/aIMAOfGA/CpXW0t/jaUUiL8syXu
+IfEWpfyb+slFPmkIg5aEGHj3t+tFbHQ2zlGbjqXx/XQMIf2Tqfc1U9eP8FnNfonD
+furVawdSy5UsSSDbl+hqrs2DrpfA4l8LaP+/FQctXxZc4s+cS7GZjpZObahG14ep
+RvT8Dza+Wfv0WfGxlN75Cg6NNCpKBpMaSmwygFM2JlFBxsE8HEkHxE172pw4cKg6
+y9DievnbsAKqU7lceljTYerqFQcQnC0SVVxpH23ailDPHTZjE/85VWX3PLbOejSU
+f+HiL8J4q5JiC7cWUS8FrEvGS8I4P3SrdS39rvgU+SrVrxAuAoK86TH9A9Xf0iU8
+ySLJKzAWbI6ioQm3RnRxh5mp0RHBzDZGLT0ViVXRS8r8BdnMlkAFJ9QdEmHmNvNL
+rkZpxMghheKkRcB7sh/UgWb6bd/SUwO3Me4V2Mj78uE6H3Ces4dfbyNntc4xYQ3P
+sVXaslDS3SXOoyMv9ifuQs+zmA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_cfb.der b/samples/rsa/pkcs8v2_rsa_aes256_cfb.der
new file mode 100644
index 0000000..3ccaa66
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes256_cfb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_cfb.pem b/samples/rsa/pkcs8v2_rsa_aes256_cfb.pem
new file mode 100644
index 0000000..19cda1a
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes256_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFETBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQItWMJ9qt32P4CAggA
+MB0GCWCGSAFlAwQBLAQQrOcV8g02pInohv6kLjyZqQSCBMLVaid7VH8IMQ7h4QNR
+jRP4LLjcZcoYvBWmlyMMa7ihajhaLJf2T4q9kaONfYpPDHgehR6zT85LlvwSuRWt
+88p4cajWyJuPxZ6eEr6OCS5WTpssfVHAz8tBA4qnKJVtcNkVFIsFJz759aAxf1/c
+zh/4lHQNdLwZoOoYLRf8zDifQybJUqkFFD32cHezRyjOhI4qWQxgKmGG5gKyv0BG
+zBRjUCsj/0/e0Eo0vmGVeaGQwrIuJMESvfjysRGq1YfMNXBY2gHy3W1Hm6t22DwC
+Jncadc+cnsufYa38ATcyUbWkxa2pqPQZIASqqMGIGav/KHZoNyT/E/P+E2Cs7vhd
+FZUMeTR4/Fi+UKMt+V3KS+kFMnj8SP5L9c8TE0N/gBhtwQicvdNgmojQXD/3a7GM
+wckQ/eWz0VrbKNHQY03u5Ymrvf701CgfXjM0R1PVtbUHvI2A+2/2pDcrwxnZ1mdc
+xhMHSGN6WMoRVsjh1FWFeIA5MFG84AAk/G8x6XHZXEzaqpuB6ySk/rLlK3GLNfAi
+gMb8D42q5jF70crLD1wLBYQMMNtRovQ25rk0nlZG+gkpqie7HESngH6phRldM0KC
+OnlkBZT9Nnfnm8aLM/4vYIzF8qsLZ3UgEdPu/B8Z7hrUeETsHTr2g27E3DeJxmqe
+ysnVLVKsAqY0LF+IpnrO3v6asU0Og68DXq93Mo/U7kfSPeXol3QBmMKs1OSyT1vP
++3BfWN52TBIutLDKZN6QbCd17cJaUjQ6k0C4xoGJJz+BoP9rSMLlbDCatqo0tHBJ
+go1RFfkpooy+ZFVgBxMpEgiD68Gk2N/1zvqtwxMNPPJituY6x97DZwf8zYmEgKey
+t5RWS/cwIO4WwwCdy1riZey8DrgRqxZO5GKExnOkmFhH+k3TvskjYzwX2xrJbLGF
++xasm2AohpSTHd1BSCVo2lhVCDhRqrS36I3NNwI7qEOaWHSjzuS8f90CpV2fsf5l
+VTTzRc7c8296E0k1thpn4vq4bNH+4RmwHiPE2R40r1zPhaPH4uwmHRb6R1gbptM7
+aA3rTZwvRfmMtrBZ9uFgwJARn/k3tme9jjUOPg0BmVvSS02uM4B3mF1X8ON492j3
+Ibg1fwtZX7uER+JaHx+2ydteRdveL5bfx6xv62l/JifUIhlhkxmw44/SOX22rl45
+/v5PxTwQquVJq0OIHQLiegvb+SGROIulEsGSs9xpVRZsJT4MypkYDbuKXIcBnKvh
+0zefCiUM2r/UFLgDryRrQShaBPp4I4zc8iWw7OBOcZlR8spNd4pXce04Vs897aSw
+4dky+wizj++eOvPVyJhapFEqUbJDSbhM2dyffB4BI05GTpPuIWMgLeP84MjX8ba4
+OCI5IiFoyRyCt1weOxxXPHNiirUvNcXe7BCKbHcfkj5l3NI/5ncFVR8RoVReqgfF
+ewro+RJrhiewFRvC8qdA4r+RiNv1ZDn3btSwvH2oVvRVk1zzrJod4Y5rI0GcRldn
+NGvhzs+PULdS/V0COsWjyIACRR8dbPKd1GEM/veFVFb9zgs3yhSjLrQKig5ePFVn
+7u0Uz8URs0GLx0sRBtsS4f6SI2n531RULzOt37gfIYTf0aiEsJ2boHPajRoE6XKE
+px6YSso=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_ecb.der b/samples/rsa/pkcs8v2_rsa_aes256_ecb.der
new file mode 100644
index 0000000..ea4553a
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes256_ecb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_ecb.pem b/samples/rsa/pkcs8v2_rsa_aes256_ecb.pem
new file mode 100644
index 0000000..0e2281f
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes256_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI8u+Z7SFPcE4CAggA
+MB0GCWCGSAFlAwQBKQQQAAAAAAAAAAAAAAAAAAAAAASCBNAw9xUq40IIV2tSyK+K
+gJp13md8srHqWafHfw1BAJv8aa7Gy3FIq7r5WFjxfaQwrdUSLbesT75o/tdahn13
+DDha0QORRk89Sm0CN1iId4DCicZliys5G0kieWJjemA7xBrgr3Zv2yakG6JUmM3K
+Kjt9bpp2yC0uC3YfkJ1uWD3dWUS8uesXeSJoXmgtR/GJSV30irVarR9lDERcaAaL
+YaL2qEtG3OQhTyKUj6nMyRxGU3RhPtLQ2OhHyLhGhvvq5FT0JIBT4uuSNRL7pMj7
+G5uZCCg84q21oN5xPvqeB6RUkxHAqOI++UiOKqq3nm268medqBmph6wmKmMvKFgH
+jGgihkPlwtfTWba1/P5Pk0HkVeAhKXUCRaU8uCSfXbc3o4PFez0Edh0dA6bSpMQ6
+okcBg4BfkhDsbzkZX6LpnBdm7ItfJYgeUL9JI8qAC1bVVnPrIVTODFxVQj1B3fTy
+QSDrB4WYkPAdUJXZOEYRcJNCzKM19T98nCpIz0Rrmx4IpSC7X1nCHyL/VMLuZNrA
+Q/rgcipfjbX3up8OsDm2WR9vkqeRHuCWNBdsdIvIB50Om8tFVx9q2ZqXLzpYEgBv
+8mwXGlunGi4nkQIo0GkMkPeVCXN/rtseQvAtcPRnXA8mr22L1icmIC9EeDP6sJK3
+p9k1ptex9WhvslHMJhJQe8wz5Vf9vVIoPH7qaaTVOf2CnQardQf/wrtRilPqDrii
+d7+8iA2loYxnuzbRHVrFg+utls2DWVT6Ox9fdUVHNsCFxvGkeD7vZ6wOTwZQSPFt
+oNLDjp0sjmtwy4cjYRhZrmMutAxC9/LaqzpbUe1MT+4k3jl4UbZ6PyijS1FFYvgb
+oREAyn1MXY+Whir2ldRn4JF0+4t31WvwfAnDKp461i64PEmvCm1wy43MRldqI7YG
+vZs5X0H4wqFkcIU5/CtTSNfHJ8mf+Kvr957ni6nQ50tRhlxZs7wpBq8dDPWynZEv
+a6+ftAiHWK7xajEp98hKsf7/oNuiz9frDHQYYNa2wKQa5F2rQ7nJqVy+46Qo8IRp
+e6H76WqeiXMfBfsuLs9dm2elGRZlAWiKlmYYpDxxUoEknDYcuKGCKFaoQ4MTna8u
+50HR4aegbaAoDX1CYQR1s8jbAOrCtf0kwCrz9pGTVLRo4CRSnYAmS4IZxUPpYuQk
+V+5433SptoRK05kB2eUkkULnS4614v2lqaVmPceCdSAfkMdc6YGJvyiohHZf6eAI
+lXuYVSRdCuo1B8+Wo4uxL2JTovjLg43pxxJnInwE3IEbGU9lGNn0xm45UHHuXoFh
+LN9htP/30O/Ls8chi5RhGGDKc/n/9nx1G6LkOpX3adXgEwib1KKZkdHrOGtl85Jh
+HxEDcCnOLZQV+WnRu4zsoFEs78E0lJDkaXoh8l3tV41uAZCwXZYnjwWCrgqdGk+o
+4QKeXaJGuaofopeB4RdJ9yEVz0X89MXsLxjeWgsFZhP5ZrhJpPw6D7PC2lxaLRHi
+RRgqZRPv9iGnooBibuSSVE7lxDpQwYQvu3Rh80plmd6FW733SWNWk8o2OJdDKOJi
+Uerpx2JtqJfYDfwQJS4TCvaLk655qfh9xzw81MO0uLKhQGA920/UPpgR+eD1Khop
+qUEOHQYtCQXw2DzL+/o99XsHeA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_ofb.der b/samples/rsa/pkcs8v2_rsa_aes256_ofb.der
new file mode 100644
index 0000000..c08d5b7
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_aes256_ofb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_aes256_ofb.pem b/samples/rsa/pkcs8v2_rsa_aes256_ofb.pem
new file mode 100644
index 0000000..ad67413
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_aes256_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFETBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIk9vmCD/4P6YCAggA
+MB0GCWCGSAFlAwQBKwQQDFaVAHk33vRfvl1jtNDfIASCBMJIyQ9pJV2GgNzenpFl
+6g+yCbi8b5siIo1qAKHX1sV0nkOVCPwgXdEfXvZISYitOx0AtnjTdXqRHG7dhQhV
+O1GRknfn/frhW2RQ6Q4X1zJ4a1U4oqVesrFHroWHdVh6BHbASCRZPnVEi2j3gC/f
+Aad5QtJx/HRSE2BH7fK5lxb4+xVQzhCpHlPcSE4VKL31V8qsrFav2pPPHroNZu3e
+qVVZPDgcd11rHBilCJK+F1iCuzc/JWU8qrleTXdkJQkmBOvYBkswbUnAV+sk/Lnr
+u0uBtgmdRfFauaTOgtMel8GjliMj73ZJbAX3eZE24sF67q8irdjZZ7vKLJWkmM/c
+dIu8rQ23rl7OvS8jASSojxl59wXdF4QmfkC87NGssARyY+Ii0xf7q9uQNJxPFsBg
+gtpC8xNnbB2A64Xs3KMYEJIt5w/6UeYccoffhchlc5GDqHldd0NGVw6cUMlzTo2i
+RSvllRvWXBQ4ffu+ApBVoWlhcHVUm+CzdiLlLeSh5IPO2NRpQ/pLKLfHTQAli2Mk
+eJuff+mRClcZTTMP8/zbCH+wugb16Q2DEVcwn3rXF7tcV3NaO+EBfcoQgmyR193S
+MAz9MMaWBCipGNC0ElTayESUgDXF87L43VzL6XM26MJrhVrTBkbOKhGcXjrvrIzu
+BkohTfPOnIgFR605Mbld03a/vtruP//3A4K9e7oB6xNs0jkV5LzoqP083mB2JTAg
+zhy7Qck6LinI9ewUNd/KrrU4hrAEpzRJ6O1fyyIRppDnL3ID5BdHSdcwbyLlUDaj
+dhKXCkLzWxnbpKHnsiH0DTcoabC7jx5s02eOZ56L5cEleGumhYDhCD70AUo6f9Vq
+mfv5TWIJGwQLO/YGtxQiDyfRq3wk25IBM2UID8aS1+rifukaaAficP8KmrQWKPyP
+ecC+Bf5035gYakUPhNgh0FNjFp8MQVTtYrWz92VQuPHnY2aBoSVNIybZa3/vf0cy
+V9jgsT50R6i0lN3mHu7vtYOZ6JjaWX7rcASLf8JFXJad0g9IQ2RTjYn+TG+cdFix
+i+19O87Vq8AUCajpCZ6nPr7NlyS/QyvdK3YEL3KbLNBx6AjMF2Z5qCLfsTXogKtl
+73JMmD5DzIsg6cmnkojKo3pruVOwVyZ663Ao3h/FZ7S0nQ2m4rM/4OZoNpPpmtJi
++8stPTy1Je0CNhQf64/jwA7ghVp2lSC67EkTSJ4Ds7B04aKnIoP44DqpY4gHxdJ/
+OFXLiecjZGAKOQlDJfHmcFiN01g3FRiB+DsdAACdWnaTqAlBwpJdw2op0IwCF9Yu
+65Y6lVCQZbp/EYwNNv0xPFInOknO84qmNI6ilNgVaBemfG4H5+SkruHrT9t9GvOu
+rqyoDMN03/LGaDehbLJrDvw4OK5blj+36yQA5QIY9hnWOw3jZpVhTw8w4+EJqvQL
+tKUkchaNyJT/6K7MxqH3yG1hiXviloLF5p/3hb3rrt+yYRbNrotl3GtP2AL3AFeN
+/q1M1ZGtgemtzrT+bX5JJDUr+6VdMgMoLYR2iPyo4OM8V5Cx3PdFpMCJQp1rf5DM
+1GhM8xspnLbukm+ING/4+RdQWZNrpbQB8p9G2+it4IHrlO5aSXmQGh/bTQ3Zxh6/
+u00h5/0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_blowfish_cbc.der b/samples/rsa/pkcs8v2_rsa_blowfish_cbc.der
new file mode 100644
index 0000000..9d3222e
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_blowfish_cbc.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_blowfish_cbc.pem b/samples/rsa/pkcs8v2_rsa_blowfish_cbc.pem
new file mode 100644
index 0000000..f22fd48
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_blowfish_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDzBBBgkqhkiG9w0BBQ0wNDAbBgkqhkiG9w0BBQwwDgQI+SHyL0TmEd4CAggA
+MBUGCSsGAQQBl1UBAgQIe5OfjWHHpAMEggTIr/Ma8RAEsq65a1K/AooVkDgwtqRD
+Q6A5Wx5LOvXRvQ4RLd11ham+GCWxHKWHeMTnLLrW2gQyDdEvMPtM0TRoGmm31npu
+soEDFLIruE5XUmpzsKZkqztVhNl0pamzsqD6g7vSMlckFORsRInuWq3THVIDoHVi
+m54JE5RCa/tZMVjmvvYOt1KHJhAqUeyb+CQYZsO6c+mjNBZrvdNFDz4bgutVKreL
+FQMYJWr4sClAqnvHCvra2SV/mwIBZ1lYj920Qq885+HoSSQfgLOwar5XYCyEb7z1
+Q+NYMjaDqhEIWvlXsXu7B2YIYoSC6vse4bfXvi93fJtb1CXVjWnDKC8xJs9pqVCx
+t1P9JsztRHZ5g1daHwu6WQwD/7YRubi0y9pYjHB6H4M7KSWX3CEz/hDccUWoZHKH
+D/R6cNe12RqVqRr0a5tteUCvFwbXCcwKbTG8n5zd3MS+2FF29S8jvhqNXJOPuykS
+Sxq1wi73puQWCXAmw5aYy8RBlv9y3TlcaTDO37AkDdhJkWQLWbNy5MzLmh7dhNCQ
+R2Qy4wz9Mw/1GZYhOYM0kSovMSHcN1jIvw94YPAfflmL+k6VtI2C1iyD4BG8li1h
+ChCqL02fiLYjBsZquOdE5Fkg6tT6IucB0x35Qfjm8lTwcbVnjVRHnaQyPIMZeN9N
+UdZqzyb7nf0zI3rbrCHFMPsGX5741VGt2Mz9t/rQEXjezgkEuxn54Z/Q39Rm0vmX
+LfcKznYCVdMkomC0tIaYHBjVQWZerBRIHPGUhozdKwwASYco+FuJNNc9SZZnJ5AU
+ux2yD3NTec6c/fgseJXi3UT/qDDmUQxX9hjwnUw8CPHUjXWGTmJ/ihfQVGo1ypwg
+oRZWtF0AnxB7ZfdtnW3yq5/xCFzsIrKyFy4s/kdsylC8eGw4snGA19PN23eEyTZD
+bSuW5KLjgScbR+ro+e3Y1F3OTI6+VF2oMLY31XVyt8S1N2Zz1lpoN0JfKaWTrTTJ
+9Ic0oe2qtgqC42g11WHQizYAe83cZYNZgzU9mRa1FIqQD4kMQh+Vv9Cca6FpdPUv
+D4GS7/fA5Ez5jFV7VghOCFfK2+1Q95b+2RnQEpmHk60+U7tZG4dACXLL7i1hbJH6
+YuokBuw0Wjm5dicOSG2DptwzyqFfy7C2DYgB3Gi34fSNFxKis7CeKQLNMqppmBof
+q379AD8hY9Bc8gUWAwMONs9AreDiRCGyR+IokQPTgKRuVzR7ISoxWkKvfW5XIdNf
+Pd5kGLhX0HfGhikQCVP2XQMkOqsJw4ShV+FAcMfzaq54/PzXoemkRCOMsCzsDUde
+C6XGF1wviq52P+DnAr1tDmYGOP+jP+O0shzyXF/res1CZ0PjiLIyUb1JM8m5eMRH
+dEwzX/btO/A/OwNwy5FzS7VdFwaGUjFBXK3F/xyu8jl6ov02/ooddkpqNm5Cxko2
+ZlJG4LXdDbO1y3rbdwSgukYS2SeUmGqLpONlGi6u8kGRrgetcCAzkyT+XQkV3ZWg
+TFfGxr3q3NV0C35hIKBxLXr/+ZZHDP4Yx6/Ok6xYnUyJ7RoM6QE7Ppyo0hFPv0Q3
+VknhyfXk/85k81dxWLWV3DiXZbW/9gGa8TGRuZxliqTr1YjTRGiUwn+fCVx7YLyw
+PiNp
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_des1_cbc.der b/samples/rsa/pkcs8v2_rsa_des1_cbc.der
new file mode 100644
index 0000000..497e226
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_des1_cbc.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_des1_cbc.pem b/samples/rsa/pkcs8v2_rsa_des1_cbc.pem
new file mode 100644
index 0000000..e8c430c
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_des1_cbc.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFCzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIGBflqeZFz8sCAggA
+MBEGBSsOAwIHBAgLbTq8mvQ7QASCBMhUPEBJHO0Uvu4bW2bfb0NIvczMuPbFQDQC
+GnmzPGsa6vLcE+z61rBmPLOT45ZWcbTf867wh0e0KKFERkDh70lgenwYACRcefoE
+ktuvdjRBpMiSAqr+ucD3ZwyIVp1+I5xUJqLhqxV1Wd5pkwFaZsqxUCRd6DQmZvH4
+kVw2ulaE1HfT0XTPGO/ewBQ72wZ/XiegYsP7yp4dNIfmwMk03A+V0K8PjQTY6Sui
+IHeoe9YT0b2J3ocsf38pHAiTmsgnl0ZtedcjlOYJ8yVxXu6h8FO+Xu0MXYGN387J
+m4OUqLFudtWt8oVTVQuevNO+EzP061gsZnTEUJNvQNwLajdQnmER5ht28snby3tM
+f4pzwu6asM5RHDD2FBSp5sBD5G/ev0hM6R5MkTBAEcz0CB/TYSMKq1IfWCqHkY1z
+bvd7Bm19vwoyszXBGEBmhaVC34kYXo3IoTw3ezvXPgSaNk6IUvFavZRvAuJLleWs
+cpN13G7pbi6WeCYQzml3L2hLP62DP+VLwkYyxUW3CvwLhVP1h2w12tb+cKC+4uih
+4Of7cjt0R99vNvyTuPJ4HDjcn22KT+NJwPDNviLcBrNs1XxCXFa211nZWDGDC2cf
+6lCd1JVQczewMfQuFX8lUMuZOfLoAN+wq+ZWLIEtIMC+4bciZWYxzKFijOWKqnd8
+JhnOTKZ3Ua1txrAYE4Z0jLYI4xXImnGoW42h882aEiWSzsGARD065zXiQr//b5ot
+TtFXfJ3IiJMMTyss93mirPPzcua8uoGvwvjw3GoxLbNIttX0hmR1NBGyM3MUnghy
+7lrQssx2FcENuI/zAq/6l3ZT2jGtixch+Eu8mrCBTthWRBap8KIcO428c38C/IJ3
+bdWmWJw0r401gqbZS2ZoSi0ia+RFM/DByrQl1Cww8Z81v6S4tedxMbmSiI5/vpXt
+TcM4xQctZr/shYU9CDpxLUznmaRXbnFb77S7ykrJdPgnk+Oq5GYIhrcrxXXwF7+S
+wg+72F5MVkFhqhzsZ8VGbgpgSw+BFDJd9wHiLM87ywQW4eHYqJfQtO1lPfzAkXfz
+oPDyGX/Q6Nisy7dVErZ4dTXlUKxXEXAfvZABA08/L+3w+p3HEWm1HJFpZitEKHas
+dheCNwnwmmyzItSjXBE2kBg9ZtH6Zx9mQpU2ra75dl+X2SvV8096lh7Xt0uHgjgq
+vtYl2Bc9yBnxcwf6ppI8+VzBTxT/Q3BBBTL5e8RuYlSB+9BTlsp/bgP2prMFL+Lr
+DJUisjPHJn3gPeG09lcWnAzTdw07/JN83WV3HHRjJ/ot8TdoVix/qlrtK7IPkTH3
+hyLhPA4V49aOz7f42Jg3Xb0/C3WUEaP3aJ6UEoCVd0856RN9CTOlG95SPH+IoDLP
+33oFlrRMlqQ0K8Y/j40h/3VbBxaHeWCNiZr3sN5ybxNkT8TaXOr2kWfePsYdGf7c
+Pbz3IEwUeOD3z/GzDdiYvOfEo4quECEEQj9dWedOVVxD2wtc5jbaaB+HEaxlPNg5
+5Sqd3F7IPtpoBGl9OOgigBJIP6JQWctjYJYjLGnVn4GpXt8pWclmkQ+SsCSCeYnX
+Hax2rVBqD3yMRpVw225Dzxb84R1hleqx/N6VJpjmk2agYCTwXKsMyd2tMROOJxo=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_des1_cfb.der b/samples/rsa/pkcs8v2_rsa_des1_cfb.der
new file mode 100644
index 0000000..3c9c35f
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_des1_cfb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_des1_cfb.pem b/samples/rsa/pkcs8v2_rsa_des1_cfb.pem
new file mode 100644
index 0000000..5c96b17
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_des1_cfb.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFBTA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIyrtLg/hL/L8CAggA
+MBEGBSsOAwIJBAitq97jfB2j+wSCBMLwmaT2ht4i5Kj6RAKRBOJJsF8sRCeDO/mO
+Q07e8OwmjgyAl9a2ZrBM6WLsxi9jm85+OOf4yhyqDa1nCcXKoGt1mb/SiAkZdYd9
+7tQrxF94+AZUJ0g/z8pnBKpx/1/99P0du8wxBDBoQhqfY/a/jXmmZsfvO1TeJgEb
+fnwiTHBk+8iUQcc257OaxUyYDbKBbzckAsleiep8Lco+8Mpl7MaPAc3phQDwHfVL
+9tNmcS97m6g+n5KkV7UR6f2ukxRAczmh6x7wjf2rqEI5KwSm2IPkCxPDGQKmeCNg
+F7ezrokU0lIx+DJQtxW02KCWgHLI4I55TdzhSyAwCsCFfl9zDalW64oqFKgJYG2b
+ZACYYGRIENsh/+qfZ5nJt+xhynQxX7eZZ8bcwXRDdPtPpCMmDq2K/cPVkSUcFPjP
+41a6yZk/dd+NQZ0pC8nPTbpCFmbugLS7Z06GmD+aRdDMxTLP9QY1BMu51+vlxsTs
+WhDkrH5BJb9z89FzcXuzR/qp4zQ6oEn49P/IhztUV2V75GvzCiw9ip+5+Sh8v5Q2
+GGyFgFx6qSE6h7Z6iu3BGeGsoFhbLLwgcM9YXdP3MuNdSJsZbzz/iRIHeHif2duQ
+vgEJpielRb80Anq18SsORqamYQCWCLLTyWgSluJfYxt6eGCuPGEJnK8njwjYmOU/
+hukosJDYE25jrSHNC7fySIFJIzxbu7ofXnOB8PaguS/d7CbLbhyKHLNWnsKDrFtV
+4sGbgcLp4CNDBhGruPUihtf3yNwZ/Kqknsy1wvJxKwateXtlqQpcCGoUTn034GAP
+BIA8GJOMiHUMjaSUrq1DxdUki8HAJRfM+CqERaVYNIDsH2AL2chVXkPWHlC/x8E+
+qKMHczBYjDhURrjWj1iGHN8aMw4nEKqT2Qs7J9Mbgz9Ibdycc4uXeSgOuOmOdgZt
+K135ThyHCUTUCjYxwiz+3+cG6bju1A/7dbS3o2W2bg5ESUlIXXf+shOCTHWVnW2N
+JGGYMA8u9Rib9GCchX4D+LqoocZFxO0g563/ADAU+Hg5ZS25lQmrLKuBKUNiyrf6
+W/WzyXH+8pNlWqKCOb692G1NRrBKpZwRv0NDo46dgYWwmSErahMC3dnmm+H19auu
+L9B6gsE+hQjv5NCpUrqNT4O9yVlocOLzL3jINGc1EaB/zCsb19Ksk9XQB0O0EoUS
+T4VFLoeGCxJ9/DrDqtuWiYwfJinJk/kED9zavFe5ETkmjglaw+WgUec6QORQY36/
+cGz5blwsiqf2TSksgLREdGBFQ2ATJh5cKmCp6yp/EEyiuhNyY0LXbhaG0UP0FJY+
+LJ2ihIzcnusp+QfclKOKEOajrI1BjAyFJkMQS0jcPgpQ3SAI8fTqNxpiQ5SuoceF
+FV7MCNnVtlc8j2rSLj0tXXes2Y0N5YfnQkkPuZSJpk+6Unv2RwlXUpda3YpIMkxw
+9rDF7j67tIlnogd4cDma7JbEdgPjvqDNKm1VEXgNhRZ167VyDGP8nTly8O+UGCqd
+tsAail/REaO3m2yNEdE0+7GPnW2v/znHcvqVWyq0R4NgyzugKb4Dxtzh2SWPosTt
+CbcdJKNKWrsNOX1pKp8+NuYS0JScGrUQQaAZmFJ7aAl+3mbYvZ5AGt8=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_des1_ecb.der b/samples/rsa/pkcs8v2_rsa_des1_ecb.der
new file mode 100644
index 0000000..112a8e3
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_des1_ecb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_des1_ecb.pem b/samples/rsa/pkcs8v2_rsa_des1_ecb.pem
new file mode 100644
index 0000000..acb9765
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_des1_ecb.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFCzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIP260cva5DI4CAggA
+MBEGBSsOAwIGBAgAAAAAAAAAAASCBMhzhJsbVbG5HLxDzjiJunh1991nhCQOicEZ
+BHDgTKSGVu9upjcDVnD/wSdG8reMAM9NU/EoHH5dO5nzS9fHq5dqfIAzsXic46UK
+Puh65gxMFpGTfphkdoTjZRQ5mlqzrxYZsdaI0iIxgzshzTVDP5wobEoap/yskoip
+0845BDvdH3vQ8WeyGBIkCIimlDNBgCGwzsruQOREhMOpxiP3KC9qKi+pkcNgKcsL
+t/oU8B7i0pPphi/bTWJeF4TghS7yozwd910/KufBgpAm0BR17NIrldazXscrzykw
+epw3HEejdTI7QZHZ7NARz0mXW2r5+XAhNSLLYwYnn1HimrZYNAb6rTDuYAv5i3Wi
+itmMdNbzeGxSTTvaPPwVQMOSMtyJu0phDt0n4op1C/eK1m0AUfqX86HmLiB1GYbS
+PbZHZ5kj3tfcenTNzCnl7zAwc/BeRNe4ifTPc/glYlUJmvq3vPl9H02uuXxJVNDa
+Yq+B1d5DH8f/MbUXsbpzWDGSWVRauMnGp4ROGcYa7fwl10zgt9LPV9CX9OasO+IF
+/jQN9vjmYNIrjzPcHpeVmJzSw6vbaiJIViyfhXq58JVpJ+tqhkKN/QOxpmDgmDJU
+pPfg/eXpI5miDoHA0EoyTtIsN22fI5ux1WSO0+PezechJ+TFs1aLwfnniWFYhAJ9
+gxci9SFlnBUqUC1nRrmSLzr7R2KXWNNXi2ZSbuk4C8tVbBE5ibyFcpMwqIDBcBfD
+WMw//qS7R27EUcKdX/jHW6ZdIQGJhlXRF3/KovIRd6g8wqjCZ7hPZkJs7SoA+DbX
+lz3KxMTZi1SoD/YQxEqMWEuSffLsRFgNSW6+DyTxi0hBAdwRxJE/13ULZbkr+fd2
+d77i63g3Go4RpydTkIwTnfvg337bTFKASqYpV498ZE9gaGe1epk0TplAE/C0qcZn
+m3NkUIo8CPl4zid+Tn+2gqrRo4Byjl9f5+bqg7CdPB/dRu6bAksvjAgA1c+LM3Y2
+cOBhwe8GzQdNv9xOKufHq4JwwHrkn+tgUZRPgf4qof26jtRQKiPMRPGz7UM6ZOIk
+/b0BZUtBnYTowFOfOCqspkOQoKN3UCvBFjQNhyVqYIGsMxbBC5wABzHJY66pxX2u
+Ortb6MvTHEij3kyrTfrDaUFdoGxEiBT1kP+kbG1A3+p31JMOs3PAaosrEBTqWfdN
+VKI9shrmNIOJz7uxU8eajVi80DDRwovMp37kOCri8Ul0/yfqF1jWXUaDv5MQI5Ic
+PlUDd8LaxGtc8uJNXC+g7P4fRhU97EjMaaFRIBWIRlqbv1ct2+eFApY3RYm6BrIh
+u4cjV7x/9d6rAxBiJdtSq9UNSV6t2OIt86rwKS398HudbBbH4zIhGIbbzjn9GzSS
+6qEbyPYzO55Feo6KZRsQBvitgmQ7wpNotI7s7uKV5yHMdVCnIpMTHB1u1xIA2uiJ
+jbg8+F0EIggQoiXTTLGjj8M5ZXZ3CnqT34U7cMDeg257F40Tl9CZ/eQXyXmqvV4L
+GdlxKIOyYKcsMeJ0FlcxFJ2pTJRFtLvetPNaN5JHaOTRC8+zoqL964ubxikiH+LZ
+EfpWDUGkouqCGoc/6fNjtabJjwmBK2MG3fOhTpNH/4n2AUUulm4SPtBkp4uZj+8=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_des1_ofb.der b/samples/rsa/pkcs8v2_rsa_des1_ofb.der
new file mode 100644
index 0000000..8cb2506
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_des1_ofb.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_des1_ofb.pem b/samples/rsa/pkcs8v2_rsa_des1_ofb.pem
new file mode 100644
index 0000000..6a91ef1
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_des1_ofb.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFBTA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIbdCq00ZNZVcCAggA
+MBEGBSsOAwIIBAhCvoMFuBlNXwSCBMIvzvagl88RWujl4nG2RsaXP1eyr28SnH0j
+VEoKRp3XUKxfchwBmJFmgOZlDX8RRSb0Sr13RPGXij3RJTvyretkTkhmxGuISEtp
+XdTE0AMccTlJhdchhN8wCR2wPpIkf1zKHEwxwYzcw7/kd30MhbZ9FF7kZv9u85GM
+nBgyg9qApy7N9OcdeE0b3kltwnFBv4zlD/6YWZJSE4HdnLsyXqxZDNH6jGEXbJOP
+hQxvCB7v8LWT+97DW0wZCkq+IAmNUsdOWbz1PXUNbhDLimqfKv40jKn2vcr9PIAe
+3hVIAfYAUNBaR+AWl29DxlN5IwuEZI5Wzy5KImGY3UeIrncx2QPyE9C0oT5ec+tm
+XeHbM5qfDXZvIs7pv4GESGQxSdey8fh83tGiLg6jMPSGT4X9qh2AEM58dAGDudtG
+DCznUP90indqcSdFcij+UEafV46g6JfYPUXGWN/loaALD5aCednCddJPwUflw9lc
+CYFCFBWxkr/P+0MVcYuNKYIe7wiKulzG48ltQGvXXU7Q7Cqb1C7rIOHTP1ie45ll
+XJUjcAq049rfgwDtiICQYLvhfQri5VDfq3mEpRk3+nJV0OsS+NIWPVEzuwq4LGNi
+sn45h7rGlcix1NpNL273ZYgL6eO25XBz1UJ3Y04lV1KP1BEXq+vzKP6SuuJcU9rj
+Ny6T4krH5UT5T9et52TaHqy0P7wTYma0UeIbasdbQI/pgT3P53VI/pyHfumK1iTO
+GX8BLPWvMx6Ldfe4fA7eAogIWub0sk/eD5lKi55ZNLbh2WO7tNztscWxhbwET0HI
++sqoMHZDxMUOSZHkS7Wo2UpDx4Qxt3atSq1XPIi8ZGV5+MsIfR0P38V+1gzRA3GG
+8BSdbDaeMKBjIUdXvs3RwfkrCxIhbf0yZTqtd+JNoIDjQdCR6x5lxTc6V25E3qBN
+eAd5J+XsDkwfjZ9ASVvUVU8J/Y3ogd3JIjgwWFmQg9GT7lkb+JM531rCOiR9FdOj
+bMKYdoYN8sbPQjHJL4Dv1A21o9uuojZifx4sQH1CCw/NLWeqjwk6tFu7zBhK/1TQ
+/5ZLgMH2ZGk7B3LIoeDeh2pi746NJRE4rpmqLKrDdjHCfMEhdfa33Ql6ARZgq41x
+NEORrnB5eHpAJF94PErH/gwyk4TdTARAC9LcYV45I1qqqcfp5CZ7EzMVe2qwSJFP
+qfQsmBsKoFTx9ugwArl/jqeUl6bhZx1X/t5maHZGQPTjXr80OMsZvXLk7cQGg4sg
+6YmNeTEIpFsF/rLro3ipXjqThT08F+PgHcO60GtzomtkUI3nZfIosfrvGZ8iz9t4
+850/o/hmo0Vlk2m2+2fW7VSHmJTocus3R2B9OqHZHOpQpHMaUvL3zMdxaaWmD0RC
+L7AppW0y2fx3d2lHwC+rUpusJVl1nId/mrUI1YytQQs/Fy6kVx2WlQdb6BnGev/1
+IURmYDkwlie1oeLipL6e32DOQkpG9GWWW866MMuZpKsaL0q1v0N7SFIxm8Qv6lYv
+YQ8sKh83Kzoe0VN0g4mY5fAtmxJasFnT4f/dn1Aj2hsiQH0UiSJwEpAXSX/YlYSH
+R1zx2oD+uT+EYVc+OmBBw01bf2wmKx+e3zLjR/Q7zxckwOY/fgB3GQU=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.der b/samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.der
new file mode 100644
index 0000000..5d3f1db
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.pem b/samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.pem
new file mode 100644
index 0000000..05553fd
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_des2_ecb_SEEMS_WRONG.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFCzA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQInUCIat7eaGcCAggA
+MBEGBSsOAwIRBAgAAAAAAAAAAASCBMiKwGB+zBHFfHfmqr6jxf8CWeEuvoR3G6bs
+6BC5Rr+2yFtkt4/duBBgldL0oEBohVSd0NeoqCGAbVKjmaY7XyDeejuMsGBJ9fIc
+ki/fWc6H/eqOb1C8kbbb+mVivdrx6tpFxQ+8tKNW+A3rOWwjIrNPTWmsnU2/jRmq
+q/CwXeEZFAUBf1/pbxSe3FmLvIbukHJGIAuoG1CZoa1l1jr9Hukt+M3grDozOFlV
+QjRbvwLyT5k33R9S9PbPogeQiLuMFVXfvmt3u7tSsEnwlS7JZqXKGvNq7WEWH3FP
+BdyI1ZC/x1YqUsC9+ia9LObwseqYkWoETCWfPAwHyzYQ8VNBEWTvZuO7kIIoUPkM
+m0+BBljpc5IdLE/KIOhCI5IBn0tR8Qjvlmpr3oiEd6CsbNXCcW36wMnHKtnt4t2C
+yyEngoSuS1VZTFWr9ZhOOoiKzdQVTw7/MV1zsd4k9uX6B1I6wySlJ11LOi/Rnnqu
+ccqJTu5+IJAVf5AHCczbtUDqvzwckoTt5rDHb74QR8hcC0UW4cXXSgaGqeoJ9vie
+wH/8Z6pnZmJv1zAAHEqiUPJOOCYRE689kCTUmwI6x9nXeqk0oFFIP0AcVoPjagJc
+mhnoECLM++B5b9aLG5pUtotA5ig+FcsR4bdiNv0m/imP7Ip15WWQc/PT44VXAQQq
+os/Qm4IOEbe0N/DFgldoMXb4gEodumgsUg/3SiXIOW4CAZOcVT1ySfzUhGCB32l5
+Nsi7Gqet/rHeYeHAXGjS88QE0nKU/RsAi4YHHmvrTyirA5T5yEtL9ELPZwm7z/9j
+5F/odiIPh6E/d4vHBNQLFK56rKi9MEaNxvCaR+h8ThH+n44CaFW6A4nERR5ehsaY
+RAk4dtJGTR+b0T/DpbhxufqIc4f5hup9do+VIZwGLOqOGzACG23N2Ts7biiwH14E
+ZHGv5/bCw/onis8VIhyH0AUeYGswcvhs7XeBkWLNAfov4Uge0VT4age8jnM27Pv3
+9WRrbVi5YhYl9blNA1NAi73ABe9N1x29hWLRBMMgrqL8+KVxsdraQipBqshIO+SU
+i2rsRF9/vx8pm79qfInIGKxxl60ZSqebmNsTnCElFUUS/dyOwCZ3yGZ76Fsb8eXI
+6N+YCwXaMcJ5lYewTIdIrBZ2i6zF+gwKEESdIU8HdgsaUbu4aAIwGC2ChhO8gcpd
+xoKDZ9HXR1+5IH8/c0APIfKPbJkafzcpFpAEsYHGEbSYrThuqqxrzMSababkQSU3
+GIt1aYORWmd9bUHStqgs8py8kf8uPpyaudE9Iyzj77cCWoEmOW0GZURaKNBASV7U
+6HxNO1n2w/Bpe9zk/+eIpIWDYo7dgSC9fW2nZ/o/ULsyLhEUpmPTa8UAcIgn2rTP
+CSVnxBq06pkM4JgX25dmgJbOGkJ5Tian+X4D5BBTCDtrcJL5saXcWKnB15ScGhKM
+8++3TfRMkl54Xlc3ni9JZ3gXwg4hs2lsdj0FKvhUzvnLUhnbuBpR803RlgcyZsHd
+o27xL0Xyi7ZFbJlHEwZdrrqdBTe+TLcswpghjl6hsdE3ol65HiaCYkdkVzMW24RX
+dvaDFvVjCny6gQoJk7oXxfBVpRMAgIic4w3jBPP1mokDbXKkDqGcrRqi9VQantg=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_des3.der b/samples/rsa/pkcs8v2_rsa_des3.der
new file mode 100644
index 0000000..7736282
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_des3.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_des3.pem b/samples/rsa/pkcs8v2_rsa_des3.pem
new file mode 100644
index 0000000..97921d7
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_des3.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIqpcsbmHTx+gCAggA
+MBQGCCqGSIb3DQMHBAiEYtVFOafp9ASCBMhnk03sYcXPAU1eYthAr8vueotiNFFr
+xpbIbhB2cjC/bXd39GxyH/8X36KjVMuBJxFknY630SOBsdTn/H7lN/G8c+fEYTcq
+porajF/pxr7asdFl94xjnx/DGaQmUJooqqUp8p80On1Otj7xEZtTivlEISY5Pr6y
+6ou+fKIFKK5QzDzD9C+vLzYJMqhk4YamjxvDOwzYUoDFl+enMHXcuZYpA1yEvqze
+5lFk+9AxdTbHgOsPECqS3bkq64VGanrfFtqywqLLLhsakcnByjddcHdsFFvhu/dH
+raFdV3vsHppedqxTHbfFpvVl2+9XTpeBzwvb9XcJ2WUi4JUMtcR1gZwOo8S6q8LL
+UWzTbGjsZVG3ew4FZ5avAjUCGgiUR47LFleSJ34eWrllUptHzfVTpV5f787gfN1g
+BRhAJ1YJTWqcalIhd9YEKFxI3sjfWAOLdUW4at4z4yuRZh/uUck4V3ken8/M4JCG
+/Vy7B9Juf9uHRKFWtl3hYDY32UJoQt0cH7V76y/rjpbhvhVtKaAbcK4ccZ+4JuDb
+9qbs81Joe8jW4OZtYL/L+g4WboW/FSGlJXxJIP674lnglXXB5C8HT/I/7CzrEEgv
+wcKKAwZ25+aR7pCYqWdDLUaENQQ/Z1mARGDw9JGszonXJMdMWnQN89DXsmkp6qe/
+YkmZ3Sm4rrvz9LKc7mW+v+d+WnPTeJ4FBHmnUhGkuZroDl6SrCPjm3qFqj3zvyyV
+8Lk8xNMm6AEN8IOs7qeUAb811bdpfUzLebZkuNXDMl8KCoyt+nNF8UN7vpCXU3/c
+PEJahN+XxmRftOR0KKBIKCMKgnR90JenNmSyW2BJbT9D++7ujYoDlL0gTfbYa34a
+P4H3ChnU0s5KMA2h48UBkDUlwCOn4L860h4sZIDfRkWcptB3HFipeKP0npGAfWfb
+sQhueC7Ue8XpZIq5QBDOa+Zle3l8KZdmC4+sZYTsDoYm6jKX+LPgUAvvwyCBEUS7
+0zVrBgXTwFDFuGt5LYROcngfRggekAMa7gWTPbwb0mQgCIvKaVxlu3FO5cNi4ExX
+tlUUJyNualG+8qsbihqhHQBPs6QYhQ95y4ZndDqMtoyPWLhcOMo/Z/CLMQNhpXRl
+okJndM7TjzFW05Fqy+cQwl8LTdGVZKUOGW/RwYMD2TPxXEp/XGEDlnREHVjppToT
++SlUlc7Dh31PCz5PoRSTvpJrsV2LZAUO9hoGoDYjfBqfUbrd5mFIii/52eJva7o1
+RcrsHEkLTvu4BOk3Ztp3Zi26atBraADZ2T6UqwrfzZZrD1gI4sORuKN4/jmqt0KQ
+H4FMJkKZgvJ0Rfjpt6ZqRj99wSnwNfDvr7641WTpB07Ati2LI3Tr6Fx7f2Phfkg1
+SbzEC+qt3bixORhzFp0PbcULwamSsNVODf/EQic56bKZjOFEC+DFw3LKpvvBG1Fj
+kGWbfZhSA2GZFUghvhFbFOsuwKh/GDoetFwKXWcM8DM0+aHSPwL61Y5FQ0Kn4DnB
+ci3lJnSctD0fN3ckDIcTU/Nnza/RMJn1jRwBZc2Ql7/lA98jCM8uKTMVJy76ABf9
+8lQrLGp6tSMD6jo31DMLVmKA9qed7Mk4QeZiDTm0/6d2GZ6hO8xwvzFRQ6Qy1ETG
+W5c=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_rc2_128.der b/samples/rsa/pkcs8v2_rsa_rc2_128.der
new file mode 100644
index 0000000..f7b19c9
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_rc2_128.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_rc2_128.pem b/samples/rsa/pkcs8v2_rsa_rc2_128.pem
new file mode 100644
index 0000000..d68b22b
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_rc2_128.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFFjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQI4aRQrNlj6ZECAggA
+AgEQMBkGCCqGSIb3DQMCMA0CAToECG8qyWz/E/DoBIIEyFBBZXtbGNaIuDvM/J1u
+l8gKw+zfurof6G7BSxefE8zuVFVhRXc7MnLQml97awOeEzvnGC7y61JELsZ7ROqa
+1JWjdfURTsxxE4DGyUe+jOu2A1YSsnADCWq2bmvAkbFbV9N3Z1LqIkJNPtfS9KJQ
+ukDscB51M3m0Y8PaQDrGFBdsRK/lAErOxdLkfRYQItqUnzawF1FuysiYlcQiCC0e
+JrwiN9B/wW4bvnhQXABlQeI02MsfMPX8GLrlRfoNojLKTMCL1d+WK6dKuIA0QVRq
+bXzAkqWe2VjIaOHXcbzk9OcLmJAHkGX0pwkYpgSDyD2yqXB4thhkvCc9hlRQObMn
+Qvj2k5wyc3FzExWRwflTDZqpW9dFGCzjyzvOzfyJ+MWgS4e4a76vPEa79CMTWZcn
+UgNuSK65g7wRLFm6Ko15jxKAEP9zEGV+mKNBMmkRvL4aWWwbJOK48GYar9RaqC8u
+qbMTeQB/nfk//2JdxDR5W51dCSk5z64v/1ZEiLz96Y8GV8cc7PwVVjotW/yJEQv1
+mhWBqeiGLRQdymhU8AKwiNxhw2m1b/CW+pjOUpB21A7P8q3j2h5EqhD1VXneB6pH
++RTvFOUzYWp4mz21Ul8qXzc0CLsDm+Lywiqv9hDKMtaCe3cNrR/PFNoFuRYO6fZ7
+OOK3R7DQ/Us8cMpUJBCuYmBBwQB81fDxiHJdvtq8BmToJ6EYh4KzyTg4SGC1CPlh
+KjWkzIf0w7eZZj+hP4tKsrkeFsJ3/QSQW53bH7sNxp7uiSEwFpi3Sa/n3ABbOLit
+HR+O3GSfQIQMeLdZ5kcG2ww1SFEpaYBryBJZPfF7xF4rl5fWkrLasAPgUpTxsZ52
+UdD6bZb/8Ij3ZkjNJIRaGzCMlfWbUYpM4xBZ4bSQL2OGDYxC37T8TU4s6PIwGpB2
+zux3razpSBMFM6cT6ROw0zTzQpbDNF3U/wjOoyZmqRNpyr9AfXlsnxjXYzevmBUU
+IHEXUjEwhoGrVAv0U67YFgxLay9bWU76q6StODcz4flrcgf6Z1SK1J9WnX1FMYGK
+5HK0krzesjdFSqsx7T4VNv1paf5ql8mvMrIMTT2envm2vwMVG6EkOhGLjVeF/wPA
+0URcR8Fw9Wh9enObpocFnkqKiQfpyTOLBRIcYdJ07s/ER3HmqcnOPO4am5EqHeUu
++3YPVrNuV9E+BMNGKcMFzda5MIJi0rbYlF59Bz5xy8+nxiUqN2SvJYIMh/6egBue
+MEq/6O6ex5ypPFMlXItmubd3cqW6WMMOGuAxj0ciFLzZTxOwGDqh4G8GvPTZ6OtL
+fq2mitjPkLOKHplJ+Mjzd6qQIXxv5S7utPvpVnJPimD3jdwfWFXI5sO8pIjTVgbJ
+ZzkDw8ilLa5dR4e72+KHSlygjy0w2cvDX8kDfZyiRE30gIGQiHH7l/0Sv1GtOxpd
+2tmDTdA3zaI7W/gukmsMrpfBbGgHVC/YKlRVnfWFEh+a/4LLhc5gywqxyZzC59Dc
+nDRVPwSIPwWsx74ViClmviq4j0QV+n94JaQ2exgVvddBjluR7+9F+6+BSbfrgCeT
+nTAowzDF15LOg+/wXaAnSerzIwB1s9xfYyssGuKd31Rc6FBH+iZTZorVGS+8UARa
+yLHeQoz3pbRtiA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_rc2_40.der b/samples/rsa/pkcs8v2_rsa_rc2_40.der
new file mode 100644
index 0000000..6ae9150
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_rc2_40.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_rc2_40.pem b/samples/rsa/pkcs8v2_rsa_rc2_40.pem
new file mode 100644
index 0000000..8a582f8
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_rc2_40.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFFzBJBgkqhkiG9w0BBQ0wPDAeBgkqhkiG9w0BBQwwEQQIEE4B6fCGV+ECAggA
+AgEFMBoGCCqGSIb3DQMCMA4CAgCgBAgEbKm9AhH8KgSCBMhfarJG3ur5WGGeeRIn
+M31j4IfUqpBGofJzVT0HPSX0qMUCvfIGA9YLdKZKdM3r8KfF5uSSe9vdQwOZwTtg
+AsCgJu76cC/iRCbAZX0gJcVE29KjLfXKl92Jumuysjmd+Le38Pc38/T+gwTeNyyg
+aW/ABB75yqxQUbrBv1kE389jNctQqDfga/oW2LQu05EAxup5aRD1B4KNP+7vCok+
++kzDGRMkZmjalhnvPZUytX0W7MWNigVsg86krQUSGWrb6xPYUmSsYG40RCpPJtie
+0hWTuSHecI7ZP3H3UtUw6jOYvOXzJAmImp5HhGpUNhIyMNi1xJRd5KoKKWLcsChC
+OkLkf7nxPVBFShhwq7jRoPKnv3r0qDutB29iDZmD1V13pQ08gNsEX9sNwgEWMVQZ
+RGQSE3Ff1LmXcpaC0TcxRmoAvEZFsNfmsIC8E+InNfY2QcgGytes8t5FzHdR4ZdG
+G+fWMwSKzC07XestYJq1ung2hG+j4VmH4+yD3KY1iNg8veWmYC45yCp/IU/nBwf+
+AIE0UtitgeWG7GIzVZNasnb2gc/FAOb/6QeSt2l3gS1pzgHXO6iUIOylGLM/eWAa
+/jIaDI//bBOIhEaNNI3xAa04Jk/Lo0slTIUiXJpv2qefWbO2LtHlTel0FQlRWH5k
+rYFohxXeQ0TnZqNsVPdresFbxqsvGvp57gGpAFkUPfdyzhDMwEArTB5QuvuHSq0W
+lYYhAVIMBa/HgI93YuEqsLEM5wp+7NapZGJDUn0y93qn2med4a5xRUeBOVPelJUj
+aexagd9OF5YvT4+ZU2fDA1qaDUtH9ECDqqpaSRQlN6RBnsWCkd/rxOx4aV7w7kep
+8Ie5NtO6ANPkIFFA6q/RuH73MeAnQzABmSHYLYzDe56eGLPwutKeJqx4mp/7lvCZ
+IZQf2qOl8+onLmscESKwzzDN0O4zL6vgNyG+h6quP17LLTBzWijR03JPcC1uhl0q
+Bt8QZYTaD7hEJYB1LNiTG4x4N24/fvch19BiGXnMRomHHgQ4V5Exe3OKsV2UfRYw
+ZbG6ncMUTiWAEhbvpPgVWmvjkZdcyK1EhhED0j6NcOLhDc/BJRLPoczNWY+JYiol
+LbML/dj5MXkNBNOAAF5F9SL72XN+25Ylkxc64axoaOC8HjKIJqd0Kw1LKJ/YPxWJ
+ZxKV7J3jBDqlaGdtnrcWOhkEUw5mLewlOiabDBzYq+2A0PjdC54wzql5dhJ/vJFL
+FM4BxF7y9t811D35A/A8tVsviE27zfz/Re6wKteSaoadWmU5xBFHSO/I6b15GKw/
+/qQg2EdFJ0zx4C/+ZOJJzLpMyZAdOVdV8ZKXx6i0QaiAspdpK+xyuLt0YQiqlmp5
+VCVlmxEQEyoIGM3ec1f4Wrvg0dmaaahyRwxwWpojbe6HqO+QDmfdjX6tNhCL62xO
+J/f2N2suY4PnQAr2o1fKH/n9Tx7OYJp7tXr29/oQRGFcFb1SC+8ucrHROB1rdoMm
+5VQZU7Pzx6ixp/eoRGF4o/sXPrJ2MHzQ7Pr0X4Tz/vYxtA3NITPn+ARZMNxkBnkn
+c0rRtxepYJeNDWAP1dvpWDn3PfMKGDKNLAp69T3QVaI8xIPzx5xgQRT+HMtfqGjP
+km5ELjRjyzzarVI=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa/pkcs8v2_rsa_rc2_64.der b/samples/rsa/pkcs8v2_rsa_rc2_64.der
new file mode 100644
index 0000000..14de077
Binary files /dev/null and b/samples/rsa/pkcs8v2_rsa_rc2_64.der differ
diff --git a/samples/rsa/pkcs8v2_rsa_rc2_64.pem b/samples/rsa/pkcs8v2_rsa_rc2_64.pem
new file mode 100644
index 0000000..5c43ce2
--- /dev/null
+++ b/samples/rsa/pkcs8v2_rsa_rc2_64.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFFjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIEK45YkGUmvECAggA
+AgEIMBkGCCqGSIb3DQMCMA0CAXgECPuUIT3jxRz3BIIEyNfj2MRyn+4lRb4k+M/h
+IAEefhbiYMZ3P2vRDX1zFe6zHqBpRxTD+vskLXG1YScwt6TQMpXxMqlgarwk9wXE
+L/RrpxJrXJ9X4UJoVM47Q/D0an8xkEF7L6YzFKgfngzqI36A8EqSO3MT4+UIHcCr
+LGoUev14l9FXhVar2sW2eeK/LSd2MgqbeMK8iLeWvSWRZYL95ji6PWnWO10Ggojp
+f2ttHty9FsvNigzE2qZutYG3zPL94i/Xz/v6qH278fCX0PHnGWCAsOqg2h648vhd
+tbUcBB+tC4dKiYVwcmprrzJVPEWQuXIPmWMZa+s0RgM7jqI0vkrkLHbgGxLxRvFM
+n4xxQRs+rNcw57sm/LeoNyosqbWEic8RqLV2sDp+e/A+Te/n7JwOuhYHhmeSVyds
+yF1V8k1ObAg4hsYyhwcZL+7X6af4miG3DVVPC8eR2UWOYLvML0LbvWegp/WyNwkh
+rOd+IXR0qWKGmmEpJQPrsTLH8x6ueNgtqKP1jQvRLVS91Y80nmnzHNyOx6z1pR9v
+GZ8dRAPUd+/fygLv8zpBUOt0yf6ZT0TKWg5C3wP81mfe311QkPm2+3AMF9v/QCYk
+hLvAgFFvuzIqzrIVXofBgzABFssUIeG1OmPdn13NFGFeW7QXIktt8hqt++dyBMV3
+ZkOZhVkK85c/sxPYOh+Q6N20xq22DZ/O5/UAVsBMY0NtUgUsJ7qjaSsy5gnhO5mu
+oEl9IgSOMnl+I+wLmgXn84nMmsjJBOX+VOBviArCEEPlY6Vf/vppFE6Fx4wlmNl2
+nuDf+Oe9drcw9JO97Axiu4JzLhTaGITWcuBQnIvmDi22P35DIqUvi20iif3el8eb
+AwtmNz4pyU8W7EiSn5kQPuP36PxnPSLuCvAZAcYrkxu6aCQIMpD4m/CH8UbCLHGZ
+0o2zX/eyYcLJLgNn+u41B0TFBDZ+Q4XovykjGdjl9vMP5i0tW8q5zAC2zdlusRQD
+s7nA9KNCOwOeZBpYrEOtZ0ALTudnKwNEfwr/h2oYdFv16H5RvefyEhn06nBZfxuT
+6xQO/+ayaGZLMcmwhfDkap/ubc8NNlolG8Hgy2QqRlooBM8cxq2KTQd1wgl6KLOR
+Ahj7ebU2+7Q3sqIvCwc7Y5SxclevRiAUbYuvxbKCAjW+iKml3G5rbTBuk4ocEVsM
+Kp6c+M1iCeyaKRja5y6QGYJpw/hB4K//rAvWmnLGYSsJEl2eKo33CvqwEAM70pg6
+o77K6Y6uMoJu5erR7siuybTGXa9tMGfhyQLQ4zQgsi0+YaAh//snDv8YtOOZHP5+
+wrVmfiVoMTj4eE3GeQsnQnYzkpIl4SGDnVRvxTFuMCgzJVLxWC9Yf/5U82bZUhjn
+MXwV16QDuHv9mYK33aDe5bjSwOTGSrLw9WisZLxokjcm/D6ippwADodlXEFb9mKo
+aOoqpeWJpOinMIyUGa89KH8gtdQ4YWvkiZdlugWFirE5/cTT9lR6KMTZxqILGgGC
+EI/jDj6p9pMY1FVUcU34CT//JxUdt7O9Fcy602RlfIxlB4jXMTOPAuwEWhrixk7s
+gwKnR09vcj+Jil0VPJ+Td5PPFnbCC+gKpFKyNIvHCMBKPaXV9hxRrZ9o5dZkRk2J
+iEMh5e/7Lh8dUg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/samples/rsa_result.html b/samples/rsa_result.html
new file mode 100644
index 0000000..f5ceb97
--- /dev/null
+++ b/samples/rsa_result.html
@@ -0,0 +1,38 @@
+<html>
+<head>
+<title>Not-Yet-Commons-SSL - Decrypting RSA Private Keys in Java</title>
+<style type="text/css">
+h1, h2, h3 { margin: 0; border: 0; padding: 0; font-size: 100%; }
+h1 { float: left; color: red; }
+b.n { font-family: arial; font-weight: bold; }
+span.hl { color: white; background-color: green; }
+div.nav { float: left; margin-left: 20px; font-weight: bold; }
+.nav a, .nav span { padding: 0 5px; }
+.nav a { color: blue; }
+.nav span.hl a { color: white; }
+li.top { margin-top: 10px; }
+ul.openssl { float: left; width: 100px; margin-top: 8px; }
+ul.pkcs8 { float: left; width: 200px; margin-top: 8px; }
+</style>
+</head>
+<body>
+<h1>not-yet-commons-ssl</h1>
+<div class="nav">
+<a href="../index.html">main</a> |
+<a href="../ssl.html">ssl</a> |
+<span class="hl"><a href="../pkcs8.html">pkcs8</a></span> |
+<a href="../pbe.html">pbe</a> |
+<a href="../rmi.html">rmi</a> |
+<a href="../utilities.html">utilities</a> |
+<a href="../source.html">source</a> |
+<a href="../javadocs/">javadocs</a> |
+<a href="../download.html">download</a>
+</div>
+<br clear="all"/>
+<hr/>
+<h2>Decrypting RSA Private Keys in Java</h2>
+<p>Don't forget to install your JVM's <a href="http://java.sun.com/javase/downloads/">Unlimited Strength Jurisdiction Policy Files</a>
+if you want the AES-192 and AES-256 tests to pass.</p>
+<!--#include virtual="rsa.html" -->
+</body>
+</html>
diff --git a/samples/x509/certificate.der b/samples/x509/certificate.der
new file mode 100644
index 0000000..8fc0b96
Binary files /dev/null and b/samples/x509/certificate.der differ
diff --git a/samples/x509/certificate.pem b/samples/x509/certificate.pem
new file mode 100644
index 0000000..0d710cd
--- /dev/null
+++ b/samples/x509/certificate.pem
@@ -0,0 +1,85 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:7f
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Nov  5 21:52:37 2006 GMT
+            Not After : Nov  5 21:52:37 2007 GMT
+        Subject: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_certificate/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+    Signature Algorithm: sha1WithRSAEncryption
+        70:2c:29:17:f6:55:3b:b0:f2:82:53:db:06:ac:01:8c:2c:40:
+        c2:59:30:58:78:af:17:d7:39:4b:87:f2:df:ed:cf:93:80:d5:
+        05:ca:81:13:84:bc:d6:87:15:01:7e:45:f8:27:d9:3e:46:0a:
+        a5:92:0d:ce:71:25:b4:40:6b:17:16:e7:fd:d4:30:8c:9f:df:
+        8a:f7:53:4f:91:e7:0d:ea:b7:06:03:f4:48:8b:6d:09:ea:cf:
+        58:99:55:89:58:05:dc:8a:25:05:55:8d:19:65:87:f3:be:32:
+        b5:98:42:01:63:80:9b:25:ab:50:88:4b:e1:6d:09:7f:6a:27:
+        7c:66:07:64:ac:a6:c1:d6:73:e6:05:30:4e:32:e9:7d:67:51:
+        60:20:14:5e:b7:3c:71:c7:02:85:aa:57:16:66:56:3a:33:ce:
+        85:ae:62:58:41:5c:66:88:ae:e6:3e:a7:7b:b2:e6:9c:7b:b9:
+        29:2e:fb:0c:de:c4:73:5c:40:cf:a9:27:81:f1:f0:5a:a2:a5:
+        71:0a:78:2c:77:1d:0c:88:fb:9e:49:8c:38:27:49:83:b5:14:
+        53:4f:df:74:0b:18:02:15:e6:f2:d2:67:a6:f4:4b:19:ec:23:
+        01:04:52:5b:43:8e:0d:8e:37:c6:a1:9a:21:f4:b5:ca:c6:21:
+        4f:31:8b:54
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIJAIz+EYMBU6Z/MA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTEwNTIxNTIzN1oXDTA3MTEwNTIxNTIzN1owgZ4x
+CzAJBgNVBAYTAkNBMQswCQYDVQQIEwJCQzESMBAGA1UEBxMJVmFuY291dmVyMRYw
+FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEZMBcG
+A1UEAxQQZGVtb19jZXJ0aWZpY2F0ZTElMCMGCSqGSIb3DQEJARYWanVsaXVzZGF2
+aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhj
+r5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2BlYho4O84
+X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRyzerA/Ztr
+lUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY07hNKXAb
+2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8BqnGd87x
+QU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiVJTxpTKqy
+m93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E
+HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFJ8Ud78/
+OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNSyoemDT4N
+MA0GCSqGSIb3DQEBBQUAA4IBAQBwLCkX9lU7sPKCU9sGrAGMLEDCWTBYeK8X1zlL
+h/Lf7c+TgNUFyoEThLzWhxUBfkX4J9k+Rgqlkg3OcSW0QGsXFuf91DCMn9+K91NP
+kecN6rcGA/RIi20J6s9YmVWJWAXciiUFVY0ZZYfzvjK1mEIBY4CbJatQiEvhbQl/
+aid8ZgdkrKbB1nPmBTBOMul9Z1FgIBRetzxxxwKFqlcWZlY6M86FrmJYQVxmiK7m
+Pqd7suace7kpLvsM3sRzXEDPqSeB8fBaoqVxCngsdx0MiPueSYw4J0mDtRRTT990
+CxgCFeby0mem9EsZ7CMBBFJbQ44NjjfGoZoh9LXKxiFPMYtU
+-----END CERTIFICATE-----
diff --git a/samples/x509/certificate_chain.pem b/samples/x509/certificate_chain.pem
new file mode 100644
index 0000000..cb52090
--- /dev/null
+++ b/samples/x509/certificate_chain.pem
@@ -0,0 +1,79 @@
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIJAIz+EYMBU6Z/MA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTEwNTIxNTIzN1oXDTA3MTEwNTIxNTIzN1owgZ4x
+CzAJBgNVBAYTAkNBMQswCQYDVQQIEwJCQzESMBAGA1UEBxMJVmFuY291dmVyMRYw
+FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEZMBcG
+A1UEAxQQZGVtb19jZXJ0aWZpY2F0ZTElMCMGCSqGSIb3DQEJARYWanVsaXVzZGF2
+aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhj
+r5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2BlYho4O84
+X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRyzerA/Ztr
+lUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY07hNKXAb
+2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8BqnGd87x
+QU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiVJTxpTKqy
+m93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E
+HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFJ8Ud78/
+OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNSyoemDT4N
+MA0GCSqGSIb3DQEBBQUAA4IBAQBwLCkX9lU7sPKCU9sGrAGMLEDCWTBYeK8X1zlL
+h/Lf7c+TgNUFyoEThLzWhxUBfkX4J9k+Rgqlkg3OcSW0QGsXFuf91DCMn9+K91NP
+kecN6rcGA/RIi20J6s9YmVWJWAXciiUFVY0ZZYfzvjK1mEIBY4CbJatQiEvhbQl/
+aid8ZgdkrKbB1nPmBTBOMul9Z1FgIBRetzxxxwKFqlcWZlY6M86FrmJYQVxmiK7m
+Pqd7suace7kpLvsM3sRzXEDPqSeB8fBaoqVxCngsdx0MiPueSYw4J0mDtRRTT990
+CxgCFeby0mem9EsZ7CMBBFJbQ44NjjfGoZoh9LXKxiFPMYtU
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEnDCCA4SgAwIBAgIJAJTNwZ6yNa5cMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS
+BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq
+hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjE0OTMx
+WhcNMDcxMTA1MjE0OTMxWjCBojELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRIw
+EAYDVQQHEwlWYW5jb3V2ZXIxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDASBgNV
+BAsUC2NvbW1vbnNfc3NsMR0wGwYDVQQDFBRkZW1vX2ludGVybWVkaWF0ZV9jYTEl
+MCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL0S4y3vUO0EM6lwqOEfK8fvrUprIbsikXaG
+XzejcZ+T3l2Dc7t8WtBfRf78i4JypMqJQSijrUicj3H6mOMIReKaXm6ls4hA5d8w
+Lhmgiqsz/kW+gA8SeWGWRN683BD/RbQmzOls6ynBvap9jZlthXWBrSIlPCQoBLXY
+KVaxGzbL4ezaq+XFMKMQSm2uKwVmHHQNbfmZlPsuendBVomb/ked53Ab9IH6dwwN
+qJH9WIrvIzIVEXWlpvQ5MCqozM7u1akU+G8cazr8theGPCaYkzoXnigWua4OjdpV
+9z5ZDknhfBzG1AjapdG07FIirwWWgIyZXqZSD96ikmLtwT29qnsCAwEAAaOB7jCB
+6zAdBgNVHQ4EFgQUe5raj5CZTlLSrNuzA1LKh6YNPg0wgbsGA1UdIwSBszCBsIAU
+rN8eFIvMiRFXXgDqKumS0/W2AhOhgYykgYkwgYYxCzAJBgNVBAYTAkNBMQswCQYD
+VQQIEwJCQzEWMBQGA1UEChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9u
+c19zc2wxFTATBgNVBAMUDGRlbW9fcm9vdF9jYTElMCMGCSqGSIb3DQEJARYWanVs
+aXVzZGF2aWVzQGdtYWlsLmNvbYIJAJTNwZ6yNa5bMAwGA1UdEwQFMAMBAf8wDQYJ
+KoZIhvcNAQEFBQADggEBAIB4KMZvHD20pdKajFtMBpL7X4W4soq6EeTtjml3NYa9
+Qc52bsQEGNccKY9afYSBIndaQvFdtmz6HdoN+B8TjYShw2KhyjtKimGLpWYoi1YF
+e4aHdmA/Gp5xk8pZzR18FmooxC9RqBux+NAM2iTFSLgDtGIIj4sg2rbn6Bb6ZlQT
+1rg6VucXCA1629lNfMeNcu7CBNmUKIdaxHR/YJQallE0KfGRiOIWPrPj/VNk0YA6
+XFg0ocjqXJ2/N0N9rWVshMUaXgOh7m4D/5zga5/nuxDU+PoToA6mQ4bV6eCYqZbh
+aa1kQYtR9B4ZiG6pB82qVc2dCqStOH2FAEWos2gAVkQ=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEgDCCA2igAwIBAgIJAJTNwZ6yNa5bMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS
+BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq
+hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjEzNjQz
+WhcNMjYxMTA1MjEzNjQzWjCBhjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYw
+FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMG
+A1UEAxQMZGVtb19yb290X2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNA
+Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+OnocmJ
+79UeO2hlCwK+Cle5uZWnU6uwJl+08z5cvebb5tT64WL9+psDbfgUH/Gm9JsuxKTg
+w1tZO/4duIgnaLNSx4HoqaTjwigd/hR3TsoGEPXTCkz1ikgTCOEDvl+iMid6aOrd
+mViE8HhscxKZ+h5FE7oHZyuT6gFoiaIXhFq+xK2w4ZwDz9L+paiwqywyUJJMnh9U
+jKorY+nua81N0oxpIhHPspCanDU4neMzCzYOZyLR/LqV5xORvHcFY84GWMz5hI25
+JbgaWJsYKuCAvNsnQwVoqKPGa7x1fn7x6oGsXJaCVt8weUwIj2xwg1lxMhrNaisH
+EvKpEAEnGGwWKQIDAQABo4HuMIHrMB0GA1UdDgQWBBSs3x4Ui8yJEVdeAOoq6ZLT
+9bYCEzCBuwYDVR0jBIGzMIGwgBSs3x4Ui8yJEVdeAOoq6ZLT9bYCE6GBjKSBiTCB
+hjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYwFAYDVQQKEw13d3cuY3VjYmMu
+Y29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMGA1UEAxQMZGVtb19yb290X2Nh
+MSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNAZ21haWwuY29tggkAlM3BnrI1
+rlswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAlPl3/8h1LttR1svC
+S8RXbHpAWIT2BEDhGHUNjSmgDQNkE/itf/FCEXh0tlU4bYdtBSOHzflbnzOyIPId
+VZeSWs33V38xDFy6KoVg1gT8JxkLmE5S1vWkpsHIlpw/U6r7KD0Kx9FYx5AiXjw0
+lzz/zlVNuO2U09KIDwDPVG1mBzQiMiSWj1U1pM4KxINkWQwDy/fvu/I983s8lW5z
+hf2WuFNzQN3fcMK5dpBE9NVIu27oYuGYh2sak34v+7T700W2ooBB71qFXtm9P5rl
+Yp9RCEsg3KEEPNTtCBs8fROeXvLDrP0cmBIqwGYDuRNCxFDTOdjv6YGdA8nLOjaH
+2dDk0g==
+-----END CERTIFICATE-----
diff --git a/samples/x509/certificate_root_ca.der b/samples/x509/certificate_root_ca.der
new file mode 100644
index 0000000..02f710c
Binary files /dev/null and b/samples/x509/certificate_root_ca.der differ
diff --git a/samples/x509/certificate_root_ca.pem b/samples/x509/certificate_root_ca.pem
new file mode 100644
index 0000000..5811d8e
--- /dev/null
+++ b/samples/x509/certificate_root_ca.pem
@@ -0,0 +1,87 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            94:cd:c1:9e:b2:35:ae:5b
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, O=www.cucbc.com, OU=commons_ssl, CN=demo_root_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Nov  5 21:36:43 2006 GMT
+            Not After : Nov  5 21:36:43 2026 GMT
+        Subject: C=CA, ST=BC, O=www.cucbc.com, OU=commons_ssl, CN=demo_root_ca/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:bf:e3:a7:a1:c9:89:ef:d5:1e:3b:68:65:0b:02:
+                    be:0a:57:b9:b9:95:a7:53:ab:b0:26:5f:b4:f3:3e:
+                    5c:bd:e6:db:e6:d4:fa:e1:62:fd:fa:9b:03:6d:f8:
+                    14:1f:f1:a6:f4:9b:2e:c4:a4:e0:c3:5b:59:3b:fe:
+                    1d:b8:88:27:68:b3:52:c7:81:e8:a9:a4:e3:c2:28:
+                    1d:fe:14:77:4e:ca:06:10:f5:d3:0a:4c:f5:8a:48:
+                    13:08:e1:03:be:5f:a2:32:27:7a:68:ea:dd:99:58:
+                    84:f0:78:6c:73:12:99:fa:1e:45:13:ba:07:67:2b:
+                    93:ea:01:68:89:a2:17:84:5a:be:c4:ad:b0:e1:9c:
+                    03:cf:d2:fe:a5:a8:b0:ab:2c:32:50:92:4c:9e:1f:
+                    54:8c:aa:2b:63:e9:ee:6b:cd:4d:d2:8c:69:22:11:
+                    cf:b2:90:9a:9c:35:38:9d:e3:33:0b:36:0e:67:22:
+                    d1:fc:ba:95:e7:13:91:bc:77:05:63:ce:06:58:cc:
+                    f9:84:8d:b9:25:b8:1a:58:9b:18:2a:e0:80:bc:db:
+                    27:43:05:68:a8:a3:c6:6b:bc:75:7e:7e:f1:ea:81:
+                    ac:5c:96:82:56:df:30:79:4c:08:8f:6c:70:83:59:
+                    71:32:1a:cd:6a:2b:07:12:f2:a9:10:01:27:18:6c:
+                    16:29
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                AC:DF:1E:14:8B:CC:89:11:57:5E:00:EA:2A:E9:92:D3:F5:B6:02:13
+            X509v3 Authority Key Identifier: 
+                keyid:AC:DF:1E:14:8B:CC:89:11:57:5E:00:EA:2A:E9:92:D3:F5:B6:02:13
+                DirName:/C=CA/ST=BC/O=www.cucbc.com/OU=commons_ssl/CN=demo_root_ca/emailAddress=juliusdavies at gmail.com
+                serial:94:CD:C1:9E:B2:35:AE:5B
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha1WithRSAEncryption
+        94:f9:77:ff:c8:75:2e:db:51:d6:cb:c2:4b:c4:57:6c:7a:40:
+        58:84:f6:04:40:e1:18:75:0d:8d:29:a0:0d:03:64:13:f8:ad:
+        7f:f1:42:11:78:74:b6:55:38:6d:87:6d:05:23:87:cd:f9:5b:
+        9f:33:b2:20:f2:1d:55:97:92:5a:cd:f7:57:7f:31:0c:5c:ba:
+        2a:85:60:d6:04:fc:27:19:0b:98:4e:52:d6:f5:a4:a6:c1:c8:
+        96:9c:3f:53:aa:fb:28:3d:0a:c7:d1:58:c7:90:22:5e:3c:34:
+        97:3c:ff:ce:55:4d:b8:ed:94:d3:d2:88:0f:00:cf:54:6d:66:
+        07:34:22:32:24:96:8f:55:35:a4:ce:0a:c4:83:64:59:0c:03:
+        cb:f7:ef:bb:f2:3d:f3:7b:3c:95:6e:73:85:fd:96:b8:53:73:
+        40:dd:df:70:c2:b9:76:90:44:f4:d5:48:bb:6e:e8:62:e1:98:
+        87:6b:1a:93:7e:2f:fb:b4:fb:d3:45:b6:a2:80:41:ef:5a:85:
+        5e:d9:bd:3f:9a:e5:62:9f:51:08:4b:20:dc:a1:04:3c:d4:ed:
+        08:1b:3c:7d:13:9e:5e:f2:c3:ac:fd:1c:98:12:2a:c0:66:03:
+        b9:13:42:c4:50:d3:39:d8:ef:e9:81:9d:03:c9:cb:3a:36:87:
+        d9:d0:e4:d2
+-----BEGIN CERTIFICATE-----
+MIIEgDCCA2igAwIBAgIJAJTNwZ6yNa5bMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS
+BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq
+hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjEzNjQz
+WhcNMjYxMTA1MjEzNjQzWjCBhjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYw
+FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMG
+A1UEAxQMZGVtb19yb290X2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNA
+Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+OnocmJ
+79UeO2hlCwK+Cle5uZWnU6uwJl+08z5cvebb5tT64WL9+psDbfgUH/Gm9JsuxKTg
+w1tZO/4duIgnaLNSx4HoqaTjwigd/hR3TsoGEPXTCkz1ikgTCOEDvl+iMid6aOrd
+mViE8HhscxKZ+h5FE7oHZyuT6gFoiaIXhFq+xK2w4ZwDz9L+paiwqywyUJJMnh9U
+jKorY+nua81N0oxpIhHPspCanDU4neMzCzYOZyLR/LqV5xORvHcFY84GWMz5hI25
+JbgaWJsYKuCAvNsnQwVoqKPGa7x1fn7x6oGsXJaCVt8weUwIj2xwg1lxMhrNaisH
+EvKpEAEnGGwWKQIDAQABo4HuMIHrMB0GA1UdDgQWBBSs3x4Ui8yJEVdeAOoq6ZLT
+9bYCEzCBuwYDVR0jBIGzMIGwgBSs3x4Ui8yJEVdeAOoq6ZLT9bYCE6GBjKSBiTCB
+hjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYwFAYDVQQKEw13d3cuY3VjYmMu
+Y29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMGA1UEAxQMZGVtb19yb290X2Nh
+MSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNAZ21haWwuY29tggkAlM3BnrI1
+rlswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAlPl3/8h1LttR1svC
+S8RXbHpAWIT2BEDhGHUNjSmgDQNkE/itf/FCEXh0tlU4bYdtBSOHzflbnzOyIPId
+VZeSWs33V38xDFy6KoVg1gT8JxkLmE5S1vWkpsHIlpw/U6r7KD0Kx9FYx5AiXjw0
+lzz/zlVNuO2U09KIDwDPVG1mBzQiMiSWj1U1pM4KxINkWQwDy/fvu/I983s8lW5z
+hf2WuFNzQN3fcMK5dpBE9NVIu27oYuGYh2sak34v+7T700W2ooBB71qFXtm9P5rl
+Yp9RCEsg3KEEPNTtCBs8fROeXvLDrP0cmBIqwGYDuRNCxFDTOdjv6YGdA8nLOjaH
+2dDk0g==
+-----END CERTIFICATE-----
diff --git a/samples/x509/oscp.pem b/samples/x509/oscp.pem
new file mode 100644
index 0000000..2f5177a
--- /dev/null
+++ b/samples/x509/oscp.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDnTCCAwagAwIBAgIDPoz6MA0GCSqGSIb3DQEBBAUAMIHEMQswCQYDVQQGEwJa
+QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xHTAb
+BgNVBAoTFFRoYXd0ZSBDb25zdWx0aW5nIGNjMSgwJgYDVQQLEx9DZXJ0aWZpY2F0
+aW9uIFNlcnZpY2VzIERpdmlzaW9uMRkwFwYDVQQDExBUaGF3dGUgU2VydmVyIENB
+MSYwJAYJKoZIhvcNAQkBFhdzZXJ2ZXItY2VydHNAdGhhd3RlLmNvbTAeFw0wNDA4
+MjcwOTEzMjNaFw0wNjA5MTcxNDQ4MjlaMIG/MQswCQYDVQQGEwJDQTEZMBcGA1UE
+CBMQQnJpdGlzaCBDb2x1bWJpYTESMBAGA1UEBxMJVmFuY291dmVyMSwwKgYDVQQK
+EyNWYW5jb3V2ZXIgQ2l0eSBTYXZpbmdzIENyZWRpdCBVbmlvbjEUMBIGA1UECxML
+V2ViIEhvc3RpbmcxGDAWBgNVBAMTD3d3dy52YW5jaXR5LmNvbTEjMCEGCSqGSIb3
+DQEJARYUaG9zdG1hc3RlckBjdWNiYy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALtc21pS+6njj9KkWcrRQt5Yva75YNE8o2aQQTA4aDi8WO1nLkC0qSWw
+V/0wO8K0gIe1WV/RluAKNU7oOmz8DGMRDF+CS5zFLKgKQJ3CxYwaWNKISAWrRkQu
+lp+oAm5EPqAaxtPTE4Fghv1EnZkA4g12g6PxYkAa2KeT80/8M8aBAgMBAAGjgZ8w
+gZwwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMDkGA1UdHwQyMDAwLqAs
+oCqGKGh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVTZXJ2ZXJDQS5jcmwwMgYI
+KwYBBQUHAQEEJjAkMCIGCCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29t
+MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEEBQADgYEAiOi2YuiopBCQpCM6kJkp
+Tu251MgDkn82qx33rxYeZKuv68qvJfucfbiQgqrjVsp1X0Vuv0Uu3vpLs44Gq5Na
+05dDmmAzk3BRrOikMjOhZV4F/+e/NoUTjgi0QSWCavEZvEcW2Ids4xrRS1290TUS
+Fou+stRrYkGIyc3OUG4hZHY=
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/samples/x509/two-crls.pem b/samples/x509/two-crls.pem
new file mode 100644
index 0000000..5ddca1e
--- /dev/null
+++ b/samples/x509/two-crls.pem
@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIINjCCBx6gAwIBAgIKB3SNcwAAAAAAlDANBgkqhkiG9w0BAQUFADCBojELMAkG
+A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
+MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
+d3d3LnVzZXJ0cnVzdC5jb20xKjAoBgNVBAMTIVVTRVJUUlVTVCAtIFNlcnZlciBB
+dXRoZW50aWNhdGlvbjAeFw0wNTA0MDUxODM1MDZaFw0wNzAzMDYwMzIyMDRaMHYx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp
+dHkxEjAQBgNVBAoTCVVTRVJUUlVTVDERMA8GA1UECxMIREFUQUNvcnAxGjAYBgNV
+BAMTEXd3dy51c2VydHJ1c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA1yFt+Fjn7VJaPv7lv5IyQTjx7mFv2myDOci0sf13SjWo6D8Lv/8tC7Xt
+VoDXyonDY4ulBu2wIoKNocbtyNQGjb7RaYMxpxMrFydypIWXVfz3yuvJr74ZeGc1
+0X+vLTzThsQe/QLkqxDq0btjGfuaYe0wfogOGh6nptWNAiCvvrAO9TBE4NW5q7F2
+ZZQD/MhVgG2o+rGUOL7ieEWNtX7P596hCUaji6t2UIVQXViReCGjot0dw9wLGJ38
+hLIX+KdI5arB00ODSeo1X+EobDOpL6xiIh1vRJS7Cb59/cXk/P+STGOXVlP+d1xT
+W66rfYuvdKzqMICxbghXhQF9tD0mZQIDAQABo4IElzCCBJMwCwYDVR0PBAQDAgG4
+MBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSgPNyE/1EGrMbLIevLBQfX
+EMJo5jCB0wYDVR0jBIHLMIHIgBR1ASiXxkYbNG7ooJEVcZJ57rcDzqGBnaSBmjCB
+lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
+Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
+SGFyZHdhcmWCEAAVbCcaVP6zgr6vVP70ooswDAYDVR0TAQH/BAIwADCBkwYDVR0f
+BIGLMIGIMEGgP6A9hjtodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRSVVNU
+LVNlcnZlckF1dGhlbnRpY2F0aW9uLmNybDBDoEGgP4Y9aHR0cDovL3d3dy51dG5z
+ZWN1cml0eS5jb20vVVNFUlRSVVNULVNlcnZlckF1dGhlbnRpY2F0aW9uLmNybDCB
+tAYIKwYBBQUHAQEEgacwgaQwTwYIKwYBBQUHMAKGQ2h0dHA6Ly93d3cudXNlcnRy
+dXN0LmNvbS9DQUNlcnRzL1VTRVJUUlVTVC1TZXJ2ZXJBdXRoZW50aWNhdGlvbi5j
+cnQwUQYIKwYBBQUHMAKGRWh0dHA6Ly93d3cudXRuc2VjdXJpdHkuY29tL0NBQ2Vy
+dHMvVVNFUlRSVVNULVNlcnZlckF1dGhlbnRpY2F0aW9uLmNydDCCAh0GA1UdIASC
+AhQwggIQMIICDAYIKoZIhvpfAQEwggH+MCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
+LnVzZXJ0cnVzdC5jb20vQ1BTMIIB0AYIKwYBBQUHAgIwggHCGoIBvlRoaXMgY2Vy
+dGlmaWNhdGUgaW5jb3Jwb3JhdGVzIGJ5IHJlZmVyZW5jZSwgYW5kIGl0cyB1c2Ug
+aXMgc3RyaWN0bHkgc3ViamVjdCB0bywgdGhlIFVTRVJGaXJzdCBDZXJ0aWZpY2F0
+aW9uIFByYWN0aWNlcyBTdGF0ZW1lbnQgKENQUykuIFB1cnN1YW50IHRvIHRoZSBD
+UFMsIFV0YWggU3RhdGUgbGF3LCBhbmQgRmVkZXJhbCBsYXcsIGNlcnRhaW4gd2Fy
+cmFudGllcyBhcmUgZGlzY2xhaW1lZCBhbmQgbGlhYmlsaXR5IGlzIGxpbWl0ZWQu
+IENvcGllcyBvZiB0aGUgQ1BTIGFyZSBhdmFpbGFibGUgYXQ6IGh0dHA6Ly93d3cu
+dXNlcnRydXN0LmNvbS9DUFM7IG9yIGJ5IG1haWwgYXQgVVNFUlRydXN0LCBJbmMu
+LCAyNjUgRWFzdCAxMDAgU291dGgsIFNhbHQgTGFrZSBDaXR5LCBVVCA4NDExMS4g
+Q29weXJpZ2h0KGMpIDIwMDIgVVNFUlRydXN0LCBJbmMuIEFsbCBSaWdodHMgUmVz
+ZXJ2ZWQuMA0GCSqGSIb3DQEBBQUAA4IBAQDPZpUYi6Nz5wSo+hbzYmBKJvG1N7PN
+etSdYz+h7lIwKZ56sue6oPm/T5VjY7upz8W5GL1q5YLNOr836pxXvNgg2L4ajPUA
+nq3EZtNgkt0iZmGISQwFcgUDnYJ4L56c84vXlreLS2xAD3rL+XeIE/d08OcxLpSB
+udQKfNEd84tM564hEkD5ah99qJbckBFqRNf89ZijW7xPUavbhGStaeaCvdllekRD
+ZYtppwGMlA1Lw74p74GpgAwzRtc3vkya4Ls/FZ7d7/R/cOkLX+MYp6SAi+GsHEYz
+55ACEUNhFU6X6sIkhFgxqDe0hL/AcKCV+WTJ0pSGXCFdUbPGsPQCy3ck
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_foo.pem b/samples/x509/x509_foo.pem
new file mode 100644
index 0000000..c7601e9
--- /dev/null
+++ b/samples/x509/x509_foo.pem
@@ -0,0 +1,85 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:90
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 15:31:41 2006 GMT
+            Not After : Nov  5 15:31:41 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=foo.com/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+    Signature Algorithm: sha1WithRSAEncryption
+        b7:8d:19:84:c9:ae:ac:40:29:26:89:e5:0b:72:fc:7c:cf:3d:
+        5e:b8:29:3d:7d:27:b3:ec:11:2d:92:2f:3e:76:67:cc:5d:ed:
+        ca:ee:c1:f4:94:8f:1f:e2:32:51:d2:b6:d2:0a:3a:66:09:02:
+        d8:9b:30:b7:37:10:4a:78:93:96:d1:17:23:34:1a:4e:73:62:
+        65:18:ef:5a:b9:7b:f6:18:33:f8:21:88:97:12:52:c9:e9:54:
+        aa:73:c5:af:0e:29:2f:d0:99:82:09:69:b4:66:06:be:6d:96:
+        d1:fc:45:8d:e4:37:84:b4:57:45:f3:5e:42:2e:92:59:35:c6:
+        30:89:8c:06:cb:f0:95:43:bc:36:4e:75:e5:1b:e9:ab:69:93:
+        b3:fa:8c:2b:f9:c2:fa:27:f6:5e:b1:b7:44:59:f8:e8:4b:5f:
+        9c:50:48:44:1f:09:4d:ac:0b:bc:8e:56:76:52:a4:a0:b2:44:
+        96:96:16:1d:31:30:0f:f4:23:c7:89:4b:fd:37:b1:5c:4f:9f:
+        08:b6:ff:c8:e1:f2:91:10:83:50:62:30:e9:bd:07:31:49:a4:
+        d8:6f:d7:6b:e6:c0:78:58:b3:60:96:4e:f3:c4:3b:4c:f3:41:
+        f9:d7:c5:6f:8a:14:dc:3f:b1:47:2f:e1:a7:ea:0e:23:e5:f9:
+        08:f7:cf:92
+-----BEGIN CERTIFICATE-----
+MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aQMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzE0MVoXDTI4MTEwNTE1MzE0MVowgaQx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
+cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs
+aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B
+lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy
+zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY
+07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8
+BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV
+JTxpTKqym93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB
+hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE
+FJ8Ud78/OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNS
+yoemDT4NMA0GCSqGSIb3DQEBBQUAA4IBAQC3jRmEya6sQCkmieULcvx8zz1euCk9
+fSez7BEtki8+dmfMXe3K7sH0lI8f4jJR0rbSCjpmCQLYmzC3NxBKeJOW0RcjNBpO
+c2JlGO9auXv2GDP4IYiXElLJ6VSqc8WvDikv0JmCCWm0Zga+bZbR/EWN5DeEtFdF
+815CLpJZNcYwiYwGy/CVQ7w2TnXlG+mraZOz+owr+cL6J/ZesbdEWfjoS1+cUEhE
+HwlNrAu8jlZ2UqSgskSWlhYdMTAP9CPHiUv9N7FcT58Itv/I4fKREINQYjDpvQcx
+SaTYb9dr5sB4WLNglk7zxDtM80H518VvihTcP7FHL+Gn6g4j5fkI98+S
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_foo_bar.pem b/samples/x509/x509_foo_bar.pem
new file mode 100644
index 0000000..04c9ddc
--- /dev/null
+++ b/samples/x509/x509_foo_bar.pem
@@ -0,0 +1,88 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:91
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 15:36:29 2006 GMT
+            Not After : Nov  5 15:36:29 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=foo.com/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+            X509v3 Subject Alternative Name: 
+                DNS:bar.com
+    Signature Algorithm: sha1WithRSAEncryption
+        75:0c:a9:ac:d6:41:99:59:ef:b9:55:a3:57:8d:ac:7b:2f:cf:
+        4d:f9:18:4a:12:70:cb:58:f4:fe:37:05:65:1f:f2:a5:95:28:
+        be:98:87:18:33:b5:0e:02:f7:63:72:0f:cd:54:36:ea:e8:54:
+        b1:2c:3a:1b:48:06:46:26:81:0d:ef:f4:2d:47:25:5d:9a:09:
+        cd:75:f5:aa:94:b9:e4:e6:9d:c5:6e:f7:6e:bc:e2:4b:4b:31:
+        46:01:ab:64:4f:dd:de:0e:64:92:2a:3a:20:40:f8:ec:e3:fa:
+        c1:89:e5:99:9e:c4:28:ff:5c:aa:35:b0:96:7b:c7:9e:75:1c:
+        67:64:ac:72:82:cd:62:cf:6b:37:d7:1c:a7:cb:6e:ab:66:f2:
+        f3:c3:b2:84:ac:06:8c:97:e1:3a:e7:6a:7d:33:59:70:3c:d1:
+        1f:1e:05:ce:6e:d4:b1:56:b2:71:5c:38:b8:39:a1:10:72:6b:
+        02:c9:8c:3e:98:ff:f9:74:4a:f7:fe:36:db:1a:be:f1:b7:3a:
+        1e:88:dd:b5:b0:b2:ba:0f:df:bc:16:6f:66:a4:17:4a:65:3c:
+        9b:c2:15:70:c9:96:33:3d:19:40:ef:1e:7b:74:24:04:73:19:
+        7c:2c:bb:3f:f9:2b:55:b5:b1:fe:e1:13:22:65:2e:f8:d6:60:
+        db:67:b0:13
+-----BEGIN CERTIFICATE-----
+MIIEXDCCA0SgAwIBAgIJAIz+EYMBU6aRMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzYyOVoXDTI4MTEwNTE1MzYyOVowgaQx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
+cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs
+aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B
+lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy
+zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY
+07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8
+BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV
+JTxpTKqym93whYk93l3ocEe55c0CAwEAAaOBkDCBjTAJBgNVHRMEAjAAMCwGCWCG
+SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E
+FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz
+A1LKh6YNPg0wEgYDVR0RBAswCYIHYmFyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEA
+dQyprNZBmVnvuVWjV42sey/PTfkYShJwy1j0/jcFZR/ypZUovpiHGDO1DgL3Y3IP
+zVQ26uhUsSw6G0gGRiaBDe/0LUclXZoJzXX1qpS55OadxW73brziS0sxRgGrZE/d
+3g5kkio6IED47OP6wYnlmZ7EKP9cqjWwlnvHnnUcZ2SscoLNYs9rN9ccp8tuq2by
+88OyhKwGjJfhOudqfTNZcDzRHx4Fzm7UsVaycVw4uDmhEHJrAsmMPpj/+XRK9/42
+2xq+8bc6HojdtbCyug/fvBZvZqQXSmU8m8IVcMmWMz0ZQO8ee3QkBHMZfCy7P/kr
+VbWx/uETImUu+NZg22ewEw==
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_foo_bar_hanako.pem b/samples/x509/x509_foo_bar_hanako.pem
new file mode 100644
index 0000000..4e80578
--- /dev/null
+++ b/samples/x509/x509_foo_bar_hanako.pem
@@ -0,0 +1,88 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:92
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 15:38:13 2006 GMT
+            Not After : Nov  5 15:38:13 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=foo.com/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+            X509v3 Subject Alternative Name: 
+                DNS:bar.com, DNS:花子.co.jp
+    Signature Algorithm: sha1WithRSAEncryption
+        5e:66:ce:d9:21:8c:8a:b5:d9:d5:c5:5b:dd:2e:0c:32:48:43:
+        ce:13:8a:41:49:78:a2:ed:76:2f:d1:0f:50:52:f1:bf:fb:e8:
+        05:19:08:7c:f4:78:40:07:30:35:99:55:23:1f:97:49:4d:0a:
+        92:2c:5b:d1:7e:a4:c7:a8:ba:71:4b:14:96:a8:c1:e7:bd:13:
+        38:70:f0:64:21:1a:7f:5e:53:0a:3e:55:da:75:8b:49:2c:f4:
+        e0:a5:b8:2f:ba:50:35:89:c9:02:f4:4c:25:35:85:a7:a3:06:
+        78:bb:19:df:b0:c8:21:5b:81:ec:90:1a:9a:57:e3:e7:43:c6:
+        6f:cb:72:f4:d7:67:3b:0a:0e:26:28:a4:b9:a5:bd:47:75:1b:
+        a2:0f:6a:29:67:e1:dc:ef:b8:11:40:bb:ed:58:d4:bc:8d:0b:
+        dd:fe:24:db:87:a7:ee:bd:32:9f:00:e1:68:5f:0d:b6:b1:62:
+        0a:1d:8a:e6:84:22:11:b2:15:0d:a2:11:97:bf:9d:26:da:8f:
+        b5:c3:da:16:99:0e:83:92:ae:e5:0a:37:d7:7d:40:78:c0:86:
+        e0:80:98:e9:c8:4b:5b:36:a0:6d:8f:83:02:db:1e:6b:7e:c2:
+        ca:2a:a4:e8:2a:63:44:ee:91:44:82:ac:1e:f3:ff:c0:6a:bd:
+        5b:f9:08:fe
+-----BEGIN CERTIFICATE-----
+MIIEajCCA1KgAwIBAgIJAIz+EYMBU6aSMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzgxM1oXDTI4MTEwNTE1MzgxM1owgaQx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
+cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs
+aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B
+lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy
+zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY
+07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8
+BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV
+JTxpTKqym93whYk93l3ocEe55c0CAwEAAaOBnjCBmzAJBgNVHRMEAjAAMCwGCWCG
+SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E
+FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz
+A1LKh6YNPg0wIAYDVR0RBBkwF4IHYmFyLmNvbYIM6Iqx5a2QLmNvLmpwMA0GCSqG
+SIb3DQEBBQUAA4IBAQBeZs7ZIYyKtdnVxVvdLgwySEPOE4pBSXii7XYv0Q9QUvG/
+++gFGQh89HhABzA1mVUjH5dJTQqSLFvRfqTHqLpxSxSWqMHnvRM4cPBkIRp/XlMK
+PlXadYtJLPTgpbgvulA1ickC9EwlNYWnowZ4uxnfsMghW4HskBqaV+PnQ8Zvy3L0
+12c7Cg4mKKS5pb1HdRuiD2opZ+Hc77gRQLvtWNS8jQvd/iTbh6fuvTKfAOFoXw22
+sWIKHYrmhCIRshUNohGXv50m2o+1w9oWmQ6Dkq7lCjfXfUB4wIbggJjpyEtbNqBt
+j4MC2x5rfsLKKqToKmNE7pFEgqwe8//Aar1b+Qj+
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_hanako.pem b/samples/x509/x509_hanako.pem
new file mode 100644
index 0000000..548c546
--- /dev/null
+++ b/samples/x509/x509_hanako.pem
@@ -0,0 +1,85 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:93
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 15:42:15 2006 GMT
+            Not After : Nov  5 15:42:15 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=\xE8\x8A\xB1\xE5\xAD\x90.co.jp/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+    Signature Algorithm: sha1WithRSAEncryption
+        b2:76:ee:2d:e8:91:5f:ca:be:50:e9:e8:a3:08:0f:78:1d:21:
+        39:7a:f0:fc:88:b7:3c:f1:f9:2a:ae:17:c8:1a:84:c8:74:d7:
+        a3:57:ef:7c:ff:a1:56:68:55:43:5d:7e:d9:5a:f3:03:d4:07:
+        51:b0:22:40:27:1a:48:50:f4:b1:ca:b2:90:5d:6d:18:82:8f:
+        48:0c:98:b0:ac:5f:c4:ab:8c:5b:eb:ed:c6:1b:d9:c2:ba:27:
+        f7:c9:7b:dd:a5:d6:d8:3f:ed:8e:28:ed:5f:ec:e0:90:5e:fd:
+        cc:bd:53:dc:3c:6b:47:2d:b8:39:84:04:28:02:ef:ce:09:30:
+        3b:53:eb:b9:25:45:fa:ff:d8:b9:6a:5a:19:4e:12:ae:e9:50:
+        5c:51:2d:b8:69:aa:e6:80:1d:23:a3:98:87:16:9d:5a:70:f4:
+        1b:0e:ee:a7:b8:ea:18:9d:82:7d:fd:84:a8:75:5a:32:8a:d9:
+        57:0b:ff:76:11:b0:2e:30:52:2d:0f:06:d1:56:e9:27:0c:0a:
+        e3:21:80:84:57:48:f5:39:e5:16:9e:50:89:4e:74:f8:e3:af:
+        54:94:35:61:88:77:5a:c3:ed:6d:7a:49:ca:70:9e:49:e7:df:
+        5d:05:37:11:4c:1d:52:34:19:31:85:90:d7:64:8a:53:42:14:
+        97:08:a1:10
+-----BEGIN CERTIFICATE-----
+MIIESzCCAzOgAwIBAgIJAIz+EYMBU6aTMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1NDIxNVoXDTI4MTEwNTE1NDIxNVowgakx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl
+cnRpZmljYXRlczEVMBMGA1UEAwwM6Iqx5a2QLmNvLmpwMSUwIwYJKoZIhvcNAQkB
+FhZqdWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjU
+g4pNjYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQc
+wHf0ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t
+7iu1JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAn
+AxK6q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArD
+qUYxqJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwG
+CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV
+HQ4EFgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLS
+rNuzA1LKh6YNPg0wDQYJKoZIhvcNAQEFBQADggEBALJ27i3okV/KvlDp6KMID3gd
+ITl68PyItzzx+SquF8gahMh016NX73z/oVZoVUNdftla8wPUB1GwIkAnGkhQ9LHK
+spBdbRiCj0gMmLCsX8SrjFvr7cYb2cK6J/fJe92l1tg/7Y4o7V/s4JBe/cy9U9w8
+a0ctuDmEBCgC784JMDtT67klRfr/2LlqWhlOEq7pUFxRLbhpquaAHSOjmIcWnVpw
+9BsO7qe46hidgn39hKh1WjKK2VcL/3YRsC4wUi0PBtFW6ScMCuMhgIRXSPU55Rae
+UIlOdPjjr1SUNWGId1rD7W16Scpwnknn310FNxFMHVI0GTGFkNdkilNCFJcIoRA=
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_no_cns_foo.pem b/samples/x509/x509_no_cns_foo.pem
new file mode 100644
index 0000000..5e77ce4
--- /dev/null
+++ b/samples/x509/x509_no_cns_foo.pem
@@ -0,0 +1,87 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:98
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 16:26:10 2006 GMT
+            Not After : Nov  5 16:26:10 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+            X509v3 Subject Alternative Name: 
+                DNS:foo.com
+    Signature Algorithm: sha1WithRSAEncryption
+        8e:5e:fc:a0:c8:f3:15:db:0c:cb:a1:75:b0:68:3f:22:43:bc:
+        b4:5e:72:52:03:e0:15:8a:ec:e3:5c:b3:01:c6:bb:21:0b:ba:
+        1b:da:ad:14:32:73:ff:b7:a1:87:ff:47:a0:6f:a8:a8:20:88:
+        1c:fb:88:3a:64:bb:49:dd:30:9e:4c:89:63:b6:34:e2:35:57:
+        21:bd:da:e9:fe:80:80:19:04:14:fd:67:39:3d:33:ea:48:d3:
+        ee:f9:00:e4:b2:76:cb:73:22:0d:c5:ee:44:d3:12:b5:ae:4f:
+        61:59:eb:5f:c6:99:ca:2a:95:50:d8:b8:d2:97:ae:67:64:7c:
+        98:05:12:06:f5:a0:0f:bc:f6:a9:68:45:f1:88:03:6f:bc:16:
+        68:58:e0:e7:72:37:ea:f5:8a:9f:dd:19:12:d8:b7:c0:d0:b0:
+        a8:05:6a:8b:13:3e:27:4a:89:99:04:ad:80:07:39:de:2d:9a:
+        4c:cb:c0:42:ed:c0:de:c9:ef:1f:f3:c7:4c:1a:3e:e5:42:fb:
+        da:7f:52:d6:46:72:34:2b:15:7f:54:28:9f:c8:ca:4e:24:6b:
+        88:43:3e:7c:c1:65:72:04:0f:db:ce:04:04:5c:d8:1f:20:97:
+        15:bf:4e:fe:13:23:2b:6f:ba:99:8f:5e:b8:c0:75:53:56:85:
+        17:33:3f:06
+-----BEGIN CERTIFICATE-----
+MIIESjCCAzKgAwIBAgIJAIz+EYMBU6aYMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MjYxMFoXDTI4MTEwNTE2MjYxMFowgZIx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl
+cnRpZmljYXRlczElMCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNv
+bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhjr5aCPoyp0R1iroWA
+fnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2BlYho4O84X244QrZTRl8kQbYt
+xnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRyzerA/ZtrlUqf+lKo0uWcocxe
+Rc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY07hNKXAb2odnVqgzcYiDkLV8
+ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8BqnGd87xQU3FVZI4tbtkB+Kz
+jD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiVJTxpTKqym93whYk93l3ocEe5
+5c0CAwEAAaOBkDCBjTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
+IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxR3vz86tso4gkJIFiza
+0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuzA1LKh6YNPg0wEgYDVR0RBAsw
+CYIHZm9vLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAjl78oMjzFdsMy6F1sGg/IkO8
+tF5yUgPgFYrs41yzAca7IQu6G9qtFDJz/7ehh/9HoG+oqCCIHPuIOmS7Sd0wnkyJ
+Y7Y04jVXIb3a6f6AgBkEFP1nOT0z6kjT7vkA5LJ2y3MiDcXuRNMSta5PYVnrX8aZ
+yiqVUNi40peuZ2R8mAUSBvWgD7z2qWhF8YgDb7wWaFjg53I36vWKn90ZEti3wNCw
+qAVqixM+J0qJmQStgAc53i2aTMvAQu3A3snvH/PHTBo+5UL72n9S1kZyNCsVf1Qo
+n8jKTiRriEM+fMFlcgQP284EBFzYHyCXFb9O/hMjK2+6mY9euMB1U1aFFzM/Bg==
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_three_cns_foo_bar_hanako.pem b/samples/x509/x509_three_cns_foo_bar_hanako.pem
new file mode 100644
index 0000000..a57ef79
--- /dev/null
+++ b/samples/x509/x509_three_cns_foo_bar_hanako.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:97
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 16:19:45 2006 GMT
+            Not After : Nov  5 16:19:45 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=foo.com, CN=bar.com, CN=\xE8\x8A\xB1\xE5\xAD\x90.co.jp/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+    Signature Algorithm: sha1WithRSAEncryption
+        6b:99:6f:c6:a2:d4:d3:b6:8f:8b:f7:cb:d4:cb:66:f7:79:b3:
+        4b:e1:e7:f4:c4:ee:7e:d1:5f:ef:14:cb:7e:ce:2f:99:3b:c7:
+        d9:ed:d2:63:35:4f:20:0a:c6:50:9c:63:ef:61:e9:fa:ee:7b:
+        c3:1e:99:92:08:2d:22:2f:32:bb:73:71:ca:8d:cf:45:75:58:
+        a8:00:f8:ea:df:b9:4a:da:6e:69:fe:0b:11:c5:e6:0a:72:ea:
+        0d:50:b3:62:23:55:85:80:e5:fe:c5:44:e9:ff:27:e0:1d:f2:
+        02:58:73:56:b3:39:60:8b:42:a4:b2:7e:93:51:2d:2b:d8:12:
+        b8:90:14:45:7a:dd:7b:e4:27:c2:6b:1b:ad:9b:fb:63:93:da:
+        5a:93:e0:e3:b4:ee:04:8f:7a:da:69:76:54:9a:f0:d0:52:28:
+        fe:80:ae:8f:51:21:7d:59:8d:46:50:4a:94:05:09:fa:34:d8:
+        d3:b4:b8:d4:43:3d:47:49:c7:68:6e:c9:c7:4d:6f:e0:17:1d:
+        a3:bb:79:77:af:0c:b2:7e:42:7a:88:98:8c:f1:5a:26:3a:cc:
+        b3:9d:ce:38:c8:54:13:24:2c:79:a7:3f:b4:a3:19:24:37:5c:
+        0e:01:ca:b4:0e:c5:f3:94:4f:22:f2:13:b3:6e:7a:68:47:a6:
+        9b:90:3f:11
+-----BEGIN CERTIFICATE-----
+MIIEbzCCA1egAwIBAgIJAIz+EYMBU6aXMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTk0NVoXDTI4MTEwNTE2MTk0NVowgc0x
+CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl
+cnRpZmljYXRlczEQMA4GA1UEAwwHZm9vLmNvbTEQMA4GA1UEAwwHYmFyLmNvbTEV
+MBMGA1UEAwwM6Iqx5a2QLmNvLmpwMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyGOv
+loI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pNjYGViGjg7zhf
+bjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0ZHLN6sD9m2uV
+Sp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1JVjTuE0pcBva
+h2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6q/wGqcZ3zvFB
+TcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYxqJUlPGlMqrKb
+3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
+Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxR3vz86
+tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuzA1LKh6YNPg0w
+DQYJKoZIhvcNAQEFBQADggEBAGuZb8ai1NO2j4v3y9TLZvd5s0vh5/TE7n7RX+8U
+y37OL5k7x9nt0mM1TyAKxlCcY+9h6frue8MemZIILSIvMrtzccqNz0V1WKgA+Orf
+uUrabmn+CxHF5gpy6g1Qs2IjVYWA5f7FROn/J+Ad8gJYc1azOWCLQqSyfpNRLSvY
+EriQFEV63XvkJ8JrG62b+2OT2lqT4OO07gSPetppdlSa8NBSKP6Aro9RIX1ZjUZQ
+SpQFCfo02NO0uNRDPUdJx2huycdNb+AXHaO7eXevDLJ+QnqImIzxWiY6zLOdzjjI
+VBMkLHmnP7SjGSQ3XA4ByrQOxfOUTyLyE7NuemhHppuQPxE=
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_wild_co_jp.pem b/samples/x509/x509_wild_co_jp.pem
new file mode 100644
index 0000000..1dc9ae7
--- /dev/null
+++ b/samples/x509/x509_wild_co_jp.pem
@@ -0,0 +1,85 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:95
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 16:16:30 2006 GMT
+            Not After : Nov  5 16:16:30 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=*.co.jp/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+    Signature Algorithm: sha1WithRSAEncryption
+        34:b1:68:25:56:53:31:db:33:46:bd:4a:85:0b:bd:d7:b5:11:
+        30:8a:2e:77:09:f3:0c:ea:6b:5f:db:e7:f7:93:f7:7c:29:78:
+        4b:37:24:ab:83:c4:51:94:dd:75:ce:09:a9:3d:a2:ed:6d:d4:
+        cb:ae:61:b8:51:d0:07:1d:8a:fc:3b:8c:b6:04:19:84:d5:cc:
+        4d:7c:6c:71:79:c8:60:17:c1:d7:d7:44:15:e1:d9:32:ce:9e:
+        99:d5:c7:f0:bc:27:8c:ad:3e:46:fd:5d:69:7a:36:a0:a3:46:
+        b2:5f:1f:86:3c:b6:d6:94:d7:99:4b:e2:a5:d2:6d:e9:f9:0a:
+        65:5e:e8:ed:c0:6e:5f:61:c2:29:68:6a:62:62:b6:81:2f:1d:
+        d3:69:d8:a1:df:d4:0d:eb:90:a7:02:1f:f3:44:38:4b:09:4c:
+        ca:ca:df:65:50:63:cb:11:40:f3:44:73:0f:1c:b9:d2:a9:3d:
+        67:e5:45:39:50:34:72:b5:b8:c9:3d:7c:c5:fa:5f:fe:59:92:
+        2c:6a:77:9f:58:bb:31:9e:48:00:b9:97:bf:a0:c3:05:10:93:
+        2b:c8:4c:ce:8e:0e:13:7e:e7:39:a8:cd:04:5e:83:dc:43:f2:
+        65:85:e6:b1:67:8d:29:d8:8c:87:a9:bb:16:57:83:11:62:e1:
+        47:e1:b9:0c
+-----BEGIN CERTIFICATE-----
+MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aVMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTYzMFoXDTI4MTEwNTE2MTYzMFowgaQx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
+cnRpZmljYXRlczEQMA4GA1UEAxQHKi5jby5qcDElMCMGCSqGSIb3DQEJARYWanVs
+aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B
+lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy
+zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY
+07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8
+BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV
+JTxpTKqym93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB
+hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE
+FJ8Ud78/OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNS
+yoemDT4NMA0GCSqGSIb3DQEBBQUAA4IBAQA0sWglVlMx2zNGvUqFC73XtREwii53
+CfMM6mtf2+f3k/d8KXhLNySrg8RRlN11zgmpPaLtbdTLrmG4UdAHHYr8O4y2BBmE
+1cxNfGxxechgF8HX10QV4dkyzp6Z1cfwvCeMrT5G/V1pejago0ayXx+GPLbWlNeZ
+S+Kl0m3p+QplXujtwG5fYcIpaGpiYraBLx3Tadih39QN65CnAh/zRDhLCUzKyt9l
+UGPLEUDzRHMPHLnSqT1n5UU5UDRytbjJPXzF+l/+WZIsanefWLsxnkgAuZe/oMMF
+EJMryEzOjg4Tfuc5qM0EXoPcQ/JlheaxZ40p2IyHqbsWV4MRYuFH4bkM
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_wild_foo.pem b/samples/x509/x509_wild_foo.pem
new file mode 100644
index 0000000..62ecdf3
--- /dev/null
+++ b/samples/x509/x509_wild_foo.pem
@@ -0,0 +1,85 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:94
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 16:15:55 2006 GMT
+            Not After : Nov  5 16:15:55 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=*.foo.com/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+    Signature Algorithm: sha1WithRSAEncryption
+        7d:22:a4:6e:89:e7:ad:54:29:47:e0:91:e5:bb:1a:f6:30:5b:
+        df:01:37:56:68:a1:65:fe:24:41:19:2b:bf:8f:7f:ff:7a:77:
+        72:23:d2:bc:3d:00:27:cd:e1:ba:5f:9c:2a:b4:55:43:59:55:
+        26:01:f8:6b:61:43:6c:d8:bb:3e:ed:7f:f5:18:03:a9:f1:56:
+        04:7f:22:31:ba:f4:19:ac:06:5f:76:b8:53:bb:25:33:6d:1f:
+        3b:6e:88:fa:81:9f:9f:69:b7:eb:cd:c7:8c:8f:be:7a:3b:ce:
+        6c:6c:7c:8e:e3:bf:4c:30:c9:fb:3e:d0:53:66:ec:5c:1d:b0:
+        2d:64:e3:b1:81:48:e6:86:c3:7f:24:b8:85:56:a9:74:80:6c:
+        be:04:5f:d1:a4:af:21:86:38:a1:8d:87:4a:af:00:43:42:75:
+        14:81:1b:d6:7a:b7:23:1b:99:f4:58:f9:d2:d2:87:76:bd:27:
+        0a:04:70:15:2c:a3:a1:16:60:16:a4:2d:ba:b8:9c:6f:e7:bd:
+        87:58:bc:6f:5e:86:b9:cb:57:06:45:2f:cd:9e:97:74:3f:44:
+        af:79:6e:70:3a:72:e4:42:94:6b:ac:2d:a7:74:7b:a6:e3:90:
+        1c:f1:fd:54:37:55:aa:c3:12:90:24:4c:b5:06:54:06:b4:08:
+        b5:ed:9f:27
+-----BEGIN CERTIFICATE-----
+MIIESDCCAzCgAwIBAgIJAIz+EYMBU6aUMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTU1NVoXDTI4MTEwNTE2MTU1NVowgaYx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
+cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq
+dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN
+jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0
+ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1
+JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6
+q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx
+qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCG
+SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E
+FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz
+A1LKh6YNPg0wDQYJKoZIhvcNAQEFBQADggEBAH0ipG6J561UKUfgkeW7GvYwW98B
+N1ZooWX+JEEZK7+Pf/96d3Ij0rw9ACfN4bpfnCq0VUNZVSYB+GthQ2zYuz7tf/UY
+A6nxVgR/IjG69BmsBl92uFO7JTNtHztuiPqBn59pt+vNx4yPvno7zmxsfI7jv0ww
+yfs+0FNm7FwdsC1k47GBSOaGw38kuIVWqXSAbL4EX9GkryGGOKGNh0qvAENCdRSB
+G9Z6tyMbmfRY+dLSh3a9JwoEcBUso6EWYBakLbq4nG/nvYdYvG9ehrnLVwZFL82e
+l3Q/RK95bnA6cuRClGusLad0e6bjkBzx/VQ3VarDEpAkTLUGVAa0CLXtnyc=
+-----END CERTIFICATE-----
diff --git a/samples/x509/x509_wild_foo_bar_hanako.pem b/samples/x509/x509_wild_foo_bar_hanako.pem
new file mode 100644
index 0000000..2c751b7
--- /dev/null
+++ b/samples/x509/x509_wild_foo_bar_hanako.pem
@@ -0,0 +1,88 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:fe:11:83:01:53:a6:96
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=CA, ST=BC, L=Vancouver, O=www.cucbc.com, OU=commons_ssl, CN=demo_intermediate_ca/emailAddress=juliusdavies at gmail.com
+        Validity
+            Not Before: Dec 11 16:17:31 2006 GMT
+            Not After : Nov  5 16:17:31 2028 GMT
+        Subject: C=US, ST=Maryland, L=Forest Hill, O=httpcomponents, OU=test certificates, CN=*.foo.com/emailAddress=juliusdavies at gmail.com
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c8:63:af:96:82:3e:8c:a9:d1:1d:62:ae:85:80:
+                    7e:71:32:04:c1:98:5a:80:a2:74:7f:7a:c8:63:c5:
+                    8d:82:e8:c1:ec:f9:69:82:98:d4:83:8a:4d:8d:81:
+                    95:88:68:e0:ef:38:5f:6e:38:42:b6:53:46:5f:24:
+                    41:b6:2d:c6:71:a1:e2:04:82:0f:e6:7c:82:36:7f:
+                    80:cb:cb:52:58:6a:39:bf:96:5c:f0:14:1c:c0:77:
+                    f4:64:72:cd:ea:c0:fd:9b:6b:95:4a:9f:fa:52:a8:
+                    d2:e5:9c:a1:cc:5e:45:ce:fb:d4:a3:7c:70:f1:f7:
+                    9c:76:74:ad:5d:07:c7:86:40:67:2e:94:e3:1c:4e:
+                    6d:ee:2b:b5:25:58:d3:b8:4d:29:70:1b:da:87:67:
+                    56:a8:33:71:88:83:90:b5:7c:8a:5b:c4:9a:83:56:
+                    31:6a:e9:f1:40:6a:91:37:29:12:16:21:09:8a:77:
+                    71:39:20:27:03:12:ba:ab:fc:06:a9:c6:77:ce:f1:
+                    41:4d:c5:55:92:38:b5:bb:64:07:e2:b3:8c:3f:73:
+                    cf:c4:02:0c:90:1f:0e:36:47:47:4d:ca:35:0e:66:
+                    c4:e8:17:c3:1c:0a:c3:a9:46:31:a8:95:25:3c:69:
+                    4c:aa:b2:9b:dd:f0:85:89:3d:de:5d:e8:70:47:b9:
+                    e5:cd
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                9F:14:77:BF:3F:3A:B6:CA:38:82:42:48:16:2C:DA:D0:CB:5E:87:D8
+            X509v3 Authority Key Identifier: 
+                keyid:7B:9A:DA:8F:90:99:4E:52:D2:AC:DB:B3:03:52:CA:87:A6:0D:3E:0D
+
+            X509v3 Subject Alternative Name: 
+                DNS:*.bar.com, DNS:*.花子.co.jp
+    Signature Algorithm: sha1WithRSAEncryption
+        68:6d:60:be:0f:9f:e5:c7:a6:21:5f:ae:02:c1:9d:ba:5c:b8:
+        f1:68:4d:12:e3:5e:5a:8d:b0:6a:0c:ae:e5:cf:e4:60:ef:33:
+        84:dc:6b:13:00:c8:be:95:d5:18:9e:1c:b3:d3:00:e2:5c:1f:
+        14:c0:a5:e5:d1:20:d3:a0:1d:99:e0:63:a0:a9:08:c0:aa:83:
+        26:ac:fd:2e:58:1e:98:e9:da:64:7d:dd:6a:0d:15:33:23:5d:
+        b4:cc:f6:20:49:db:17:8c:75:bd:ab:61:fb:ee:25:76:df:c8:
+        6a:21:4e:ea:0a:f1:33:fa:57:ea:a9:61:18:e7:4e:33:85:83:
+        65:92:76:d4:9d:1e:76:e4:8b:68:b0:45:70:5c:50:49:4e:46:
+        77:63:0f:20:83:4d:9c:d7:dc:a2:f1:30:21:e4:b8:b7:01:df:
+        17:42:69:92:24:c5:81:57:85:ca:a8:5a:f4:00:86:4a:06:58:
+        3a:35:96:45:7f:fd:1d:3f:dc:dc:2a:1c:d2:ae:25:b6:ed:b6:
+        34:5d:fc:c0:e8:64:a2:44:35:eb:0e:38:17:ab:a6:da:45:3e:
+        98:c2:02:20:a6:02:6c:0d:b2:6d:65:f1:e7:57:59:dd:dc:ce:
+        b3:3a:d4:0f:9b:54:c8:42:93:66:30:c3:1d:fc:33:eb:19:c5:
+        10:7a:b0:f7
+-----BEGIN CERTIFICATE-----
+MIIEcDCCA1igAwIBAgIJAIz+EYMBU6aWMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD
+VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE
+ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU
+FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp
+ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTczMVoXDTI4MTEwNTE2MTczMVowgaYx
+CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0
+IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl
+cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq
+dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN
+jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0
+ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1
+JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6
+q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx
+qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo4GiMIGfMAkGA1UdEwQCMAAwLAYJ
+YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1Ud
+DgQWBBSfFHe/Pzq2yjiCQkgWLNrQy16H2DAfBgNVHSMEGDAWgBR7mtqPkJlOUtKs
+27MDUsqHpg0+DTAkBgNVHREEHTAbggkqLmJhci5jb22CDiou6Iqx5a2QLmNvLmpw
+MA0GCSqGSIb3DQEBBQUAA4IBAQBobWC+D5/lx6YhX64CwZ26XLjxaE0S415ajbBq
+DK7lz+Rg7zOE3GsTAMi+ldUYnhyz0wDiXB8UwKXl0SDToB2Z4GOgqQjAqoMmrP0u
+WB6Y6dpkfd1qDRUzI120zPYgSdsXjHW9q2H77iV238hqIU7qCvEz+lfqqWEY504z
+hYNlknbUnR525ItosEVwXFBJTkZ3Yw8gg02c19yi8TAh5Li3Ad8XQmmSJMWBV4XK
+qFr0AIZKBlg6NZZFf/0dP9zcKhzSriW27bY0XfzA6GSiRDXrDjgXq6baRT6YwgIg
+pgJsDbJtZfHnV1nd3M6zOtQPm1TIQpNmMMMd/DPrGcUQerD3
+-----END CERTIFICATE-----
diff --git a/src/java/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java b/src/java/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java
new file mode 100644
index 0000000..03bf14e
--- /dev/null
+++ b/src/java/org/apache/commons/httpclient/contrib/ssl/AuthSSLProtocolSocketFactory.java
@@ -0,0 +1,196 @@
+/*
+ * $Header$
+ * $Revision: 129 $
+ * $Date: 2007-11-14 19:21:33 -0800 (Wed, 14 Nov 2007) $
+ *
+ * ====================================================================
+ *
+ *  Copyright 2002-2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.httpclient.contrib.ssl;
+
+import org.apache.commons.ssl.HttpSecureProtocol;
+import org.apache.commons.ssl.KeyMaterial;
+import org.apache.commons.ssl.TrustMaterial;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+
+/**
+ * <p/>
+ * AuthSSLProtocolSocketFactory can be used to validate the identity of the HTTPS
+ * server against a list of trusted certificates and to authenticate to the HTTPS
+ * server using a private key.
+ * </p>
+ * <p/>
+ * <p/>
+ * AuthSSLProtocolSocketFactory will enable server authentication when supplied with
+ * a {@link java.security.KeyStore truststore} file containg one or several trusted certificates.
+ * The client secure socket will reject the connection during the SSL session handshake
+ * if the target HTTPS server attempts to authenticate itself with a non-trusted
+ * certificate.
+ * </p>
+ * <p/>
+ * <p/>
+ * Use JDK keytool utility to import a trusted certificate and generate a truststore file:
+ * <pre>
+ *     keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
+ *    </pre>
+ * </p>
+ * <p/>
+ * <p/>
+ * AuthSSLProtocolSocketFactory will enable client authentication when supplied with
+ * a {@link java.security.KeyStore keystore} file containg a private key/public certificate pair.
+ * The client secure socket will use the private key to authenticate itself to the target
+ * HTTPS server during the SSL session handshake if requested to do so by the server.
+ * The target HTTPS server will in its turn verify the certificate presented by the client
+ * in order to establish client's authenticity
+ * </p>
+ * <p/>
+ * <p/>
+ * Use the following sequence of actions to generate a keystore file
+ * </p>
+ * <ul>
+ * <li>
+ * <p/>
+ * Use JDK keytool utility to generate a new key
+ * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
+ * For simplicity use the same password for the key as that of the keystore
+ * </p>
+ * </li>
+ * <li>
+ * <p/>
+ * Issue a certificate signing request (CSR)
+ * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p/>
+ * Send the certificate request to the trusted Certificate Authority for signature.
+ * One may choose to act as her own CA and sign the certificate request using a PKI
+ * tool, such as OpenSSL.
+ * </p>
+ * </li>
+ * <li>
+ * <p/>
+ * Import the trusted CA root certificate
+ * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p/>
+ * Import the PKCS#7 file containg the complete certificate chain
+ * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p/>
+ * Verify the content the resultant keystore file
+ * <pre>keytool -list -v -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * </ul>
+ * <p/>
+ * Example of using custom protocol socket factory for a specific host:
+ * <pre>
+ *     Protocol authhttps = new Protocol("https",
+ *          new AuthSSLProtocolSocketFactory(
+ *              new URL("file:my.keystore"), "mypassword",
+ *              new URL("file:my.truststore"), "mypassword"), 443);
+ * <p/>
+ *     HttpClient client = new HttpClient();
+ *     client.getHostConfiguration().setHost("localhost", 443, authhttps);
+ *     // use relative url only
+ *     GetMethod httpget = new GetMethod("/");
+ *     client.executeMethod(httpget);
+ *     </pre>
+ * </p>
+ * <p/>
+ * Example of using custom protocol socket factory per default instead of the standard one:
+ * <pre>
+ *     Protocol authhttps = new Protocol("https",
+ *          new AuthSSLProtocolSocketFactory(
+ *              new URL("file:my.keystore"), "mypassword",
+ *              new URL("file:my.truststore"), "mypassword"), 443);
+ *     Protocol.registerProtocol("https", authhttps);
+ * <p/>
+ *     HttpClient client = new HttpClient();
+ *     GetMethod httpget = new GetMethod("https://localhost/");
+ *     client.executeMethod(httpget);
+ *     </pre>
+ * </p>
+ *
+ * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
+ *         <p/>
+ *         <p/>
+ *         DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ *         The component is provided as a reference material, which may be inappropriate
+ *         for use without additional customization.
+ *         </p>
+ */
+
+public class AuthSSLProtocolSocketFactory extends HttpSecureProtocol {
+
+    /**
+     * Constructor for AuthSSLProtocolSocketFactory. Either a keystore or truststore file
+     * must be given. Otherwise SSL context initialization error will result.
+     *
+     * @param keystoreUrl        URL of the keystore file. May be <tt>null</tt> if HTTPS client
+     *                           authentication is not to be used.
+     * @param keystorePassword   Password to unlock the keystore. IMPORTANT: this implementation
+     *                           assumes that the same password is used to protect the key and the keystore itself.
+     * @param truststoreUrl      URL of the truststore file. May be <tt>null</tt> if HTTPS server
+     *                           authentication is not to be used.
+     * @param truststorePassword Password to unlock the truststore.
+     */
+    public AuthSSLProtocolSocketFactory(final URL keystoreUrl,
+                                        final String keystorePassword,
+                                        final URL truststoreUrl,
+                                        final String truststorePassword)
+        throws GeneralSecurityException, IOException {
+
+        super();
+
+        // prepare key material
+        if (keystoreUrl != null) {
+            char[] ksPass = null;
+            if (keystorePassword != null) {
+                ksPass = keystorePassword.toCharArray();
+            }
+            KeyMaterial km = new KeyMaterial(keystoreUrl, ksPass);
+            super.setKeyMaterial(km);
+        }
+
+        // prepare trust material1
+        if (truststoreUrl != null) {
+            char[] tsPass = null;
+            if (truststorePassword != null) {
+                tsPass = truststorePassword.toCharArray();
+            }
+            TrustMaterial tm = new KeyMaterial(truststoreUrl, tsPass);
+            super.setTrustMaterial(tm);
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java b/src/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java
new file mode 100644
index 0000000..ab84dd1
--- /dev/null
+++ b/src/java/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java
@@ -0,0 +1,102 @@
+/*
+ * $Header$
+ * $Revision: 129 $
+ * $Date: 2007-11-14 19:21:33 -0800 (Wed, 14 Nov 2007) $
+ * 
+ * ====================================================================
+ *
+ *  Copyright 2002-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.httpclient.contrib.ssl;
+
+import org.apache.commons.ssl.HttpSecureProtocol;
+import org.apache.commons.ssl.TrustMaterial;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+
+/**
+ * <p/>
+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
+ * that accept self-signed certificates.
+ * </p>
+ * <p/>
+ * This socket factory SHOULD NOT be used for productive systems
+ * due to security reasons, unless it is a concious decision and
+ * you are perfectly aware of security implications of accepting
+ * self-signed certificates
+ * </p>
+ * <p/>
+ * <p/>
+ * Example of using custom protocol socket factory for a specific host:
+ * <pre>
+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ * <p/>
+ *     HttpClient client = new HttpClient();
+ *     client.getHostConfiguration().setHost("localhost", 443, easyhttps);
+ *     // use relative url only
+ *     GetMethod httpget = new GetMethod("/");
+ *     client.executeMethod(httpget);
+ *     </pre>
+ * </p>
+ * <p/>
+ * Example of using custom protocol socket factory per default instead of the standard one:
+ * <pre>
+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *     Protocol.registerProtocol("https", easyhttps);
+ * <p/>
+ *     HttpClient client = new HttpClient();
+ *     GetMethod httpget = new GetMethod("https://localhost/");
+ *     client.executeMethod(httpget);
+ *     </pre>
+ * </p>
+ *
+ * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
+ *         <p/>
+ *         <p/>
+ *         DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ *         The component is provided as a reference material, which may be inappropriate
+ *         for use without additional customization.
+ *         </p>
+ */
+
+public class EasySSLProtocolSocketFactory extends HttpSecureProtocol {
+
+    /**
+     * Constructor for EasySSLProtocolSocketFactory.
+     *
+     * @throws GeneralSecurityException GeneralSecurityException
+     * @throws IOException              IOException
+     */
+    public EasySSLProtocolSocketFactory()
+        throws GeneralSecurityException, IOException {
+        super();
+        super.useDefaultJavaCiphers();
+        super.setTrustMaterial(TrustMaterial.TRUST_ALL);
+        super.setCheckHostname(false);
+        super.setCheckExpiry(false);
+        super.setCheckCRL(false );
+	}
+
+}
diff --git a/src/java/org/apache/commons/httpclient/contrib/ssl/StrictSSLProtocolSocketFactory.java b/src/java/org/apache/commons/httpclient/contrib/ssl/StrictSSLProtocolSocketFactory.java
new file mode 100644
index 0000000..05e207d
--- /dev/null
+++ b/src/java/org/apache/commons/httpclient/contrib/ssl/StrictSSLProtocolSocketFactory.java
@@ -0,0 +1,131 @@
+/*
+ * $Header$
+ * $Revision: 129 $
+ * $Date: 2007-11-14 19:21:33 -0800 (Wed, 14 Nov 2007) $
+ *
+ * ====================================================================
+ *
+ *  Copyright 1999-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * [Additional notices, if required by prior licensing conditions]
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU Lesser General Public License Version 2 or later
+ * (the "LGPL"), in which case the provisions of the LGPL are 
+ * applicable instead of those above.  See terms of LGPL at
+ * <http://www.gnu.org/copyleft/lesser.txt>.
+ * If you wish to allow use of your version of this file only under 
+ * the terms of the LGPL and not to allow others to use your version
+ * of this file under the Apache Software License, indicate your 
+ * decision by deleting the provisions above and replace them with 
+ * the notice and other provisions required by the LGPL.  If you do 
+ * not delete the provisions above, a recipient may use your version 
+ * of this file under either the Apache Software License or the LGPL.
+ */
+
+package org.apache.commons.httpclient.contrib.ssl;
+
+import org.apache.commons.ssl.HttpSecureProtocol;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+/**
+ * A <code>SecureProtocolSocketFactory</code> that uses JSSE to create
+ * SSL sockets.  It will also support host name verification to help preventing
+ * man-in-the-middle attacks.  Host name verification is turned <b>on</b> by
+ * default but one will be able to turn it off, which might be a useful feature
+ * during development.  Host name verification will make sure the SSL sessions
+ * server host name matches with the the host name returned in the
+ * server certificates "Common Name" field of the "SubjectDN" entry.
+ *
+ * @author <a href="mailto:hauer at psicode.com">Sebastian Hauer</a>
+ *         <p/>
+ *         DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ *         The component is provided as a reference material, which may be inappropriate
+ *         for use without additional customization.
+ *         </p>
+ */
+public class StrictSSLProtocolSocketFactory extends HttpSecureProtocol {
+
+    /**
+     * Constructor for StrictSSLProtocolSocketFactory.
+     *
+     * @param verifyHostname The host name verification flag. If set to
+     *                       <code>true</code> the SSL sessions server host name will be compared
+     *                       to the host name returned in the server certificates "Common Name"
+     *                       field of the "SubjectDN" entry.  If these names do not match a
+     *                       Exception is thrown to indicate this.  Enabling host name verification
+     *                       will help to prevent from man-in-the-middle attacks.  If set to
+     *                       <code>false</code> host name verification is turned off.
+     *                       <p/>
+     *                       Code sample:
+     *                       <p/>
+     *                       <blockquote>
+     *                       Protocol stricthttps = new Protocol(
+     *                       "https", new StrictSSLProtocolSocketFactory(true), 443);
+     *                       <p/>
+     *                       HttpClient client = new HttpClient();
+     *                       client.getHostConfiguration().setHost("localhost", 443, stricthttps);
+     *                       </blockquote>
+     */
+    public StrictSSLProtocolSocketFactory(boolean verifyHostname)
+        throws GeneralSecurityException, IOException {
+        super();
+        super.setCheckHostname(verifyHostname);
+    }
+
+    /**
+     * Constructor for StrictSSLProtocolSocketFactory.
+     * Host name verification will be enabled by default.
+     */
+    public StrictSSLProtocolSocketFactory()
+        throws GeneralSecurityException, IOException {
+        this(true);
+    }
+
+    /**
+     * Set the host name verification flag.
+     *
+     * @param verifyHostname The host name verification flag. If set to
+     *                       <code>true</code> the SSL sessions server host name will be compared
+     *                       to the host name returned in the server certificates "Common Name"
+     *                       field of the "SubjectDN" entry.  If these names do not match a
+     *                       Exception is thrown to indicate this.  Enabling host name verification
+     *                       will help to prevent from man-in-the-middle attacks.  If set to
+     *                       <code>false</code> host name verification is turned off.
+     */
+    public void setHostnameVerification(boolean verifyHostname) {
+        super.setCheckHostname(verifyHostname);
+    }
+
+    /**
+     * Gets the status of the host name verification flag.
+     *
+     * @return Host name verification flag.  Either <code>true</code> if host
+     *         name verification is turned on, or <code>false</code> if host name
+     *         verification is turned off.
+     */
+    public boolean getHostnameVerification() {
+        return super.getCheckHostname();
+    }
+
+}
diff --git a/src/java/org/apache/commons/httpclient/contrib/ssl/TrustSSLProtocolSocketFactory.java b/src/java/org/apache/commons/httpclient/contrib/ssl/TrustSSLProtocolSocketFactory.java
new file mode 100644
index 0000000..fc1a847
--- /dev/null
+++ b/src/java/org/apache/commons/httpclient/contrib/ssl/TrustSSLProtocolSocketFactory.java
@@ -0,0 +1,199 @@
+/*
+ * ====================================================================
+ *
+ *  Copyright 1999-2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.httpclient.contrib.ssl;
+
+import org.apache.commons.ssl.HttpSecureProtocol;
+import org.apache.commons.ssl.KeyMaterial;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+/**
+ * <p/>
+ * TrustSSLProtocolSocketFactory allows you exercise full control over the
+ * HTTPS server certificates you are going to trust.  Instead of relying
+ * on the Certificate Authorities already present in "jre/lib/security/cacerts",
+ * TrustSSLProtocolSocketFactory only trusts the public certificates you provide
+ * to its constructor.
+ * </p>
+ * <p/>
+ * TrustSSLProtocolSocketFactory can be used to create SSL {@link Socket}s
+ * that accepts self-signed certificates.  Unlike EasySSLProtocolSocketFactory,
+ * TrustSSLProtocolSocketFactory can be used in production.  This is because
+ * it forces you to pre-install the self-signed certificate you are going to
+ * trust locally.
+ * <p/>
+ * TrustSSLProtocolSocketFactory can parse both Java Keystore Files (*.jks)
+ * and base64 PEM encoded public certificates (*.pem).
+ * </p>
+ * <p/>
+ * Example of using TrustSSLProtocolSocketFactory
+ * <pre>
+ * 1.  First we must find the certificate we want to trust.  In this example
+ *     we'll use gmail.google.com's certificate.
+ * <p/>
+ *   openssl s_client -showcerts -connect gmail.google.com:443
+ * <p/>
+ * 2.  Cut & paste into a "cert.pem" any certificates you are interested in
+ *     trusting in accordance with your security policies.  In this example I'll
+ *     actually use the current "gmail.google.com" certificate (instead of the
+ *     Thawte CA certificate that signed the gmail certificate - that would be
+ *     too boring) - but it expires on June 7th, 2006, so this example won't be
+ *     useful for very long!
+ * <p/>
+ * Here's what my "cert.pem" file looks like:
+ * <p/>
+ * -----BEGIN CERTIFICATE-----
+ * MIIDFjCCAn+gAwIBAgIDP3PeMA0GCSqGSIb3DQEBBAUAMEwxCzAJBgNVBAYTAlpB
+ * MSUwIwYDVQQKExxUaGF3dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQuMRYwFAYDVQQD
+ * Ew1UaGF3dGUgU0dDIENBMB4XDTA1MDYwNzIyMTI1N1oXDTA2MDYwNzIyMTI1N1ow
+ * ajELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1v
+ * dW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBJbmMxGTAXBgNVBAMTEGdtYWls
+ * Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALoRiWYW0hZw
+ * 9TSn3s9912syZg1CP2TaC86PU1Ao2qf3pVu7Mx10Wl8W+aKZrQlvrYjTwku4sEh+
+ * 9uI+gWnfmCd0OyVcXr1eFOGCYiiyaPv79Wtb0m0d8GuiRSJhYkZGzGlgFViws2vR
+ * BAMCD2fdp7WGJUVGYOO+s52dgAMUHQXxAgMBAAGjgecwgeQwKAYDVR0lBCEwHwYI
+ * KwYBBQUHAwEGCCsGAQUFBwMCBglghkgBhvhCBAEwNgYDVR0fBC8wLTAroCmgJ4Yl
+ * aHR0cDovL2NybC50aGF3dGUuY29tL1RoYXd0ZVNHQ0NBLmNybDByBggrBgEFBQcB
+ * AQRmMGQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnRoYXd0ZS5jb20wPgYIKwYB
+ * BQUHMAKGMmh0dHA6Ly93d3cudGhhd3RlLmNvbS9yZXBvc2l0b3J5L1RoYXd0ZV9T
+ * R0NfQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEEBQADgYEAktM1l1cV
+ * ebi+Uo6fCE/eLnvvY6QbNNCsU5Pi9B5E1BlEUG+AGpgzE2cSPw1N4ZZb+2AWWwjx
+ * H8/IrJ143KZZXM49ri3Z2e491Jj8qitrMauT7/hb16Jw6I02/74/do4TtHu/Eifr
+ * EZCaSOobSHGeufHjlqlC3ehC4Bx4mLexIMk=
+ * -----END CERTIFICATE-----
+ * <p/>
+ * 3.  Run "openssl x509" to analyze the certificate more deeply.  This helps
+ *     us answer questions like "Do we really want to trust it?  When does it
+ *     expire? What's the value of the CN (Common Name) field?".
+ * <p/>
+ *     "openssl x509" is also super cool, and will impress all your friends,
+ *     coworkers, family, and that cute girl at the starbucks.   :-)
+ * <p/>
+ *     If you dig through "man x509" you'll find this example.  Run it:
+ * <p/>
+ *    openssl x509 -in cert.pem -noout -text
+ * <p/>
+ * 4.  Rename "cert.pem" to "gmail.pem" so that step 5 works.
+ * <p/>
+ * 5.  Setup the TrustSSLProtocolSocketFactory to trust "gmail.google.com"
+ *     for URLS of the form "https-gmail://" - but don't trust anything else
+ *     when using "https-gmail://":
+ * <p/>
+ *     TrustSSLProtocolSocketFactory sf = new TrustSSLProtocolSocketFactory( "/path/to/gmail.pem" );
+ *     Protocol trustHttps = new Protocol("https-gmail", sf, 443);
+ *     Protocol.registerProtocol("https-gmail", trustHttps);
+ * <p/>
+ *     HttpClient client = new HttpClient();
+ *     GetMethod httpget = new GetMethod("https-gmail://gmail.google.com/");
+ *     client.executeMethod(httpget);
+ * <p/>
+ * 6.  Notice that "https-gmail://" cannot connect to "www.wellsfargo.com" -
+ *     the server's certificate isn't trusted!  It would still work using
+ *     regular "https://" because Java would use the "jre/lib/security/cacerts"
+ *     file.
+ * <p/>
+ *     httpget = new GetMethod("https-gmail://www.wellsfargo.com/");
+ *     client.executeMethod(httpget);
+ * <p/>
+ * javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
+ * <p/>
+ * <p/>
+ * 7.  Of course "https-gmail://" cannot connect to hosts where the CN field
+ *     in the certificate doesn't match the hostname.  The same is supposed to
+ *     be true of regular "https://", but HTTPClient is a bit lenient.
+ * <p/>
+ *     httpget = new GetMethod("https-gmail://gmail.com/");
+ *     client.executeMethod(httpget);
+ * <p/>
+ * javax.net.ssl.SSLException: hostname in certificate didn't match: <gmail.com> != <gmail.google.com>
+ * <p/>
+ * <p/>
+ * 8.  You can use "*.jks" files instead of "*.pem" if you prefer.  Use the 2nd constructor
+ *     in that case to pass along the JKS password:
+ * <p/>
+ *   new TrustSSLProtocolSocketFactory( "/path/to/gmail.jks", "my_password".toCharArray() );
+ * <p/>
+ * </pre>
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ *         <p/>
+ *         <p/>
+ *         DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ *         The component is provided as a reference material, which may be inappropriate
+ *         for use without additional customization.
+ *         </p>
+ * @since 17-Feb-2006
+ */
+
+public class TrustSSLProtocolSocketFactory extends HttpSecureProtocol {
+
+    /**
+     * @param pathToTrustStore Path to either a ".jks" Java Key Store, or a
+     *                         ".pem" base64 encoded certificate.  If it's a
+     *                         ".pem" base64 certificate, the file must start
+     *                         with "------BEGIN CERTIFICATE-----", and must end
+     *                         with "-------END CERTIFICATE--------".
+     */
+    public TrustSSLProtocolSocketFactory(String pathToTrustStore)
+        throws GeneralSecurityException, IOException {
+        this(pathToTrustStore, null);
+    }
+
+    /**
+     * @param pathToTrustStore Path to either a ".jks" Java Key Store, or a
+     *                         ".pem" base64 encoded certificate.  If it's a
+     *                         ".pem" base64 certificate, the file must start
+     *                         with "------BEGIN CERTIFICATE-----", and must end
+     *                         with "-------END CERTIFICATE--------".
+     * @param password         Password to open the ".jks" file.  If "truststore"
+     *                         is a ".pem" file, then password can be null; if
+     *                         password isn't null and we're using a ".pem" file,
+     *                         then technically, this becomes the password to
+     *                         open up the special in-memory keystore we create
+     *                         to hold the ".pem" file, but it's not important at
+     *                         all.
+     * @throws CertificateException
+     * @throws KeyStoreException
+     * @throws IOException
+     * @throws NoSuchAlgorithmException
+     * @throws KeyManagementException
+     */
+    public TrustSSLProtocolSocketFactory(String pathToTrustStore, char[] password)
+        throws GeneralSecurityException, IOException {
+        super();
+        KeyMaterial km = new KeyMaterial(pathToTrustStore, password);
+        super.setTrustMaterial(km);
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/ASN1Structure.java b/src/java/org/apache/commons/ssl/ASN1Structure.java
new file mode 100644
index 0000000..6dd69ca
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/ASN1Structure.java
@@ -0,0 +1,112 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/ASN1Structure.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.util.Hex;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+class ASN1Structure {
+    List derIntegers = new LinkedList();
+    Set oids = new TreeSet();
+    String oid1;
+    String oid2;
+    String oid3;
+    byte[] salt;
+    byte[] iv;
+    int iterationCount;
+    int keySize;
+    byte[] bigPayload;
+    byte[] smallPayload;
+
+    public String toString() {
+        StringBuffer buf = new StringBuffer(256);
+        buf.append("------ ASN.1 PKCS Structure ------");
+        buf.append("\noid1:    ");
+        buf.append(oid1);
+        if (oid2 != null) {
+            buf.append("\noid2:    ");
+            buf.append(oid2);
+        }
+        buf.append("\nsalt:   ");
+        if (salt != null) {
+            buf.append(Hex.encode(salt));
+        } else {
+            buf.append("[null]");
+        }
+        buf.append("\nic:      ");
+        buf.append(Integer.toString(iterationCount));
+        if (keySize != 0) {
+            buf.append("\nkeySize: ");
+            buf.append(Integer.toString(keySize * 8));
+        }
+        if (oid2 != null) {
+            buf.append("\noid3:    ");
+            buf.append(oid3);
+        }
+        if (oid2 != null) {
+            buf.append("\niv:      ");
+            if (iv != null) {
+                buf.append(Hex.encode(iv));
+            } else {
+                buf.append("[null]");
+            }
+        }
+        if (bigPayload != null) {
+            buf.append("\nbigPayload-length:   ");
+            buf.append(bigPayload.length);
+        }
+        if (smallPayload != null) {
+            buf.append("\nsmallPayload-length: ");
+            buf.append(smallPayload.length);
+        }
+        if (!oids.isEmpty()) {
+            Iterator it = oids.iterator();
+            buf.append("\nAll oids:");
+            while (it.hasNext()) {
+                buf.append("\n");
+                buf.append((String) it.next());
+            }
+        }
+        return buf.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/ASN1Util.java b/src/java/org/apache/commons/ssl/ASN1Util.java
new file mode 100644
index 0000000..c73a224
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/ASN1Util.java
@@ -0,0 +1,211 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/ASN1Util.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.asn1.ASN1InputStream;
+import org.apache.commons.ssl.asn1.DEREncodable;
+import org.apache.commons.ssl.asn1.DERInteger;
+import org.apache.commons.ssl.asn1.DERObjectIdentifier;
+import org.apache.commons.ssl.asn1.DEROctetString;
+import org.apache.commons.ssl.asn1.DERPrintableString;
+import org.apache.commons.ssl.asn1.DERSequence;
+import org.apache.commons.ssl.asn1.DERSet;
+import org.apache.commons.ssl.asn1.DERTaggedObject;
+import org.apache.commons.ssl.util.Hex;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+public class ASN1Util {
+    public static boolean DEBUG = false;
+    public final static BigInteger BIGGEST =
+        new BigInteger(Integer.toString(Integer.MAX_VALUE));
+
+    public static ASN1Structure analyze(byte[] asn1)
+        throws IOException {
+        ASN1InputStream asn = new ASN1InputStream(asn1);
+        DERSequence seq = (DERSequence) asn.readObject();
+        ASN1Structure pkcs8 = new ASN1Structure();
+        ASN1Util.analyze(seq, pkcs8, 0);
+        return pkcs8;
+    }
+
+    public static void main(String[] args) throws Exception {
+        DEBUG = true;
+        FileInputStream in = new FileInputStream(args[0]);
+        byte[] bytes = Util.streamToBytes(in);
+        List list = PEMUtil.decode(bytes);
+        if (!list.isEmpty()) {
+            bytes = ((PEMItem) list.get(0)).getDerBytes();
+        }
+
+        ASN1Structure asn1 = analyze(bytes);
+        while (asn1.bigPayload != null) {
+            System.out.println("------------------------------------------");
+            System.out.println(asn1);
+            System.out.println("------------------------------------------");
+            asn1 = analyze(asn1.bigPayload);
+        }
+    }
+
+
+    public static void analyze(DEREncodable seq, ASN1Structure pkcs8,
+                               int depth) {
+        String tag = null;
+        if (depth >= 2) {
+            pkcs8.derIntegers = null;
+        }
+        Enumeration en;
+        if (seq instanceof DERSequence) {
+            en = ((DERSequence) seq).getObjects();
+        } else if (seq instanceof DERSet) {
+            en = ((DERSet) seq).getObjects();
+        } else if (seq instanceof DERTaggedObject) {
+            DERTaggedObject derTag = (DERTaggedObject) seq;
+            tag = Integer.toString(derTag.getTagNo());
+            Vector v = new Vector();
+            v.add(derTag.getObject());
+            en = v.elements();
+        } else {
+            throw new IllegalArgumentException("DEREncodable must be one of: DERSequence, DERSet, DERTaggedObject");
+        }
+        while (en != null && en.hasMoreElements()) {
+            DEREncodable obj = (DEREncodable) en.nextElement();
+            if (!(obj instanceof DERSequence) &&
+                !(obj instanceof DERSet) &&
+                !(obj instanceof DERTaggedObject)) {
+                String str = obj.toString();
+                String name = obj.getClass().getName();
+                name = name.substring(name.lastIndexOf('.') + 1);
+                if (tag != null) {
+                    name = " [tag=" + tag + "] " + name;
+                }
+                for (int i = 0; i < depth; i++) {
+                    name = "  " + name;
+                }
+                if (obj instanceof DERInteger) {
+                    DERInteger dInt = (DERInteger) obj;
+                    if (pkcs8.derIntegers != null) {
+                        pkcs8.derIntegers.add(dInt);
+                    }
+                    BigInteger big = dInt.getValue();
+                    int intValue = big.intValue();
+                    if (BIGGEST.compareTo(big) >= 0 && intValue > 0) {
+                        if (pkcs8.iterationCount == 0) {
+                            pkcs8.iterationCount = intValue;
+                        } else if (pkcs8.keySize == 0) {
+                            pkcs8.keySize = intValue;
+                        }
+                    }
+                    str = dInt.getValue().toString();
+                } else if (obj instanceof DERObjectIdentifier) {
+                    DERObjectIdentifier id = (DERObjectIdentifier) obj;
+                    str = id.getId();
+                    pkcs8.oids.add(str);
+                    if (pkcs8.oid1 == null) {
+                        pkcs8.oid1 = str;
+                    } else if (pkcs8.oid2 == null) {
+                        pkcs8.oid2 = str;
+                    } else if (pkcs8.oid3 == null) {
+                        pkcs8.oid3 = str;
+                    }
+                } else {
+                    pkcs8.derIntegers = null;
+                    if (obj instanceof DEROctetString) {
+                        DEROctetString oct = (DEROctetString) obj;
+                        byte[] octets = oct.getOctets();
+                        int len = Math.min(10, octets.length);
+                        boolean probablyBinary = false;
+                        for (int i = 0; i < len; i++) {
+                            byte b = octets[i];
+                            boolean isBinary = b > 128 || b < 0;
+                            if (isBinary) {
+                                probablyBinary = true;
+                                break;
+                            }
+                        }
+                        if (probablyBinary && octets.length > 64) {
+                            if (pkcs8.bigPayload == null) {
+                                pkcs8.bigPayload = octets;
+                            }
+                            str = "probably binary";
+                        } else {
+                            str = Hex.encode(octets);
+                            if (octets.length <= 64) {
+                                if (octets.length % 8 == 0) {
+                                    if (pkcs8.salt == null) {
+                                        pkcs8.salt = octets;
+                                    } else if (pkcs8.iv == null) {
+                                        pkcs8.iv = octets;
+                                    }
+                                } else {
+                                    if (pkcs8.smallPayload == null) {
+                                        pkcs8.smallPayload = octets;
+                                    }
+                                }
+                            }
+                        }
+                        str += " (length=" + octets.length + ")";
+                    } else if (obj instanceof DERPrintableString) {
+                        DERPrintableString dps = (DERPrintableString) obj;
+                        str = dps.getString();
+                    }
+                }
+
+                if (DEBUG) {
+                    System.out.println(name + ": [" + str + "]");
+                }
+            } else {
+                if (tag != null && DEBUG) {
+                    String name = obj.getClass().getName();
+                    name = name.substring(name.lastIndexOf('.') + 1);
+                    name = " [tag=" + tag + "] " + name;
+                    for (int i = 0; i < depth; i++) {
+                        name = "  " + name;
+                    }
+                    System.out.println(name);
+                }
+                analyze(obj, pkcs8, depth + 1);
+            }
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/Base64.java b/src/java/org/apache/commons/ssl/Base64.java
new file mode 100644
index 0000000..aac382f
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Base64.java
@@ -0,0 +1,535 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Base64.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+/**
+ * Provides Base64 encoding and decoding as defined by RFC 2045.
+ * <p/>
+ * <p>This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite>
+ * from RFC 2045 <cite>Multipurpose Internet Mail Extensions (MIME) Part One:
+ * Format of Internet Message Bodies</cite> by Freed and Borenstein.</p>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Base64.java 121 2007-11-14 05:26:57Z julius $
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * @since 1.0-dev
+ */
+public class Base64 {
+
+    /**
+     * Chunk size per RFC 2045 section 6.8.
+     * <p/>
+     * <p>The character limit does not count the trailing CRLF, but counts
+     * all other characters, including any equal signs.</p>
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
+     */
+    static final int CHUNK_SIZE = 76;
+
+    /**
+     * Chunk separator per RFC 2045 section 2.1.
+     *
+     * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
+     */
+    static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes();
+
+    /** The base length. */
+    static final int BASELENGTH = 255;
+
+    /** Lookup length. */
+    static final int LOOKUPLENGTH = 64;
+
+    /** Used to calculate the number of bits in a byte. */
+    static final int EIGHTBIT = 8;
+
+    /** Used when encoding something which has fewer than 24 bits. */
+    static final int SIXTEENBIT = 16;
+
+    /** Used to determine how many bits data contains. */
+    static final int TWENTYFOURBITGROUP = 24;
+
+    /** Used to get the number of Quadruples. */
+    static final int FOURBYTE = 4;
+
+    /** Used to test the sign of a byte. */
+    static final int SIGN = -128;
+
+    /** Byte used to pad output. */
+    static final byte PAD = (byte) '=';
+
+    /**
+     * Contains the Base64 values <code>0</code> through <code>63</code> accessed by using character encodings as
+     * indices.
+     * <p/>
+     * For example, <code>base64Alphabet['+']</code> returns <code>62</code>.
+     * </p>
+     * <p/>
+     * The value of undefined encodings is <code>-1</code>.
+     * </p>
+     */
+    private static byte[] base64Alphabet = new byte[BASELENGTH];
+
+    /**
+     * <p/>
+     * Contains the Base64 encodings <code>A</code> through <code>Z</code>, followed by <code>a</code> through
+     * <code>z</code>, followed by <code>0</code> through <code>9</code>, followed by <code>+</code>, and
+     * <code>/</code>.
+     * </p>
+     * <p/>
+     * This array is accessed by using character values as indices.
+     * </p>
+     * <p/>
+     * For example, <code>lookUpBase64Alphabet[62] </code> returns <code>'+'</code>.
+     * </p>
+     */
+    private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
+
+    // Populating the lookup and character arrays
+    static {
+        for (int i = 0; i < BASELENGTH; i++) {
+            base64Alphabet[i] = (byte) -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--) {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--) {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+        for (int i = '9'; i >= '0'; i--) {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+
+        for (int i = 0; i <= 25; i++) {
+            lookUpBase64Alphabet[i] = (byte) ('A' + i);
+        }
+
+        for (int i = 26, j = 0; i <= 51; i++, j++) {
+            lookUpBase64Alphabet[i] = (byte) ('a' + j);
+        }
+
+        for (int i = 52, j = 0; i <= 61; i++, j++) {
+            lookUpBase64Alphabet[i] = (byte) ('0' + j);
+        }
+
+        lookUpBase64Alphabet[62] = (byte) '+';
+        lookUpBase64Alphabet[63] = (byte) '/';
+    }
+
+    /**
+     * Returns whether or not the <code>octect</code> is in the base 64 alphabet.
+     *
+     * @param b The value to test
+     * @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
+     */
+    public static boolean isBase64(byte b) {
+        return (b == PAD) || (b >= 0 && base64Alphabet[b] >= 0);
+    }
+
+    /**
+     * Tests a given byte array to see if it contains
+     * only valid characters within the Base64 alphabet.
+     *
+     * @param arrayOctect byte array to test
+     * @return <code>true</code> if all bytes are valid characters in the Base64
+     *         alphabet or if the byte array is empty; false, otherwise
+     */
+    public static boolean isArrayByteBase64(byte[] arrayOctect) {
+
+        arrayOctect = discardWhitespace(arrayOctect);
+
+        int length = arrayOctect.length;
+        if (length == 0) {
+            // shouldn't a 0 length array be valid base64 data?
+            // return false;
+            return true;
+        }
+        for (int i = 0; i < length; i++) {
+            if (!isBase64(arrayOctect[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm but
+     * does not chunk the output.
+     *
+     * @param binaryData binary data to encode
+     * @return Base64 characters
+     */
+    public static byte[] encodeBase64(byte[] binaryData) {
+        return encodeBase64(binaryData, false);
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm and chunks
+     * the encoded output into 76 character blocks
+     *
+     * @param binaryData binary data to encode
+     * @return Base64 characters chunked in 76 character blocks
+     */
+    public static byte[] encodeBase64Chunked(byte[] binaryData) {
+        return encodeBase64(binaryData, true);
+    }
+
+
+    /**
+     * Decodes an Object using the base64 algorithm.  This method
+     * is provided in order to satisfy the requirements of the
+     * Decoder interface, and will throw a DecoderException if the
+     * supplied object is not of type byte[].
+     *
+     * @param pObject Object to decode
+     * @return An object (of type byte[]) containing the
+     *         binary data which corresponds to the byte[] supplied.
+     * @throws IllegalArgumentException if the parameter supplied is not
+     *                                  of type byte[]
+     */
+    public Object decode(Object pObject) throws IllegalArgumentException {
+        if (!(pObject instanceof byte[])) {
+            throw new IllegalArgumentException("Parameter supplied to Base64 decode is not a byte[]");
+        }
+        return decode((byte[]) pObject);
+    }
+
+    /**
+     * Decodes a byte[] containing containing
+     * characters in the Base64 alphabet.
+     *
+     * @param pArray A byte array containing Base64 character data
+     * @return a byte array containing binary data
+     */
+    public byte[] decode(byte[] pArray) {
+        return decodeBase64(pArray);
+    }
+
+    /**
+     * Encodes binary data using the base64 algorithm, optionally
+     * chunking the output into 76 character blocks.
+     *
+     * @param binaryData Array containing binary data to encode.
+     * @param isChunked  if <code>true</code> this encoder will chunk
+     *                   the base64 output into 76 character blocks
+     * @return Base64-encoded data.
+     */
+    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
+        int lengthDataBits = binaryData.length * EIGHTBIT;
+        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+        byte encodedData[];
+        int encodedDataLength;
+        int nbrChunks = 0;
+
+        if (fewerThan24bits != 0) {
+            //data not divisible by 24 bit
+            encodedDataLength = (numberTriplets + 1) * 4;
+        } else {
+            // 16 or 8 bit
+            encodedDataLength = numberTriplets * 4;
+        }
+
+        // If the output is to be "chunked" into 76 character sections,
+        // for compliance with RFC 2045 MIME, then it is important to
+        // allow for extra length to account for the separator(s)
+        if (isChunked) {
+
+            nbrChunks =
+                (CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
+            encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
+        }
+
+        encodedData = new byte[encodedDataLength];
+
+        byte k, l, b1, b2, b3;
+        int dataIndex;
+        int i;
+        int encodedIndex = 0;
+        int nextSeparatorIndex = CHUNK_SIZE;
+        int chunksSoFar = 0;
+
+        //log.debug("number of triplets = " + numberTriplets);
+        for (i = 0; i < numberTriplets; i++) {
+            dataIndex = i * 3;
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            b3 = binaryData[dataIndex + 2];
+
+            //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
+
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 =
+                ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 =
+                ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+            byte val3 =
+                ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
+
+            encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
+            //log.debug( "val2 = " + val2 );
+            //log.debug( "k4   = " + (k<<4) );
+            //log.debug(  "vak  = " + (val2 | (k<<4)) );
+            encodedData[encodedIndex + 1] =
+                lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex + 2] =
+                lookUpBase64Alphabet[(l << 2) | val3];
+            encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
+
+            encodedIndex += 4;
+
+            // If we are chunking, let's put a chunk separator down.
+            if (isChunked) {
+                // this assumes that CHUNK_SIZE % 4 == 0
+                if (encodedIndex == nextSeparatorIndex) {
+                    System.arraycopy(CHUNK_SEPARATOR,
+                        0,
+                        encodedData,
+                        encodedIndex,
+                        CHUNK_SEPARATOR.length);
+                    chunksSoFar++;
+                    nextSeparatorIndex =
+                        (CHUNK_SIZE * (chunksSoFar + 1)) +
+                        (chunksSoFar * CHUNK_SEPARATOR.length);
+                    encodedIndex += CHUNK_SEPARATOR.length;
+                }
+            }
+        }
+
+        // form integral number of 6-bit groups
+        dataIndex = i * 3;
+
+        if (fewerThan24bits == EIGHTBIT) {
+            b1 = binaryData[dataIndex];
+            k = (byte) (b1 & 0x03);
+            //log.debug("b1=" + b1);
+            //log.debug("b1<<2 = " + (b1>>2) );
+            byte val1 =
+                ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
+            encodedData[encodedIndex + 2] = PAD;
+            encodedData[encodedIndex + 3] = PAD;
+        } else if (fewerThan24bits == SIXTEENBIT) {
+
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 =
+                ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 =
+                ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+
+            encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex + 1] =
+                lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
+            encodedData[encodedIndex + 3] = PAD;
+        }
+
+        if (isChunked) {
+            // we also add a separator to the end of the final chunk.
+            if (chunksSoFar < nbrChunks) {
+                System.arraycopy(CHUNK_SEPARATOR,
+                    0,
+                    encodedData,
+                    encodedDataLength - CHUNK_SEPARATOR.length,
+                    CHUNK_SEPARATOR.length);
+            }
+        }
+
+        return encodedData;
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param base64Data Byte array containing Base64 data
+     * @return Array containing decoded data.
+     */
+    public static byte[] decodeBase64(byte[] base64Data) {
+        // RFC 2045 requires that we discard ALL non-Base64 characters
+        base64Data = discardNonBase64(base64Data);
+
+        // handle the edge case, so we don't have to worry about it later
+        if (base64Data.length == 0) {
+            return new byte[0];
+        }
+
+        int numberQuadruple = base64Data.length / FOURBYTE;
+        byte decodedData[];
+        byte b1, b2, b3, b4, marker0, marker1;
+
+        // Throw away anything not in base64Data
+        int dataIndex;
+        int encodedIndex = 0;
+        {
+            // this sizes the output array properly - rlw
+            int lastData = base64Data.length;
+            // ignore the '=' padding
+            while (base64Data[lastData - 1] == PAD) {
+                if (--lastData == 0) {
+                    return new byte[0];
+                }
+            }
+            decodedData = new byte[lastData - numberQuadruple];
+        }
+
+        for (int i = 0; i < numberQuadruple; i++) {
+            dataIndex = i * 4;
+            marker0 = base64Data[dataIndex + 2];
+            marker1 = base64Data[dataIndex + 3];
+
+            b1 = base64Alphabet[base64Data[dataIndex]];
+            b2 = base64Alphabet[base64Data[dataIndex + 1]];
+
+            if (marker0 != PAD && marker1 != PAD) {
+                //No PAD e.g 3cQl
+                b3 = base64Alphabet[marker0];
+                b4 = base64Alphabet[marker1];
+
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex + 1] =
+                    (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+                decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
+            } else if (marker0 == PAD) {
+                //Two PAD e.g. 3c[Pad][Pad]
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+            } else // if ( marker1 == PAD ) (always true at this point)
+            {
+                //One PAD e.g. 3cQ[Pad]
+                b3 = base64Alphabet[marker0];
+
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex + 1] =
+                    (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            }
+            encodedIndex += 3;
+        }
+        return decodedData;
+    }
+
+    /**
+     * Discards any whitespace from a base-64 encoded block.
+     *
+     * @param data The base-64 encoded data to discard the whitespace
+     *             from.
+     * @return The data, less whitespace (see RFC 2045).
+     */
+    static byte[] discardWhitespace(byte[] data) {
+        byte groomedData[] = new byte[data.length];
+        int bytesCopied = 0;
+
+        for (int i = 0; i < data.length; i++) {
+            switch (data[i]) {
+                case (byte) ' ':
+                case (byte) '\n':
+                case (byte) '\r':
+                case (byte) '\t':
+                    break;
+                default:
+                    groomedData[bytesCopied++] = data[i];
+            }
+        }
+
+        byte packedData[] = new byte[bytesCopied];
+
+        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
+
+        return packedData;
+    }
+
+    /**
+     * Discards any characters outside of the base64 alphabet, per
+     * the requirements on page 25 of RFC 2045 - "Any characters
+     * outside of the base64 alphabet are to be ignored in base64
+     * encoded data."
+     *
+     * @param data The base-64 encoded data to groom
+     * @return The data, less non-base64 characters (see RFC 2045).
+     */
+    static byte[] discardNonBase64(byte[] data) {
+        byte groomedData[] = new byte[data.length];
+        int bytesCopied = 0;
+
+        for (int i = 0; i < data.length; i++) {
+            if (isBase64(data[i])) {
+                groomedData[bytesCopied++] = data[i];
+            }
+        }
+
+        byte packedData[] = new byte[bytesCopied];
+
+        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
+
+        return packedData;
+    }
+
+    // Implementation of the Encoder Interface
+
+    /**
+     * Encodes an Object using the base64 algorithm.  This method
+     * is provided in order to satisfy the requirements of the
+     * Encoder interface, and will throw an EncoderException if the
+     * supplied object is not of type byte[].
+     *
+     * @param pObject Object to encode
+     * @return An object (of type byte[]) containing the
+     *         base64 encoded data which corresponds to the byte[] supplied.
+     * @throws IllegalArgumentException if the parameter supplied is not
+     *                                  of type byte[]
+     */
+    public Object encode(Object pObject) throws IllegalArgumentException {
+        if (!(pObject instanceof byte[])) {
+            throw new IllegalArgumentException("Parameter supplied to Base64 encode is not a byte[]");
+        }
+        return encode((byte[]) pObject);
+    }
+
+    /**
+     * Encodes a byte[] containing binary data, into a byte[] containing
+     * characters in the Base64 alphabet.
+     *
+     * @param pArray a byte array containing binary data
+     * @return A byte array containing only Base64 character data
+     */
+    public byte[] encode(byte[] pArray) {
+        return encodeBase64(pArray, false);
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/Base64InputStream.java b/src/java/org/apache/commons/ssl/Base64InputStream.java
new file mode 100644
index 0000000..ef55f64
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Base64InputStream.java
@@ -0,0 +1,120 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Base64InputStream.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class Base64InputStream extends FilterInputStream {
+    private final static byte[] LINE_ENDING =
+        System.getProperty("line.separator").getBytes();
+
+    final boolean decodeMode;
+
+    byte[] currentLine = null;
+    int pos = 0;
+
+    public Base64InputStream(InputStream base64, boolean decodeMode) {
+        super(base64);
+        this.decodeMode = decodeMode;
+    }
+
+    public int read() throws IOException {
+        getLine();
+        if (currentLine == null) {
+            return -1;
+        } else {
+            byte b = currentLine[pos++];
+            if (pos >= currentLine.length) {
+                currentLine = null;
+            }
+            return b;
+        }
+    }
+
+    public int read(byte b[], int off, int len) throws IOException {
+        if (b == null) {
+            throw new NullPointerException();
+        } else if ((off < 0) || (off > b.length) || (len < 0) ||
+                   ((off + len) > b.length) || ((off + len) < 0)) {
+            throw new IndexOutOfBoundsException();
+        } else if (len == 0) {
+            return 0;
+        }
+
+        getLine();
+        if (currentLine == null) {
+            return -1;
+        }
+        int size = Math.min(currentLine.length - pos, len);
+        System.arraycopy(currentLine, pos, b, off, size);
+        if (size >= currentLine.length - pos) {
+            currentLine = null;
+        } else {
+            pos += size;
+        }
+        return size;
+    }
+
+    private void getLine() throws IOException {
+        if (currentLine == null) {
+            if (decodeMode) {
+                String line = Util.readLine(in);
+                if (line != null) {
+                    byte[] b = line.getBytes();
+                    currentLine = Base64.decodeBase64(b);
+                    pos = 0;
+                }
+            } else {
+                // It will expand to 64 bytes (16 * 4) after base64 encoding!
+                byte[] b = Util.streamToBytes(in, 16 * 3);
+                if (b.length > 0) {
+                    b = Base64.encodeBase64(b);
+
+                    int lfLen = LINE_ENDING.length;
+                    currentLine = new byte[b.length + lfLen];
+                    System.arraycopy(b, 0, currentLine, 0, b.length);
+                    System.arraycopy(LINE_ENDING, 0, currentLine, b.length, lfLen);
+                }
+            }
+        }
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/CRLUtil.java b/src/java/org/apache/commons/ssl/CRLUtil.java
new file mode 100644
index 0000000..744502d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/CRLUtil.java
@@ -0,0 +1,75 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/CRLUtil.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+/*
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.x509.CRLDistPoint;
+import org.bouncycastle.asn1.x509.DistributionPoint;
+import org.bouncycastle.asn1.x509.DistributionPointName;
+import org.bouncycastle.x509.extension.X509ExtensionUtil;
+*/
+
+import java.io.IOException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 20-Dec-2005
+ */
+public class CRLUtil {
+
+    public static String getURLToCRL(byte[] extension2_5_29_31)
+        throws IOException {
+
+        throw new UnsupportedOperationException("not yet implemented");
+
+        /*
+                    byte[] bytes = extension2_5_29_31;
+                    ASN1Encodable asn1 = X509ExtensionUtil.fromExtensionValue(bytes);
+                    DERObject obj = asn1.getDERObject();
+                    CRLDistPoint distPoint = CRLDistPoint.getInstance(obj);
+                    DistributionPoint[] points = distPoint.getDistributionPoints();
+                    DistributionPointName dpn = points[0].getDistributionPoint();
+                    obj = dpn.getName().toASN1Object();
+                    ASN1Sequence seq = ASN1Sequence.getInstance(obj);
+                    DERTaggedObject tag = (DERTaggedObject) seq.getObjectAt(0);
+                    bytes = ASN1OctetString.getInstance(tag, false).getOctets();
+                    return new String(bytes);
+                    */
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/Certificates.java b/src/java/org/apache/commons/ssl/Certificates.java
new file mode 100644
index 0000000..2c8926f
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Certificates.java
@@ -0,0 +1,591 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Certificates.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CRL;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509Extension;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 19-Aug-2005
+ */
+public class Certificates {
+
+    public final static CertificateFactory CF;
+    public final static String LINE_ENDING = System.getProperty("line.separator");
+
+    private final static HashMap crl_cache = new HashMap();
+
+    public final static String CRL_EXTENSION = "2.5.29.31";
+    public final static String OCSP_EXTENSION = "1.3.6.1.5.5.7.1.1";
+    private final static DateFormat DF = new SimpleDateFormat("yyyy/MMM/dd");
+
+    public interface SerializableComparator extends Comparator, Serializable {
+    }
+
+    public final static SerializableComparator COMPARE_BY_EXPIRY =
+        new SerializableComparator() {
+            public int compare(Object o1, Object o2) {
+                X509Certificate c1 = (X509Certificate) o1;
+                X509Certificate c2 = (X509Certificate) o2;
+                if (c1 == c2) // this deals with case where both are null
+                {
+                    return 0;
+                }
+                if (c1 == null)  // non-null is always bigger than null
+                {
+                    return -1;
+                }
+                if (c2 == null) {
+                    return 1;
+                }
+                if (c1.equals(c2)) {
+                    return 0;
+                }
+                Date d1 = c1.getNotAfter();
+                Date d2 = c2.getNotAfter();
+                int c = d1.compareTo(d2);
+                if (c == 0) {
+                    String s1 = JavaImpl.getSubjectX500(c1);
+                    String s2 = JavaImpl.getSubjectX500(c2);
+                    c = s1.compareTo(s2);
+                    if (c == 0) {
+                        s1 = JavaImpl.getIssuerX500(c1);
+                        s2 = JavaImpl.getIssuerX500(c2);
+                        c = s1.compareTo(s2);
+                        if (c == 0) {
+                            BigInteger big1 = c1.getSerialNumber();
+                            BigInteger big2 = c2.getSerialNumber();
+                            c = big1.compareTo(big2);
+                            if (c == 0) {
+                                try {
+                                    byte[] b1 = c1.getEncoded();
+                                    byte[] b2 = c2.getEncoded();
+                                    int len1 = b1.length;
+                                    int len2 = b2.length;
+                                    int i = 0;
+                                    for (; i < len1 && i < len2; i++) {
+                                        c = ((int) b1[i]) - ((int) b2[i]);
+                                        if (c != 0) {
+                                            break;
+                                        }
+                                    }
+                                    if (c == 0) {
+                                        c = b1.length - b2.length;
+                                    }
+                                }
+                                catch (CertificateEncodingException cee) {
+                                    // I give up.  They can be equal if they
+                                    // really want to be this badly.
+                                    c = 0;
+                                }
+                            }
+                        }
+                    }
+                }
+                return c;
+            }
+        };
+
+    static {
+        CertificateFactory cf = null;
+        try {
+            cf = CertificateFactory.getInstance("X.509");
+        }
+        catch (CertificateException ce) {
+            ce.printStackTrace(System.out);
+        }
+        finally {
+            CF = cf;
+        }
+    }
+
+    public static String toPEMString(X509Certificate cert)
+        throws CertificateEncodingException {
+        return toString(cert.getEncoded());
+    }
+
+    public static String toString(byte[] x509Encoded) {
+        byte[] encoded = Base64.encodeBase64(x509Encoded);
+        StringBuffer buf = new StringBuffer(encoded.length + 100);
+        buf.append("-----BEGIN CERTIFICATE-----\n");
+        for (int i = 0; i < encoded.length; i += 64) {
+            if (encoded.length - i >= 64) {
+                buf.append(new String(encoded, i, 64));
+            } else {
+                buf.append(new String(encoded, i, encoded.length - i));
+            }
+            buf.append(LINE_ENDING);
+        }
+        buf.append("-----END CERTIFICATE-----");
+        buf.append(LINE_ENDING);
+        return buf.toString();
+    }
+
+    public static String toString(X509Certificate cert) {
+        return toString(cert, false);
+    }
+
+    public static String toString(X509Certificate cert, boolean htmlStyle) {
+        String cn = getCN(cert);
+        String startStart = DF.format(cert.getNotBefore());
+        String endDate = DF.format(cert.getNotAfter());
+        String subject = JavaImpl.getSubjectX500(cert);
+        String issuer = JavaImpl.getIssuerX500(cert);
+        Iterator crls = getCRLs(cert).iterator();
+        if (subject.equals(issuer)) {
+            issuer = "self-signed";
+        }
+        StringBuffer buf = new StringBuffer(128);
+        if (htmlStyle) {
+            buf.append("<strong class=\"cn\">");
+        }
+        buf.append(cn);
+        if (htmlStyle) {
+            buf.append("</strong>");
+        }
+        buf.append(LINE_ENDING);
+        buf.append("Valid: ");
+        buf.append(startStart);
+        buf.append(" - ");
+        buf.append(endDate);
+        buf.append(LINE_ENDING);
+        buf.append("s: ");
+        buf.append(subject);
+        buf.append(LINE_ENDING);
+        buf.append("i: ");
+        buf.append(issuer);
+        while (crls.hasNext()) {
+            buf.append(LINE_ENDING);
+            buf.append("CRL: ");
+            buf.append((String) crls.next());
+        }
+        buf.append(LINE_ENDING);
+        return buf.toString();
+    }
+
+    public static List getCRLs(X509Extension cert) {
+        // What follows is a poor man's CRL extractor, for those lacking
+        // a BouncyCastle "bcprov.jar" in their classpath.
+
+        // It's a very basic state-machine:  look for a standard URL scheme
+        // (such as http), and then start looking for a terminator.  After
+        // running hexdump a few times on these things, it looks to me like
+        // the UTF-8 value "65533" seems to happen near where these things
+        // terminate.  (Of course this stuff is ASN.1 and not UTF-8, but
+        // I happen to like some of the functions available to the String
+        // object).    - juliusdavies at cucbc.com, May 10th, 2006
+        byte[] bytes = cert.getExtensionValue(CRL_EXTENSION);
+        LinkedList httpCRLS = new LinkedList();
+        LinkedList ftpCRLS = new LinkedList();
+        LinkedList otherCRLS = new LinkedList();
+        if (bytes == null) {
+            // just return empty list
+            return httpCRLS;
+        } else {
+            String s;
+            try {
+                s = new String(bytes, "UTF-8");
+            }
+            catch (UnsupportedEncodingException uee) {
+                // We're screwed if this thing has more than one CRL, because
+                // the "indeOf( (char) 65533 )" below isn't going to work.
+                s = new String(bytes);
+            }
+            int pos = 0;
+            while (pos >= 0) {
+                int x = -1, y;
+                int[] indexes = new int[4];
+                indexes[0] = s.indexOf("http", pos);
+                indexes[1] = s.indexOf("ldap", pos);
+                indexes[2] = s.indexOf("file", pos);
+                indexes[3] = s.indexOf("ftp", pos);
+                Arrays.sort(indexes);
+                for (int i = 0; i < indexes.length; i++) {
+                    if (indexes[i] >= 0) {
+                        x = indexes[i];
+                        break;
+                    }
+                }
+                if (x >= 0) {
+                    y = s.indexOf((char) 65533, x);
+                    String crl = y > x ? s.substring(x, y - 1) : s.substring(x);
+                    if (y > x && crl.endsWith("0")) {
+                        crl = crl.substring(0, crl.length() - 1);
+                    }
+                    String crlTest = crl.trim().toLowerCase();
+                    if (crlTest.startsWith("http")) {
+                        httpCRLS.add(crl);
+                    } else if (crlTest.startsWith("ftp")) {
+                        ftpCRLS.add(crl);
+                    } else {
+                        otherCRLS.add(crl);
+                    }
+                    pos = y;
+                } else {
+                    pos = -1;
+                }
+            }
+        }
+
+        httpCRLS.addAll(ftpCRLS);
+        httpCRLS.addAll(otherCRLS);
+        return httpCRLS;
+    }
+
+    public static void checkCRL(X509Certificate cert)
+        throws CertificateException {
+        // String name = cert.getSubjectX500Principal().toString();
+        byte[] bytes = cert.getExtensionValue("2.5.29.31");
+        if (bytes == null) {
+            // log.warn( "Cert doesn't contain X509v3 CRL Distribution Points (2.5.29.31): " + name );
+        } else {
+            List crlList = getCRLs(cert);
+            Iterator it = crlList.iterator();
+            while (it.hasNext()) {
+                String url = (String) it.next();
+                CRLHolder holder = (CRLHolder) crl_cache.get(url);
+                if (holder == null) {
+                    holder = new CRLHolder(url);
+                    crl_cache.put(url, holder);
+                }
+                // success == false means we couldn't actually load the CRL
+                // (probably due to an IOException), so let's try the next one in
+                // our list.
+                boolean success = holder.checkCRL(cert);
+                if (success) {
+                    break;
+                }
+            }
+        }
+
+    }
+
+    public static BigInteger getFingerprint(X509Certificate x509)
+        throws CertificateEncodingException {
+        return getFingerprint(x509.getEncoded());
+    }
+
+    public static BigInteger getFingerprint(byte[] x509)
+        throws CertificateEncodingException {
+        MessageDigest sha1;
+        try {
+            sha1 = MessageDigest.getInstance("SHA1");
+        }
+        catch (NoSuchAlgorithmException nsae) {
+            throw JavaImpl.newRuntimeException(nsae);
+        }
+
+        sha1.reset();
+        byte[] result = sha1.digest(x509);
+        return new BigInteger(result);
+    }
+
+    private static class CRLHolder {
+        private final String urlString;
+
+        private File tempCRLFile;
+        private long creationTime;
+        private Set passedTest = new HashSet();
+        private Set failedTest = new HashSet();
+
+        CRLHolder(String urlString) {
+            if (urlString == null) {
+                throw new NullPointerException("urlString can't be null");
+            }
+            this.urlString = urlString;
+        }
+
+        public synchronized boolean checkCRL(X509Certificate cert)
+            throws CertificateException {
+            CRL crl = null;
+            long now = System.currentTimeMillis();
+            if (now - creationTime > 24 * 60 * 60 * 1000) {
+                // Expire cache every 24 hours
+                if (tempCRLFile != null && tempCRLFile.exists()) {
+                    tempCRLFile.delete();
+                }
+                tempCRLFile = null;
+                passedTest.clear();
+
+                /*
+                      Note:  if any certificate ever fails the check, we will
+                      remember that fact.
+
+                      This breaks with temporary "holds" that CRL's can issue.
+                      Apparently a certificate can have a temporary "hold" on its
+                      validity, but I'm not interested in supporting that.  If a "held"
+                      certificate is suddenly "unheld", you're just going to need
+                      to restart your JVM.
+                    */
+                // failedTest.clear();  <-- DO NOT UNCOMMENT!
+            }
+
+            BigInteger fingerprint = getFingerprint(cert);
+            if (failedTest.contains(fingerprint)) {
+                throw new CertificateException("Revoked by CRL (cached response)");
+            }
+            if (passedTest.contains(fingerprint)) {
+                return true;
+            }
+
+            if (tempCRLFile == null) {
+                try {
+                    // log.info( "Trying to load CRL [" + urlString + "]" );
+                    URL url = new URL(urlString);
+                    File tempFile = File.createTempFile("crl", ".tmp");
+                    tempFile.deleteOnExit();
+
+                    OutputStream out = new FileOutputStream(tempFile);
+                    out = new BufferedOutputStream(out);
+                    InputStream in = new BufferedInputStream(url.openStream());
+                    try {
+                        Util.pipeStream(in, out);
+                    }
+                    catch (IOException ioe) {
+                        // better luck next time
+                        tempFile.delete();
+                        throw ioe;
+                    }
+                    this.tempCRLFile = tempFile;
+                    this.creationTime = System.currentTimeMillis();
+                }
+                catch (IOException ioe) {
+                    // log.warn( "Cannot check CRL: " + e );
+                }
+            }
+
+            if (tempCRLFile != null && tempCRLFile.exists()) {
+                try {
+                    InputStream in = new FileInputStream(tempCRLFile);
+                    in = new BufferedInputStream(in);
+                    synchronized (CF) {
+                        crl = CF.generateCRL(in);
+                    }
+                    in.close();
+                    if (crl.isRevoked(cert)) {
+                        // log.warn( "Revoked by CRL [" + urlString + "]: " + name );
+                        passedTest.remove(fingerprint);
+                        failedTest.add(fingerprint);
+                        throw new CertificateException("Revoked by CRL");
+                    } else {
+                        passedTest.add(fingerprint);
+                    }
+                }
+                catch (IOException ioe) {
+                    // couldn't load CRL that's supposed to be stored in Temp file.
+                    // log.warn(  );
+                }
+                catch (CRLException crle) {
+                    // something is wrong with the CRL
+                    // log.warn(  );
+                }
+            }
+            return crl != null;
+        }
+    }
+
+    public static String getCN(X509Certificate cert) {
+        String[] cns = getCNs(cert);
+        boolean foundSomeCNs = cns != null && cns.length >= 1;
+        return foundSomeCNs ? cns[0] : null;
+    }
+
+    public static String[] getCNs(X509Certificate cert) {
+        LinkedList cnList = new LinkedList();
+        /*
+          Sebastian Hauer's original StrictSSLProtocolSocketFactory used
+          getName() and had the following comment:
+
+             Parses a X.500 distinguished name for the value of the
+             "Common Name" field.  This is done a bit sloppy right
+             now and should probably be done a bit more according to
+             <code>RFC 2253</code>.
+
+           I've noticed that toString() seems to do a better job than
+           getName() on these X500Principal objects, so I'm hoping that
+           addresses Sebastian's concern.
+
+           For example, getName() gives me this:
+           1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d
+
+           whereas toString() gives me this:
+           EMAILADDRESS=juliusdavies at cucbc.com
+
+           Looks like toString() even works with non-ascii domain names!
+           I tested it with "&#x82b1;&#x5b50;.co.jp" and it worked fine.
+          */
+        String subjectPrincipal = cert.getSubjectX500Principal().toString();
+        StringTokenizer st = new StringTokenizer(subjectPrincipal, ",");
+        while (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            int x = tok.indexOf("CN=");
+            if (x >= 0) {
+                cnList.add(tok.substring(x + 3));
+            }
+        }
+        if (!cnList.isEmpty()) {
+            String[] cns = new String[cnList.size()];
+            cnList.toArray(cns);
+            return cns;
+        } else {
+            return null;
+        }
+    }
+
+
+    /**
+     * Extracts the array of SubjectAlt DNS names from an X509Certificate.
+     * Returns null if there aren't any.
+     * <p/>
+     * Note:  Java doesn't appear able to extract international characters
+     * from the SubjectAlts.  It can only extract international characters
+     * from the CN field.
+     * <p/>
+     * (Or maybe the version of OpenSSL I'm using to test isn't storing the
+     * international characters correctly in the SubjectAlts?).
+     *
+     * @param cert X509Certificate
+     * @return Array of SubjectALT DNS names stored in the certificate.
+     */
+    public static String[] getDNSSubjectAlts(X509Certificate cert) {
+        LinkedList subjectAltList = new LinkedList();
+        Collection c = null;
+        try {
+            c = cert.getSubjectAlternativeNames();
+        }
+        catch (CertificateParsingException cpe) {
+            // Should probably log.debug() this?
+            cpe.printStackTrace();
+        }
+        if (c != null) {
+            Iterator it = c.iterator();
+            while (it.hasNext()) {
+                List list = (List) it.next();
+                int type = ((Integer) list.get(0)).intValue();
+                // If type is 2, then we've got a dNSName
+                if (type == 2) {
+                    String s = (String) list.get(1);
+                    subjectAltList.add(s);
+                }
+            }
+        }
+        if (!subjectAltList.isEmpty()) {
+            String[] subjectAlts = new String[subjectAltList.size()];
+            subjectAltList.toArray(subjectAlts);
+            return subjectAlts;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Trims off any null entries on the array.  Returns a shrunk array.
+     *
+     * @param chain X509Certificate[] chain to trim
+     * @return Shrunk array with all trailing null entries removed.
+     */
+    public static X509Certificate[] trimChain(X509Certificate[] chain) {
+        for (int i = 0; i < chain.length; i++) {
+            if (chain[i] == null) {
+                X509Certificate[] newChain = new X509Certificate[i];
+                System.arraycopy(chain, 0, newChain, 0, i);
+                return newChain;
+            }
+        }
+        return chain;
+    }
+
+    /**
+     * Returns a chain of type X509Certificate[].
+     *
+     * @param chain Certificate[] chain to cast to X509Certificate[]
+     * @return chain of type X509Certificate[].
+     */
+    public static X509Certificate[] x509ifyChain(Certificate[] chain) {
+        if (chain instanceof X509Certificate[]) {
+            return (X509Certificate[]) chain;
+        } else {
+            X509Certificate[] x509Chain = new X509Certificate[chain.length];
+            System.arraycopy(chain, 0, x509Chain, 0, chain.length);
+            return x509Chain;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        for (int i = 0; i < args.length; i++) {
+            FileInputStream in = new FileInputStream(args[i]);
+            TrustMaterial tm = new TrustMaterial(in);
+            Iterator it = tm.getCertificates().iterator();
+            while (it.hasNext()) {
+                X509Certificate x509 = (X509Certificate) it.next();
+                System.out.println(toString(x509));
+            }
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/ComboInputStream.java b/src/java/org/apache/commons/ssl/ComboInputStream.java
new file mode 100644
index 0000000..d431009
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/ComboInputStream.java
@@ -0,0 +1,96 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/ComboInputStream.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class ComboInputStream extends InputStream {
+    private boolean headDone;
+    private InputStream head;
+    private InputStream tail;
+
+    public ComboInputStream(InputStream head, InputStream tail) {
+        this.head = head != null ? head : tail;
+        this.tail = tail != null ? tail : head;
+    }
+
+    public int read() throws IOException {
+        int c;
+        if (headDone) {
+            c = tail.read();
+        } else {
+            c = head.read();
+            if (c == -1) {
+                headDone = true;
+                c = tail.read();
+            }
+        }
+        return c;
+    }
+
+    public int available() throws IOException {
+        return tail.available() + head.available();
+    }
+
+    public void close() throws IOException {
+        try {
+            head.close();
+        }
+        finally {
+            if (head != tail) {
+                tail.close();
+            }
+        }
+    }
+
+    public int read(byte b[], int off, int len) throws IOException {
+        int c;
+        if (headDone) {
+            c = tail.read(b, off, len);
+        } else {
+            c = head.read(b, off, len);
+            if (c == -1) {
+                headDone = true;
+                c = tail.read(b, off, len);
+            }
+        }
+        return c;
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/DerivedKey.java b/src/java/org/apache/commons/ssl/DerivedKey.java
new file mode 100644
index 0000000..9e1ed4d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/DerivedKey.java
@@ -0,0 +1,49 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/DerivedKey.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 7-Nov-2006
+ */
+public class DerivedKey {
+    public final byte[] key;
+    public final byte[] iv;
+
+    DerivedKey(byte[] key, byte[] iv) {
+        this.key = key;
+        this.iv = iv;
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/HostPort.java b/src/java/org/apache/commons/ssl/HostPort.java
new file mode 100644
index 0000000..1826c0a
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/HostPort.java
@@ -0,0 +1,55 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/HostPort.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 14-July-2006
+ */
+public class HostPort {
+    public final String host;
+    public final int port;
+    public final InetAddress addr;
+
+    public HostPort(String host, int port) throws UnknownHostException {
+        this.host = host;
+        this.port = port;
+        this.addr = InetAddress.getByName(host);
+    }
+
+    public String toString() { return host + ":" + port; }
+}
diff --git a/src/java/org/apache/commons/ssl/HostnameVerifier.java b/src/java/org/apache/commons/ssl/HostnameVerifier.java
new file mode 100644
index 0000000..c6f22c2
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/HostnameVerifier.java
@@ -0,0 +1,481 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/HostnameVerifier.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+/**
+ * Interface for checking if a hostname matches the names stored inside the
+ * server's X.509 certificate.  Correctly implements
+ * javax.net.ssl.HostnameVerifier, but that interface is not recommended.
+ * Instead we added several check() methods that take SSLSocket,
+ * or X509Certificate, or ultimately (they all end up calling this one),
+ * String.  (It's easier to supply JUnit with Strings instead of mock
+ * SSLSession objects!)
+ * </p><p>Our check() methods throw exceptions if the name is
+ * invalid, whereas javax.net.ssl.HostnameVerifier just returns true/false.
+ * <p/>
+ * We provide the HostnameVerifier.DEFAULT, HostnameVerifier.STRICT, and
+ * HostnameVerifier.ALLOW_ALL implementations.  We also provide the more
+ * specialized HostnameVerifier.DEFAULT_AND_LOCALHOST, as well as
+ * HostnameVerifier.STRICT_IE6.  But feel free to define your own
+ * implementations!
+ * <p/>
+ * Inspired by Sebastian Hauer's original StrictSSLProtocolSocketFactory in the
+ * HttpClient "contrib" repository.
+ *
+ * @author Julius Davies
+ * @author <a href="mailto:hauer at psicode.com">Sebastian Hauer</a>
+ * @since 8-Dec-2006
+ */
+public interface HostnameVerifier extends javax.net.ssl.HostnameVerifier {
+
+    boolean verify(String host, SSLSession session);
+
+    void check(String host, SSLSocket ssl) throws IOException;
+
+    void check(String host, X509Certificate cert) throws SSLException;
+
+    void check(String host, String[] cns, String[] subjectAlts)
+        throws SSLException;
+
+    void check(String[] hosts, SSLSocket ssl) throws IOException;
+
+    void check(String[] hosts, X509Certificate cert) throws SSLException;
+
+
+    /**
+     * Checks to see if the supplied hostname matches any of the supplied CNs
+     * or "DNS" Subject-Alts.  Most implementations only look at the first CN,
+     * and ignore any additional CNs.  Most implementations do look at all of
+     * the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards
+     * according to RFC 2818.
+     *
+     * @param cns         CN fields, in order, as extracted from the X.509
+     *                    certificate.
+     * @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted
+     *                    from the X.509 certificate.
+     * @param hosts       The array of hostnames to verify.
+     * @throws SSLException If verification failed.
+     */
+    void check(String[] hosts, String[] cns, String[] subjectAlts)
+        throws SSLException;
+
+
+    /**
+     * The DEFAULT HostnameVerifier works the same way as Curl and Firefox.
+     * <p/>
+     * The hostname must match either the first CN, or any of the subject-alts.
+     * A wildcard can occur in the CN, and in any of the subject-alts.
+     * <p/>
+     * The only difference between DEFAULT and STRICT is that a wildcard (such
+     * as "*.foo.com") with DEFAULT matches all subdomains, including
+     * "a.b.foo.com".
+     */
+    public final static HostnameVerifier DEFAULT =
+        new AbstractVerifier() {
+            public final void check(final String[] hosts, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                check(hosts, cns, subjectAlts, false, false);
+            }
+
+            public final String toString() { return "DEFAULT"; }
+        };
+
+
+    /**
+     * The DEFAULT_AND_LOCALHOST HostnameVerifier works like the DEFAULT
+     * one with one additional relaxation:  a host of "localhost",
+     * "localhost.localdomain", "127.0.0.1", "::1" will always pass, no matter
+     * what is in the server's certificate.
+     */
+    public final static HostnameVerifier DEFAULT_AND_LOCALHOST =
+        new AbstractVerifier() {
+            public final void check(final String[] hosts, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                if (isLocalhost(hosts[0])) {
+                    return;
+                }
+                check(hosts, cns, subjectAlts, false, false);
+            }
+
+            public final String toString() { return "DEFAULT_AND_LOCALHOST"; }
+        };
+
+    /**
+     * The STRICT HostnameVerifier works the same way as java.net.URL in Sun
+     * Java 1.4, Sun Java 5, Sun Java 6.  It's also pretty close to IE6.
+     * This implementation appears to be compliant with RFC 2818 for dealing
+     * with wildcards.
+     * <p/>
+     * The hostname must match either the first CN, or any of the subject-alts.
+     * A wildcard can occur in the CN, and in any of the subject-alts.  The
+     * one divergence from IE6 is how we only check the first CN.  IE6 allows
+     * a match against any of the CNs present.  We decided to follow in
+     * Sun Java 1.4's footsteps and only check the first CN.
+     * <p/>
+     * A wildcard such as "*.foo.com" matches only subdomains in the same
+     * level, for example "a.foo.com".  It does not match deeper subdomains
+     * such as "a.b.foo.com".
+     */
+    public final static HostnameVerifier STRICT =
+        new AbstractVerifier() {
+            public final void check(final String[] host, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                check(host, cns, subjectAlts, false, true);
+            }
+
+            public final String toString() { return "STRICT"; }
+        };
+
+    /**
+     * The STRICT_IE6 HostnameVerifier works just like the STRICT one with one
+     * minor variation:  the hostname can match against any of the CN's in the
+     * server's certificate, not just the first one.  This behaviour is
+     * identical to IE6's behaviour.
+     */
+    public final static HostnameVerifier STRICT_IE6 =
+        new AbstractVerifier() {
+            public final void check(final String[] host, final String[] cns,
+                                    final String[] subjectAlts)
+                throws SSLException {
+                check(host, cns, subjectAlts, true, true);
+            }
+
+            public final String toString() { return "STRICT_IE6"; }
+        };
+
+    /**
+     * The ALLOW_ALL HostnameVerifier essentially turns hostname verification
+     * off.  This implementation is a no-op, and never throws the SSLException.
+     */
+    public final static HostnameVerifier ALLOW_ALL =
+        new AbstractVerifier() {
+            public final void check(final String[] host, final String[] cns,
+                                    final String[] subjectAlts) {
+                // Allow everything - so never blowup.
+            }
+
+            public final String toString() { return "ALLOW_ALL"; }
+        };
+
+    abstract class AbstractVerifier implements HostnameVerifier {
+
+        /**
+         * This contains a list of 2nd-level domains that aren't allowed to
+         * have wildcards when combined with country-codes.
+         * For example: [*.co.uk].
+         * <p/>
+         * The [*.co.uk] problem is an interesting one.  Should we just hope
+         * that CA's would never foolishly allow such a certificate to happen?
+         * Looks like we're the only implementation guarding against this.
+         * Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
+         */
+        private final static String[] BAD_COUNTRY_2LDS =
+            {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
+                "lg", "ne", "net", "or", "org"};
+
+        private final static String[] LOCALHOSTS = {"::1", "127.0.0.1",
+            "localhost",
+            "localhost.localdomain"};
+
+
+        static {
+            // Just in case developer forgot to manually sort the array.  :-)
+            Arrays.sort(BAD_COUNTRY_2LDS);
+            Arrays.sort(LOCALHOSTS);
+        }
+
+        protected AbstractVerifier() {}
+
+        /**
+         * The javax.net.ssl.HostnameVerifier contract.
+         *
+         * @param host    'hostname' we used to create our socket
+         * @param session SSLSession with the remote server
+         * @return true if the host matched the one in the certificate.
+         */
+        public boolean verify(String host, SSLSession session) {
+            try {
+                Certificate[] certs = session.getPeerCertificates();
+                X509Certificate x509 = (X509Certificate) certs[0];
+                check(new String[]{host}, x509);
+                return true;
+            }
+            catch (SSLException e) {
+                return false;
+            }
+        }
+
+        public void check(String host, SSLSocket ssl) throws IOException {
+            check(new String[]{host}, ssl);
+        }
+
+        public void check(String host, X509Certificate cert)
+            throws SSLException {
+            check(new String[]{host}, cert);
+        }
+
+        public void check(String host, String[] cns, String[] subjectAlts)
+            throws SSLException {
+            check(new String[]{host}, cns, subjectAlts);
+        }
+
+        public void check(String host[], SSLSocket ssl)
+            throws IOException {
+            if (host == null) {
+                throw new NullPointerException("host to verify is null");
+            }
+
+            SSLSession session = ssl.getSession();
+            if (session == null) {
+                // In our experience this only happens under IBM 1.4.x when
+                // spurious (unrelated) certificates show up in the server'
+                // chain.  Hopefully this will unearth the real problem:
+                InputStream in = ssl.getInputStream();
+                in.available();
+                /*
+                  If you're looking at the 2 lines of code above because
+                  you're running into a problem, you probably have two
+                  options:
+
+                    #1.  Clean up the certificate chain that your server
+                         is presenting (e.g. edit "/etc/apache2/server.crt"
+                         or wherever it is your server's certificate chain
+                         is defined).
+
+                                               OR
+
+                    #2.   Upgrade to an IBM 1.5.x or greater JVM, or switch
+                          to a non-IBM JVM.
+                */
+
+                // If ssl.getInputStream().available() didn't cause an
+                // exception, maybe at least now the session is available?
+                session = ssl.getSession();
+                if (session == null) {
+                    // If it's still null, probably a startHandshake() will
+                    // unearth the real problem.
+                    ssl.startHandshake();
+
+                    // Okay, if we still haven't managed to cause an exception,
+                    // might as well go for the NPE.  Or maybe we're okay now?
+                    session = ssl.getSession();
+                }
+            }
+            Certificate[] certs;
+            try {
+                certs = session.getPeerCertificates();
+            } catch (SSLPeerUnverifiedException spue) {
+                InputStream in = ssl.getInputStream();
+                in.available();
+                // Didn't trigger anything interesting?  Okay, just throw
+                // original.
+                throw spue;
+            }
+            X509Certificate x509 = (X509Certificate) certs[0];
+            check(host, x509);
+        }
+
+        public void check(String[] host, X509Certificate cert)
+            throws SSLException {
+            String[] cns = Certificates.getCNs(cert);
+            String[] subjectAlts = Certificates.getDNSSubjectAlts(cert);
+            check(host, cns, subjectAlts);
+        }
+
+        public void check(final String[] hosts, final String[] cns,
+                          final String[] subjectAlts, final boolean ie6,
+                          final boolean strictWithSubDomains)
+            throws SSLException {
+            // Build up lists of allowed hosts For logging/debugging purposes.
+            StringBuffer buf = new StringBuffer(32);
+            buf.append('<');
+            for (int i = 0; i < hosts.length; i++) {
+                String h = hosts[i];
+                h = h != null ? h.trim().toLowerCase() : "";
+                hosts[i] = h;
+                if (i > 0) {
+                    buf.append('/');
+                }
+                buf.append(h);
+            }
+            buf.append('>');
+            String hostnames = buf.toString();
+            // Build the list of names we're going to check.  Our DEFAULT and
+            // STRICT implementations of the HostnameVerifier only use the
+            // first CN provided.  All other CNs are ignored.
+            // (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way).
+            TreeSet names = new TreeSet();
+            if (cns != null && cns.length > 0 && cns[0] != null) {
+                names.add(cns[0]);
+                if (ie6) {
+                    for (int i = 1; i < cns.length; i++) {
+                        names.add(cns[i]);
+                    }
+                }
+            }
+            if (subjectAlts != null) {
+                for (int i = 0; i < subjectAlts.length; i++) {
+                    if (subjectAlts[i] != null) {
+                        names.add(subjectAlts[i]);
+                    }
+                }
+            }
+            if (names.isEmpty()) {
+                String msg = "Certificate for " + hosts[0] + " doesn't contain CN or DNS subjectAlt";
+                throw new SSLException(msg);
+            }
+
+            // StringBuffer for building the error message.
+            buf = new StringBuffer();
+
+            boolean match = false;
+            out:
+            for (Iterator it = names.iterator(); it.hasNext();) {
+                // Don't trim the CN, though!
+                String cn = (String) it.next();
+                cn = cn.toLowerCase();
+                // Store CN in StringBuffer in case we need to report an error.
+                buf.append(" <");
+                buf.append(cn);
+                buf.append('>');
+                if (it.hasNext()) {
+                    buf.append(" OR");
+                }
+
+                // The CN better have at least two dots if it wants wildcard
+                // action.  It also can't be [*.co.uk] or [*.co.jp] or
+                // [*.org.uk], etc...
+                boolean doWildcard = cn.startsWith("*.") &&
+                                     cn.lastIndexOf('.') >= 0 &&
+                                     !isIP4Address(cn) &&
+                                     acceptableCountryWildcard(cn);
+
+                for (int i = 0; i < hosts.length; i++) {
+                    final String hostName = hosts[i].trim().toLowerCase();
+                    if (doWildcard) {
+                        match = hostName.endsWith(cn.substring(1));
+                        if (match && strictWithSubDomains) {
+                            // If we're in strict mode, then [*.foo.com] is not
+                            // allowed to match [a.b.foo.com]
+                            match = countDots(hostName) == countDots(cn);
+                        }
+                    } else {
+                        match = hostName.equals(cn);
+                    }
+                    if (match) {
+                        break out;
+                    }
+                }
+            }
+            if (!match) {
+                throw new SSLException("hostname in certificate didn't match: " + hostnames + " !=" + buf);
+            }
+        }
+
+        public static boolean isIP4Address(final String cn) {
+            boolean isIP4 = true;
+            String tld = cn;
+            int x = cn.lastIndexOf('.');
+            // We only bother analyzing the characters after the final dot
+            // in the name.
+            if (x >= 0 && x + 1 < cn.length()) {
+                tld = cn.substring(x + 1);
+            }
+            for (int i = 0; i < tld.length(); i++) {
+                if (!Character.isDigit(tld.charAt(0))) {
+                    isIP4 = false;
+                    break;
+                }
+            }
+            return isIP4;
+        }
+
+        public static boolean acceptableCountryWildcard(final String cn) {
+            int cnLen = cn.length();
+            if (cnLen >= 7 && cnLen <= 9) {
+                // Look for the '.' in the 3rd-last position:
+                if (cn.charAt(cnLen - 3) == '.') {
+                    // Trim off the [*.] and the [.XX].
+                    String s = cn.substring(2, cnLen - 3);
+                    // And test against the sorted array of bad 2lds:
+                    int x = Arrays.binarySearch(BAD_COUNTRY_2LDS, s);
+                    return x < 0;
+                }
+            }
+            return true;
+        }
+
+        public static boolean isLocalhost(String host) {
+            host = host != null ? host.trim().toLowerCase() : "";
+            if (host.startsWith("::1")) {
+                int x = host.lastIndexOf('%');
+                if (x >= 0) {
+                    host = host.substring(0, x);
+                }
+            }
+            int x = Arrays.binarySearch(LOCALHOSTS, host);
+            return x >= 0;
+        }
+
+        /**
+         * Counts the number of dots "." in a string.
+         *
+         * @param s string to count dots from
+         * @return number of dots
+         */
+        public static int countDots(final String s) {
+            int count = 0;
+            for (int i = 0; i < s.length(); i++) {
+                if (s.charAt(i) == '.') {
+                    count++;
+                }
+            }
+            return count;
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/HttpSecureProtocol.java b/src/java/org/apache/commons/ssl/HttpSecureProtocol.java
new file mode 100644
index 0000000..9624865
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/HttpSecureProtocol.java
@@ -0,0 +1,93 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/HttpSecureProtocol.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+
+/**
+ * Hook into HttpClient.
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 5-May-2006
+ */
+public class HttpSecureProtocol extends SSLClient
+    implements SecureProtocolSocketFactory {
+
+    public HttpSecureProtocol()
+        throws GeneralSecurityException, IOException {
+        super();
+    }
+
+    /**
+     * Attempts to get a new socket connection to the given host within the
+     * given time limit.
+     * <p/>
+     * To circumvent the limitations of older JREs that do not support connect
+     * timeout a controller thread is executed. The controller thread attempts
+     * to create a new socket within the given limit of time. If socket
+     * constructor does not return until the timeout expires, the controller
+     * terminates and throws an
+     * {@link org.apache.commons.httpclient.ConnectTimeoutException}
+     * </p>
+     *
+     * @param host         the host name/IP
+     * @param port         the port on the host
+     * @param localAddress the local host name/IP to bind the socket to
+     * @param localPort    the port on the local machine
+     * @param params       {@link org.apache.commons.httpclient.params.HttpConnectionParams Http connection parameters}
+     * @return Socket a new socket
+     * @throws java.io.IOException           if an I/O error occurs while creating the socket
+     * @throws java.net.UnknownHostException if the IP address of the host cannot be
+     *                                       determined
+     */
+    public Socket createSocket(final String host,
+                               final int port,
+                               final InetAddress localAddress,
+                               final int localPort,
+                               final HttpConnectionParams params)
+        throws IOException {
+        if (params == null) {
+            throw new IllegalArgumentException("Parameters may not be null");
+        }
+        int timeout = params.getConnectionTimeout();
+        return super.createSocket(host, port, localAddress, localPort, timeout);
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/Java13.java b/src/java/org/apache/commons/ssl/Java13.java
new file mode 100644
index 0000000..b8a2721
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Java13.java
@@ -0,0 +1,290 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java13.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import com.sun.net.ssl.KeyManager;
+import com.sun.net.ssl.KeyManagerFactory;
+import com.sun.net.ssl.SSLContext;
+import com.sun.net.ssl.TrustManager;
+import com.sun.net.ssl.TrustManagerFactory;
+import com.sun.net.ssl.X509KeyManager;
+import com.sun.net.ssl.X509TrustManager;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Jun-2006
+ */
+public final class Java13 extends JavaImpl {
+    private final static Java13 instance = new Java13();
+
+    private Java13() {
+        try {
+            Class c = Class.forName("javax.crypto.Cipher");
+            Class[] sig = {String.class};
+            String[] args = {"DES/CBC/PKCS5Padding"};
+            Method m = c.getMethod("getInstance", sig);
+            m.invoke(null, args);
+        }
+        catch (Exception e) {
+            try {
+                Class c = Class.forName("com.sun.crypto.provider.SunJCE");
+                Security.addProvider((Provider) c.newInstance());
+                // System.out.println( "jce not loaded: " + e + " - loading SunJCE!" );
+                //e.printStackTrace( System.out );
+            }
+            catch (Exception e2) {
+                System.out.println("com.sun.crypto.provider.SunJCE unavailable: " + e2);
+                // e2.printStackTrace( System.out );
+            }
+        }
+        try {
+            URL u = new URL("https://vancity.com/");
+            u.openConnection();
+        }
+        catch (Exception e) {
+            // System.out.println( "java.net.URL support of https not loaded: " + e + " - attempting to load com.sun.net.ssl.internal.ssl.Provider!" );
+            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
+            System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
+        }
+        // System.out.println( "old HANDLER: " + HANDLER );
+    }
+
+    public static Java13 getInstance() {
+        return instance;
+    }
+
+    public final String getVersion() {
+        return "Java13";
+    }
+
+    protected final String retrieveSubjectX500(X509Certificate cert) {
+        return cert.getSubjectDN().toString();
+    }
+
+    protected final String retrieveIssuerX500(X509Certificate cert) {
+        return cert.getIssuerDN().toString();
+    }
+
+    protected final Certificate[] retrievePeerCerts(SSLSession sslSession)
+        throws SSLPeerUnverifiedException {
+        javax.security.cert.X509Certificate[] chain;
+        chain = sslSession.getPeerCertificateChain();
+        X509Certificate[] newChain = new X509Certificate[chain.length];
+        try {
+            for (int i = 0; i < chain.length; i++) {
+                javax.security.cert.X509Certificate javaxCert = chain[i];
+                byte[] encoded = javaxCert.getEncoded();
+                ByteArrayInputStream in = new ByteArrayInputStream(encoded);
+                synchronized (Certificates.CF) {
+                    Certificate c = Certificates.CF.generateCertificate(in);
+                    newChain[i] = (X509Certificate) c;
+                }
+            }
+        }
+        catch (Exception e) {
+            throw buildRuntimeException(e);
+        }
+        return newChain;
+    }
+
+    protected final Object buildKeyManagerFactory(KeyStore ks, char[] password)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        UnrecoverableKeyException {
+        String alg = KeyManagerFactory.getDefaultAlgorithm();
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
+        kmf.init(ks, password);
+        // overwrite password
+        for (int i = 0; i < password.length; i++) {
+            password[i] = '*';
+        }
+        return kmf;
+    }
+
+    protected final Object buildTrustManagerFactory(KeyStore ks)
+        throws NoSuchAlgorithmException, KeyStoreException {
+        String alg = TrustManagerFactory.getDefaultAlgorithm();
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg);
+        tmf.init(ks);
+        return tmf;
+    }
+
+
+    protected final Object[] retrieveKeyManagers(Object keyManagerFactory) {
+        KeyManagerFactory kmf = (KeyManagerFactory) keyManagerFactory;
+        return kmf.getKeyManagers();
+    }
+
+    protected final Object[] retrieveTrustManagers(Object trustManagerFactory) {
+        TrustManagerFactory tmf = (TrustManagerFactory) trustManagerFactory;
+        return tmf.getTrustManagers();
+    }
+
+    protected final SSLSocketFactory buildSSLSocketFactory(Object ssl) {
+        return ((SSLContext) ssl).getSocketFactory();
+    }
+
+    protected final SSLServerSocketFactory buildSSLServerSocketFactory(Object ssl) {
+        return ((SSLContext) ssl).getServerSocketFactory();
+    }
+
+    protected final RuntimeException buildRuntimeException(Exception cause) {
+        ByteArrayOutputStream byteOut = new ByteArrayOutputStream(512);
+        PrintStream ps = new PrintStream(byteOut);
+        ps.println(cause.toString());
+        cause.printStackTrace(ps);
+        ps.flush();
+        String originalCause = byteOut.toString();
+        return new RuntimeException(originalCause);
+    }
+
+    protected final SSLSocket buildSocket(SSL ssl) {
+        // Not supported in Java 1.3.
+        throw new UnsupportedOperationException();
+    }
+
+    protected final SSLSocket buildSocket(SSL ssl, String remoteHost,
+                                          int remotePort, InetAddress localHost,
+                                          int localPort, int connectTimeout)
+        throws IOException {
+        // Connect Timeout ignored for Java 1.3
+        SSLSocketFactory sf = ssl.getSSLSocketFactory();
+        SSLSocket s = (SSLSocket) connectSocket(null, sf, remoteHost,
+            remotePort, localHost,
+            localPort, -1);
+        ssl.doPreConnectSocketStuff(s);
+        ssl.doPostConnectSocketStuff(s, remoteHost);
+        return s;
+    }
+
+    protected final Socket connectSocket(Socket s, SocketFactory sf,
+                                         String remoteHost, int remotePort,
+                                         InetAddress localHost, int localPort,
+                                         int timeout)
+        throws IOException {
+        // Connect Timeout ignored for Java 1.3
+        if (s == null) {
+            if (sf == null) {
+                s = new Socket(remoteHost, remotePort, localHost, localPort);
+            } else {
+                s = sf.createSocket(remoteHost, remotePort, localHost, localPort);
+            }
+        }
+        return s;
+    }
+
+
+    protected final SSLServerSocket buildServerSocket(SSL ssl) {
+        // Not supported in Java 1.3.
+        throw new UnsupportedOperationException();
+    }
+
+    protected final void wantClientAuth(Object o, boolean wantClientAuth) {
+        // Not supported in Java 1.3.
+    }
+
+    protected final void enabledProtocols(Object o, String[] enabledProtocols) {
+        // Not supported in Java 1.3.
+    }
+
+    protected void checkTrusted(Object trustManager, X509Certificate[] chain,
+                                String authType)
+        throws CertificateException {
+        X509TrustManager tm = (X509TrustManager) trustManager;
+        boolean result = tm.isServerTrusted(chain);
+        if (!result) {
+            throw new CertificateException("commons-ssl java13 mode: certificate chain not trusted");
+        }
+    }
+
+
+    protected final Object initSSL(SSL ssl, TrustChain tc, KeyMaterial k)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        CertificateException, KeyManagementException, IOException {
+        SSLContext context = SSLContext.getInstance(ssl.getDefaultProtocol());
+        TrustManager[] trustManagers = null;
+        KeyManager[] keyManagers = null;
+        if (tc != null) {
+            trustManagers = (TrustManager[]) tc.getTrustManagers();
+        }
+        if (k != null) {
+            keyManagers = (KeyManager[]) k.getKeyManagers();
+        }
+        if (keyManagers != null) {
+            for (int i = 0; i < keyManagers.length; i++) {
+                if (keyManagers[i] instanceof X509KeyManager) {
+                    X509KeyManager km = (X509KeyManager) keyManagers[i];
+                    keyManagers[i] = new Java13KeyManagerWrapper(km, k, ssl);
+                }
+            }
+        }
+        if (trustManagers != null) {
+            for (int i = 0; i < trustManagers.length; i++) {
+                if (trustManagers[i] instanceof X509TrustManager) {
+                    X509TrustManager tm = (X509TrustManager) trustManagers[i];
+                    trustManagers[i] = new Java13TrustManagerWrapper(tm, tc, ssl);
+                }
+            }
+        }
+        context.init(keyManagers, trustManagers, null);
+        return context;
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/Java13KeyManagerWrapper.java b/src/java/org/apache/commons/ssl/Java13KeyManagerWrapper.java
new file mode 100644
index 0000000..9222496
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Java13KeyManagerWrapper.java
@@ -0,0 +1,82 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java13KeyManagerWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import com.sun.net.ssl.X509KeyManager;
+
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Jun-2006
+ */
+public class Java13KeyManagerWrapper implements X509KeyManager {
+
+    private final X509KeyManager keyManager;
+    // private final KeyMaterial keyMaterial;   <-- maybe use one day in the
+    // private final SSL ssl;                   <-- in the future?
+
+    public Java13KeyManagerWrapper(X509KeyManager m, KeyMaterial km, SSL h) {
+        this.keyManager = m;
+        // this.keyMaterial = km;   <-- maybe use one day in the
+        // this.ssl = h;            <-- in the future?
+    }
+
+    public String chooseClientAlias(String keyType, Principal[] issuers) {
+        return keyManager.chooseClientAlias(keyType, issuers);
+    }
+
+    public String chooseServerAlias(String keyType, Principal[] issuers) {
+        return keyManager.chooseServerAlias(keyType, issuers);
+    }
+
+    public X509Certificate[] getCertificateChain(String alias) {
+        return keyManager.getCertificateChain(alias);
+    }
+
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        return keyManager.getClientAliases(keyType, issuers);
+    }
+
+    public PrivateKey getPrivateKey(String alias) {
+        return keyManager.getPrivateKey(alias);
+    }
+
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        return keyManager.getServerAliases(keyType, issuers);
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/Java13TrustManagerWrapper.java b/src/java/org/apache/commons/ssl/Java13TrustManagerWrapper.java
new file mode 100644
index 0000000..0821015
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Java13TrustManagerWrapper.java
@@ -0,0 +1,99 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java13TrustManagerWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import com.sun.net.ssl.X509TrustManager;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Jun-2006
+ */
+public class Java13TrustManagerWrapper implements X509TrustManager {
+
+    private final X509TrustManager trustManager;
+    private final TrustChain trustChain;
+    private final SSL ssl;
+
+    public Java13TrustManagerWrapper(X509TrustManager m, TrustChain tc, SSL h) {
+        this.trustManager = m;
+        this.trustChain = tc;
+        this.ssl = h;
+    }
+
+    public boolean isClientTrusted(X509Certificate[] chain) {
+        ssl.setCurrentClientChain(chain);
+        boolean firstTest = trustManager.isClientTrusted(chain);
+        return test(firstTest, chain);
+    }
+
+    public boolean isServerTrusted(X509Certificate[] chain) {
+        ssl.setCurrentServerChain(chain);
+        boolean firstTest = trustManager.isServerTrusted(chain);
+        return test(firstTest, chain);
+    }
+
+    public X509Certificate[] getAcceptedIssuers() {
+        return trustManager.getAcceptedIssuers();
+    }
+
+    private boolean test(boolean firstTest, X509Certificate[] chain) {
+        // Even if the first test failed, we might still be okay as long as
+        // this SSLServer or SSLClient is setup to trust all certificates.
+        if (!firstTest) {
+            if (!trustChain.contains(TrustMaterial.TRUST_ALL)) {
+                return false;
+            }
+        }
+
+        try {
+            for (int i = 0; i < chain.length; i++) {
+                X509Certificate c = chain[i];
+                if (ssl.getCheckExpiry()) {
+                    c.checkValidity();
+                }
+                if (ssl.getCheckCRL()) {
+                    Certificates.checkCRL(c);
+                }
+            }
+            return true;
+        }
+        catch (CertificateException ce) {
+            return false;
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/Java14.java b/src/java/org/apache/commons/ssl/Java14.java
new file mode 100644
index 0000000..d416391
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Java14.java
@@ -0,0 +1,258 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java14.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Jun-2006
+ */
+public final class Java14 extends JavaImpl {
+    private static Java14 instance = new Java14();
+
+    private Java14() {
+        try {
+            SSLSocketFactory.getDefault().createSocket();
+        }
+        catch (IOException ioe) {
+            ioe.hashCode();
+        }
+    }
+
+    public static Java14 getInstance() {
+        return instance;
+    }
+
+    public final String getVersion() {
+        return "Java14";
+    }
+
+    protected final String retrieveSubjectX500(X509Certificate cert) {
+        return cert.getSubjectX500Principal().toString();
+    }
+
+    protected final String retrieveIssuerX500(X509Certificate cert) {
+        return cert.getIssuerX500Principal().toString();
+    }
+
+    protected final Certificate[] retrievePeerCerts(SSLSession sslSession)
+        throws SSLPeerUnverifiedException {
+        return sslSession.getPeerCertificates();
+    }
+
+    protected final Object buildKeyManagerFactory(KeyStore ks, char[] password)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        UnrecoverableKeyException {
+        String alg = KeyManagerFactory.getDefaultAlgorithm();
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
+        kmf.init(ks, password);
+        // overwrite password
+        for (int i = 0; i < password.length; i++) {
+            password[i] = '*';
+        }
+        return kmf;
+    }
+
+    protected final Object buildTrustManagerFactory(KeyStore ks)
+        throws NoSuchAlgorithmException, KeyStoreException {
+        String alg = TrustManagerFactory.getDefaultAlgorithm();
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(alg);
+        tmf.init(ks);
+        return tmf;
+    }
+
+    protected final Object[] retrieveKeyManagers(Object keyManagerFactory) {
+        KeyManagerFactory kmf = (KeyManagerFactory) keyManagerFactory;
+        return kmf.getKeyManagers();
+    }
+
+    protected final Object[] retrieveTrustManagers(Object trustManagerFactory) {
+        TrustManagerFactory tmf = (TrustManagerFactory) trustManagerFactory;
+        return tmf.getTrustManagers();
+    }
+
+    protected final SSLSocketFactory buildSSLSocketFactory(Object ssl) {
+        return ((SSLContext) ssl).getSocketFactory();
+    }
+
+    protected final SSLServerSocketFactory buildSSLServerSocketFactory(Object ssl) {
+        return ((SSLContext) ssl).getServerSocketFactory();
+    }
+
+    protected final RuntimeException buildRuntimeException(Exception cause) {
+        return new RuntimeException(cause);
+    }
+
+    protected final SSLSocket buildSocket(SSL ssl) throws IOException {
+        SSLSocketFactory sf = ssl.getSSLSocketFactory();
+        SSLSocket s = (SSLSocket) sf.createSocket();
+        ssl.doPreConnectSocketStuff(s);
+        return s;
+    }
+
+    protected final SSLSocket buildSocket(SSL ssl, String remoteHost,
+                                          int remotePort, InetAddress localHost,
+                                          int localPort, int timeout)
+        throws IOException {
+        SSLSocket s = buildSocket(ssl);
+        s = (SSLSocket) connectSocket(s, null, remoteHost, remotePort,
+            localHost, localPort, timeout);
+        ssl.doPostConnectSocketStuff(s, remoteHost);
+        return s;
+    }
+
+    protected final Socket connectSocket(Socket s, SocketFactory sf,
+                                         String remoteHost, int remotePort,
+                                         InetAddress localHost, int localPort,
+                                         int timeout)
+        throws IOException {
+        if (s == null) {
+            if (sf == null) {
+                s = new Socket();
+            } else {
+                s = sf.createSocket();
+            }
+        }
+        InetSocketAddress dest = new InetSocketAddress(remoteHost, remotePort);
+        InetSocketAddress src = new InetSocketAddress(localHost, localPort);
+        s.bind(src);
+        s.connect(dest, timeout);
+        return s;
+    }
+
+    protected final SSLServerSocket buildServerSocket(SSL ssl)
+        throws IOException {
+        ServerSocket s = ssl.getSSLServerSocketFactory().createServerSocket();
+        SSLServerSocket ss = (SSLServerSocket) s;
+        ssl.doPreConnectServerSocketStuff(ss);
+        return ss;
+    }
+
+    protected final void wantClientAuth(Object o, boolean wantClientAuth) {
+        SSLSocket s;
+        SSLServerSocket ss;
+        if (o instanceof SSLSocket) {
+            s = (SSLSocket) o;
+            s.setWantClientAuth(wantClientAuth);
+        } else if (o instanceof SSLServerSocket) {
+            ss = (SSLServerSocket) o;
+            ss.setWantClientAuth(wantClientAuth);
+        } else {
+            throw new ClassCastException("need SSLSocket or SSLServerSocket");
+        }
+    }
+
+    protected final void enabledProtocols(Object o, String[] enabledProtocols) {
+        SSLSocket s;
+        SSLServerSocket ss;
+        if (o instanceof SSLSocket) {
+            s = (SSLSocket) o;
+            s.setEnabledProtocols(enabledProtocols);
+        } else if (o instanceof SSLServerSocket) {
+            ss = (SSLServerSocket) o;
+            ss.setEnabledProtocols(enabledProtocols);
+        } else {
+            throw new ClassCastException("need SSLSocket or SSLServerSocket");
+        }
+    }
+
+    protected void checkTrusted(Object trustManager, X509Certificate[] chain,
+                                String authType)
+        throws CertificateException {
+        X509TrustManager tm = (X509TrustManager) trustManager;
+        tm.checkServerTrusted(chain, authType);
+    }
+
+    protected final Object initSSL(SSL ssl, TrustChain tc, KeyMaterial k)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        CertificateException, KeyManagementException, IOException {
+        SSLContext context = SSLContext.getInstance(ssl.getDefaultProtocol());
+        TrustManager[] trustManagers = null;
+        KeyManager[] keyManagers = null;
+        if (tc != null) {
+            trustManagers = (TrustManager[]) tc.getTrustManagers();
+        }
+        if (k != null) {
+            keyManagers = (KeyManager[]) k.getKeyManagers();
+        }
+        if (keyManagers != null) {
+            for (int i = 0; i < keyManagers.length; i++) {
+                if (keyManagers[i] instanceof X509KeyManager) {
+                    X509KeyManager km = (X509KeyManager) keyManagers[i];
+                    keyManagers[i] = new Java14KeyManagerWrapper(km, k, ssl);
+                }
+            }
+        }
+        if (trustManagers != null) {
+            for (int i = 0; i < trustManagers.length; i++) {
+                if (trustManagers[i] instanceof X509TrustManager) {
+                    X509TrustManager tm = (X509TrustManager) trustManagers[i];
+                    trustManagers[i] = new Java14TrustManagerWrapper(tm, tc, ssl);
+                }
+            }
+        }
+        context.init(keyManagers, trustManagers, null);
+        return context;
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/Java14KeyManagerWrapper.java b/src/java/org/apache/commons/ssl/Java14KeyManagerWrapper.java
new file mode 100644
index 0000000..2f8f03d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Java14KeyManagerWrapper.java
@@ -0,0 +1,82 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java14KeyManagerWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.X509KeyManager;
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Mar-2006
+ */
+public class Java14KeyManagerWrapper implements X509KeyManager {
+    private final X509KeyManager keyManager;
+    // private final KeyMaterial keyMaterial;
+    // private final SSL ssl;
+
+    public Java14KeyManagerWrapper(X509KeyManager m, KeyMaterial km, SSL h) {
+        this.keyManager = m;
+        // this.keyMaterial = km;
+        // this.ssl = h;
+    }
+
+    public String chooseClientAlias(String[] keyType, Principal[] issuers,
+                                    Socket socket) {
+        return keyManager.chooseClientAlias(keyType, issuers, socket);
+    }
+
+    public String chooseServerAlias(String keyType, Principal[] issuers,
+                                    Socket socket) {
+        return keyManager.chooseServerAlias(keyType, issuers, socket);
+    }
+
+    public X509Certificate[] getCertificateChain(String alias) {
+        return keyManager.getCertificateChain(alias);
+    }
+
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        return keyManager.getClientAliases(keyType, issuers);
+    }
+
+    public PrivateKey getPrivateKey(String alias) {
+        return keyManager.getPrivateKey(alias);
+    }
+
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        return keyManager.getServerAliases(keyType, issuers);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/Java14TrustManagerWrapper.java b/src/java/org/apache/commons/ssl/Java14TrustManagerWrapper.java
new file mode 100644
index 0000000..93f0ac6
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Java14TrustManagerWrapper.java
@@ -0,0 +1,128 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Java14TrustManagerWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Mar-2006
+ */
+public class Java14TrustManagerWrapper implements X509TrustManager {
+    private final X509TrustManager trustManager;
+    private final TrustChain trustChain;
+    private final SSL ssl;
+
+    public Java14TrustManagerWrapper(X509TrustManager m, TrustChain tc, SSL h) {
+        this.trustManager = m;
+        this.trustChain = tc;
+        this.ssl = h;
+    }
+
+    public void checkClientTrusted(X509Certificate[] chain, String authType)
+        throws CertificateException {
+        ssl.setCurrentClientChain(chain);
+        CertificateException ce = null;
+        try {
+            trustManager.checkClientTrusted(chain, authType);
+        }
+        catch (CertificateException e) {
+            ce = e;
+        }
+        testShouldWeThrow(ce, chain);
+    }
+
+    public void checkServerTrusted(X509Certificate[] chain, String authType)
+        throws CertificateException {
+        ssl.setCurrentServerChain(chain);
+        CertificateException ce = null;
+        try {
+            trustManager.checkServerTrusted(chain, authType);
+        }
+        catch (CertificateException e) {
+            ce = e;
+        }
+        testShouldWeThrow(ce, chain);
+    }
+
+    public X509Certificate[] getAcceptedIssuers() {
+        return trustManager.getAcceptedIssuers();
+    }
+
+    private void testShouldWeThrow(CertificateException checkException,
+                                   X509Certificate[] chain)
+        throws CertificateException {
+        if (checkException != null) {
+            Throwable root = getRootThrowable(checkException);
+            boolean expiryProblem = root instanceof CertificateExpiredException;
+            if (expiryProblem) {
+                if (ssl.getCheckExpiry()) {
+                    // We're expired, and this factory cares.
+                    throw checkException;
+                }
+            } else {
+                // Probably the cert isn't trusted.  Only let it through if
+                // this factory trusts everything.
+                if (!trustChain.contains(TrustMaterial.TRUST_ALL)) {
+                    throw checkException;
+                }
+            }
+        }
+
+        for (int i = 0; i < chain.length; i++) {
+            X509Certificate c = chain[i];
+            if (ssl.getCheckExpiry()) {
+                c.checkValidity();
+            }
+            if (ssl.getCheckCRL()) {
+                Certificates.checkCRL(c);
+            }
+        }
+    }
+
+    private static Throwable getRootThrowable(Throwable t) {
+        if (t == null) {
+            return t;
+        }
+        Throwable cause = t.getCause();
+        while (cause != null && !t.equals(cause)) {
+            t = cause;
+            cause = t.getCause();
+        }
+        return t;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/JavaImpl.java b/src/java/org/apache/commons/ssl/JavaImpl.java
new file mode 100644
index 0000000..b189fb2
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/JavaImpl.java
@@ -0,0 +1,245 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/JavaImpl.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Jun-2006
+ */
+public abstract class JavaImpl {
+    private static JavaImpl HANDLER;
+
+    static {
+        JavaImpl h = null;
+        try {
+            h = Java14.getInstance();
+        }
+        catch (Throwable t) {
+            // System.out.println( t.toString() );
+            System.out.println("commons-ssl reverting to: Java 1.3 + jsse.jar");
+        }
+        if (h == null) {
+            h = Java13.getInstance();
+        }
+        HANDLER = h;
+    }
+
+    public static void downgrade() {
+        if (HANDLER instanceof Java14) {
+            HANDLER = Java13.getInstance();
+        }
+    }
+
+    public static boolean isJava13() {
+        return HANDLER instanceof Java13;
+    }
+
+    public static void uprade() {
+        if (HANDLER instanceof Java13) {
+            HANDLER = Java14.getInstance();
+        }
+    }
+
+    public abstract String getVersion();
+
+    protected abstract Object buildKeyManagerFactory(KeyStore ks, char[] pass)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        UnrecoverableKeyException;
+
+    protected abstract Object[] retrieveKeyManagers(Object keyManagerFactory);
+
+    protected abstract Object buildTrustManagerFactory(KeyStore ks)
+        throws NoSuchAlgorithmException, KeyStoreException;
+
+    protected abstract Object[] retrieveTrustManagers(Object trustManagerFactory);
+
+    protected abstract String retrieveSubjectX500(X509Certificate cert);
+
+    protected abstract String retrieveIssuerX500(X509Certificate cert);
+
+    protected abstract Certificate[] retrievePeerCerts(SSLSession sslSession)
+        throws SSLPeerUnverifiedException;
+
+    protected abstract SSLSocketFactory buildSSLSocketFactory(Object ssl);
+
+    protected abstract SSLServerSocketFactory buildSSLServerSocketFactory(Object ssl);
+
+    protected abstract SSLSocket buildSocket(SSL ssl)
+        throws IOException;
+
+    protected abstract SSLSocket buildSocket(SSL ssl, String remoteHost,
+                                             int remotePort,
+                                             InetAddress localHost,
+                                             int localPort, int connectTimeout)
+        throws IOException;
+
+    protected abstract Socket connectSocket(Socket s, SocketFactory sf,
+                                            String remoteHost, int remotePort,
+                                            InetAddress localHost, int localPort,
+                                            int timeout)
+        throws IOException;
+
+    protected abstract SSLServerSocket buildServerSocket(SSL ssl)
+        throws IOException;
+
+    protected abstract void wantClientAuth(Object o, boolean wantClientAuth);
+
+    protected abstract void enabledProtocols(Object o, String[] enabledProtocols);
+
+    protected abstract RuntimeException buildRuntimeException(Exception cause);
+
+    protected abstract Object initSSL(SSL ssl, TrustChain tc, KeyMaterial km)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        CertificateException, KeyManagementException, IOException;
+
+    protected abstract void checkTrusted(Object trustManager,
+                                         X509Certificate[] chain,
+                                         String authType)
+        throws CertificateException;
+
+    public static Object init(SSL ssl, TrustChain trustChain, KeyMaterial keyMaterial)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        CertificateException, KeyManagementException, IOException {
+        return HANDLER.initSSL(ssl, trustChain, keyMaterial);
+    }
+
+    public static RuntimeException newRuntimeException(Exception cause) {
+        return HANDLER.buildRuntimeException(cause);
+    }
+
+    public static SSLSocketFactory getSSLSocketFactory(Object sslContext) {
+        return HANDLER.buildSSLSocketFactory(sslContext);
+    }
+
+    public static SSLServerSocketFactory getSSLServerSocketFactory(Object sslContext) {
+        return HANDLER.buildSSLServerSocketFactory(sslContext);
+    }
+
+    public static String getSubjectX500(X509Certificate cert) {
+        return HANDLER.retrieveSubjectX500(cert);
+    }
+
+    public static String getIssuerX500(X509Certificate cert) {
+        return HANDLER.retrieveIssuerX500(cert);
+    }
+
+    public static Object newKeyManagerFactory(KeyStore ks, char[] password)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        UnrecoverableKeyException {
+        return HANDLER.buildKeyManagerFactory(ks, password);
+    }
+
+    public static Object[] getKeyManagers(Object keyManagerFactory) {
+        return HANDLER.retrieveKeyManagers(keyManagerFactory);
+    }
+
+    public static Object newTrustManagerFactory(KeyStore ks)
+        throws NoSuchAlgorithmException, KeyStoreException {
+        return HANDLER.buildTrustManagerFactory(ks);
+    }
+
+    public static Object[] getTrustManagers(Object trustManagerFactory) {
+        return HANDLER.retrieveTrustManagers(trustManagerFactory);
+    }
+
+    public static SSLSocket createSocket(SSL ssl)
+        throws IOException {
+        return HANDLER.buildSocket(ssl);
+    }
+
+    public static SSLSocket createSocket(SSL ssl, String remoteHost,
+                                         int remotePort, InetAddress localHost,
+                                         int localPort, int connectTimeout)
+        throws IOException {
+        return HANDLER.buildSocket(ssl, remoteHost, remotePort, localHost,
+            localPort, connectTimeout);
+    }
+
+    protected static Socket connect(Socket s, SocketFactory sf,
+                                    String remoteHost, int remotePort,
+                                    InetAddress localHost, int localPort,
+                                    int timeout)
+        throws IOException {
+        return HANDLER.connectSocket(s, sf, remoteHost, remotePort, localHost,
+            localPort, timeout);
+    }
+
+    public static SSLServerSocket createServerSocket(SSL ssl)
+        throws IOException {
+        return HANDLER.buildServerSocket(ssl);
+    }
+
+    public static void setWantClientAuth(Object o, boolean wantClientAuth) {
+        HANDLER.wantClientAuth(o, wantClientAuth);
+    }
+
+    public static void setEnabledProtocols(Object o, String[] enabledProtocols) {
+        HANDLER.enabledProtocols(o, enabledProtocols);
+    }
+
+    public static Certificate[] getPeerCertificates(SSLSession session)
+        throws SSLPeerUnverifiedException {
+        return HANDLER.retrievePeerCerts(session);
+    }
+
+    public static void testTrust(Object trustManager, X509Certificate[] chain,
+                                 String authType)
+        throws CertificateException {
+        HANDLER.checkTrusted(trustManager, chain, authType);
+    }
+
+    public static void load() {
+        HANDLER.hashCode();
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/KeyMaterial.java b/src/java/org/apache/commons/ssl/KeyMaterial.java
new file mode 100644
index 0000000..fcfc9a3
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/KeyMaterial.java
@@ -0,0 +1,201 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/KeyMaterial.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 27-Feb-2006
+ */
+public class KeyMaterial extends TrustMaterial {
+    private final Object keyManagerFactory;
+    private final String alias;
+    private final X509Certificate[] associatedChain;
+
+    public KeyMaterial(InputStream jks, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(Util.streamToBytes(jks), password);
+    }
+
+    public KeyMaterial(InputStream jks, InputStream key, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(jks != null ? Util.streamToBytes(jks) : null,
+            key != null ? Util.streamToBytes(key) : null,
+            password);
+    }
+
+    public KeyMaterial(String pathToJksFile, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(new File(pathToJksFile), password);
+    }
+
+    public KeyMaterial(String pathToCerts, String pathToKey, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(pathToCerts != null ? new File(pathToCerts) : null,
+            pathToKey != null ? new File(pathToKey) : null,
+            password);
+    }
+
+    public KeyMaterial(File jksFile, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(new FileInputStream(jksFile), password);
+    }
+
+    public KeyMaterial(File certsFile, File keyFile, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(certsFile != null ? new FileInputStream(certsFile) : null,
+            keyFile != null ? new FileInputStream(keyFile) : null,
+            password);
+    }
+
+
+    public KeyMaterial(URL urlToJKS, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(urlToJKS.openStream(), password);
+    }
+
+    public KeyMaterial(URL urlToCerts, URL urlToKey, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(urlToCerts.openStream(), urlToKey.openStream(), password);
+    }
+
+    public KeyMaterial(byte[] jks, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(jks, null, password);
+    }
+
+    public KeyMaterial(byte[] jksOrCerts, byte[] key, char[] password)
+        throws GeneralSecurityException, IOException {
+        // We're not a simple trust type, so set "simpleTrustType" value to 0.
+        // Only TRUST_ALL and TRUST_THIS_JVM are simple trust types.
+        super(KeyStoreBuilder.build(jksOrCerts, key, password), 0);
+        KeyStore ks = getKeyStore();
+        Enumeration en = ks.aliases();
+        String myAlias = null;
+        X509Certificate[] myChain;
+        while (en.hasMoreElements()) {
+            String alias = (String) en.nextElement();
+            if (ks.isKeyEntry(alias)) {
+                if (myAlias != null) {
+                    throw new KeyStoreException("commons-ssl KeyMaterial only supports keystores with a single private key.");
+                }
+                myAlias = alias;
+            }
+        }
+        if (myAlias != null) {
+            Certificate[] chain = ks.getCertificateChain(myAlias);
+            if (chain != null) {
+                myChain = Certificates.x509ifyChain(chain);
+            } else {
+                // is password wrong?
+                throw new KeyStoreException("Could not find KeyMaterial's associated certificate chain!");
+            }
+        } else {
+            throw new KeyStoreException("KeyMaterial provided does not contain any keys!");
+        }
+        this.alias = myAlias;
+        // Cleanup chain to remove any spurious entries.
+        if (myChain != null) {
+            myChain = X509CertificateChainBuilder.buildPath(myChain[0], myChain);
+        }
+        this.associatedChain = myChain;
+        this.keyManagerFactory = JavaImpl.newKeyManagerFactory(ks, password);
+    }
+
+    public Object[] getKeyManagers() {
+        return JavaImpl.getKeyManagers(keyManagerFactory);
+    }
+
+    public X509Certificate[] getAssociatedCertificateChain() {
+        return associatedChain;
+    }
+
+    public KeyStore getKeyStore() {
+        return super.getKeyStore();
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args.length < 2) {
+            System.out.println("Usage1:  java org.apache.commons.ssl.KeyMaterial [password] [pkcs12 or jks]");
+            System.out.println("Usage2:  java org.apache.commons.ssl.KeyMaterial [password] [private-key] [cert-chain]");
+            System.exit(1);
+        }
+        char[] password = args[0].toCharArray();
+        String path1 = args[1];
+        String path2 = null;
+        if (args.length >= 3) {
+            path2 = args[2];
+        }
+
+        KeyMaterial km = new KeyMaterial(path1, path2, password);
+        System.out.println(km);
+    }
+
+    public String toString() {
+        X509Certificate[] certs = getAssociatedCertificateChain();
+        StringBuffer buf = new StringBuffer(1024);
+        buf.append("Alias: ");
+        buf.append(alias);
+        buf.append('\n');
+        if (certs != null) {
+            for (int i = 0; i < certs.length; i++) {
+                buf.append(Certificates.toString(certs[i]));
+                try {
+                    buf.append(Certificates.toPEMString(certs[i]));
+                }
+                catch (CertificateEncodingException cee) {
+                    buf.append(cee.toString());
+                    buf.append('\n');
+                }
+            }
+        }
+        return buf.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/KeyStoreBuilder.java b/src/java/org/apache/commons/ssl/KeyStoreBuilder.java
new file mode 100644
index 0000000..ab5008b
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/KeyStoreBuilder.java
@@ -0,0 +1,625 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/KeyStoreBuilder.java $
+ * $Revision: 129 $
+ * $Date: 2007-11-14 19:21:33 -0800 (Wed, 14 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.asn1.ASN1EncodableVector;
+import org.apache.commons.ssl.asn1.DERInteger;
+import org.apache.commons.ssl.asn1.DERSequence;
+import org.apache.commons.ssl.util.Hex;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Builds Java Key Store files out of pkcs12 files, or out of pkcs8 files +
+ * certificate chains.  Also supports OpenSSL style private keys (encrypted or
+ * unencrypted).
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 4-Nov-2006
+ */
+public class KeyStoreBuilder {
+    private final static String PKCS7_ENCRYPTED = "1.2.840.113549.1.7.6";
+
+    public static KeyStore build(byte[] jksOrCerts, char[] password)
+        throws IOException, CertificateException, KeyStoreException,
+        NoSuchAlgorithmException, InvalidKeyException,
+        NoSuchProviderException, ProbablyBadPasswordException,
+        UnrecoverableKeyException {
+        return build(jksOrCerts, null, password);
+    }
+
+    public static KeyStore build(byte[] jksOrCerts, byte[] privateKey,
+                                 char[] password)
+        throws IOException, CertificateException, KeyStoreException,
+        NoSuchAlgorithmException, InvalidKeyException,
+        NoSuchProviderException, ProbablyBadPasswordException,
+        UnrecoverableKeyException {
+        BuildResult br1 = parse(jksOrCerts, password);
+        BuildResult br2 = null;
+        KeyStore jks = null;
+        if (br1.jks != null) {
+            jks = br1.jks;
+        } else if (privateKey != null && privateKey.length > 0) {
+            br2 = parse(privateKey, password);
+            if (br2.jks != null) {
+                jks = br2.jks;
+            }
+        }
+
+        // If we happened to find a JKS file, let's just return that.
+        // JKS files get priority (in case some weirdo specifies both a PKCS12
+        // and a JKS file!).
+        if (jks != null) {
+            // Make sure the keystore we found is not corrupt.
+            validate(jks, password);
+            return jks;
+        }
+
+        Key key = br1.key;
+        X509Certificate[] chain = br1.chain;
+        boolean atLeastOneNotSet = key == null || chain == null;
+        if (atLeastOneNotSet && br2 != null) {
+            if (br2.key != null) {
+                // Notice that the key from build-result-2 gets priority over the
+                // key from build-result-1 (if both had valid keys).
+                key = br2.key;
+            }
+            if (chain == null) {
+                chain = br2.chain;
+            }
+        }
+
+        atLeastOneNotSet = key == null || chain == null;
+        if (atLeastOneNotSet) {
+            String missing = "";
+            if (key == null) {
+                missing = " [Private key missing (bad password?)]";
+            }
+            if (chain == null) {
+                missing += " [Certificate chain missing]";
+            }
+            throw new KeyStoreException("Can't build keystore:" + missing);
+        } else {
+
+            X509Certificate theOne = buildChain(key, chain);
+            String alias = "alias";
+            // The theOne is not null, then our chain was probably altered.
+            // Need to trim out the newly introduced null entries at the end of
+            // our chain.
+            if (theOne != null) {
+                chain = Certificates.trimChain(chain);
+                alias = Certificates.getCN(theOne);
+                alias = alias.replace(' ', '_');
+            }
+
+            KeyStore ks = KeyStore.getInstance("jks");
+            ks.load(null, password);
+            ks.setKeyEntry(alias, key, password, chain);
+            return ks;
+        }
+    }
+
+    /**
+     * Builds the chain up such that chain[ 0 ] contains the public key
+     * corresponding to the supplied private key.
+     *
+     * @param key   private key
+     * @param chain array of certificates to build chain from
+     * @return theOne!
+     * @throws KeyStoreException        no certificates correspond to private key
+     * @throws CertificateException     java libraries complaining
+     * @throws NoSuchAlgorithmException java libraries complaining
+     * @throws InvalidKeyException      java libraries complaining
+     * @throws NoSuchProviderException  java libraries complaining
+     */
+    public static X509Certificate buildChain(Key key, Certificate[] chain)
+        throws CertificateException, KeyStoreException,
+        NoSuchAlgorithmException, InvalidKeyException,
+        NoSuchProviderException {
+        X509Certificate theOne = null;
+        if (key instanceof RSAPrivateCrtKey) {
+            final RSAPrivateCrtKey rsa = (RSAPrivateCrtKey) key;
+            BigInteger publicExponent = rsa.getPublicExponent();
+            BigInteger modulus = rsa.getModulus();
+            for (int i = 0; i < chain.length; i++) {
+                X509Certificate c = (X509Certificate) chain[i];
+                PublicKey pub = c.getPublicKey();
+                if (pub instanceof RSAPublicKey) {
+                    RSAPublicKey certKey = (RSAPublicKey) pub;
+                    BigInteger pe = certKey.getPublicExponent();
+                    BigInteger mod = certKey.getModulus();
+                    if (publicExponent.equals(pe) && modulus.equals(mod)) {
+                        theOne = c;
+                    }
+                }
+            }
+            if (theOne == null) {
+                throw new KeyStoreException("Can't build keystore: [No certificates belong to the private-key]");
+            }
+            X509Certificate[] newChain;
+            newChain = X509CertificateChainBuilder.buildPath(theOne, chain);
+            Arrays.fill(chain, null);
+            System.arraycopy(newChain, 0, chain, 0, newChain.length);
+        }
+        return theOne;
+    }
+
+    public static void validate(KeyStore jks, char[] password)
+        throws CertificateException, KeyStoreException,
+        NoSuchAlgorithmException, InvalidKeyException,
+        NoSuchProviderException, UnrecoverableKeyException {
+        Enumeration en = jks.aliases();
+        String privateKeyAlias = null;
+        while (en.hasMoreElements()) {
+            String alias = (String) en.nextElement();
+            boolean isKey = jks.isKeyEntry(alias);
+            if (isKey) {
+                if (privateKeyAlias != null) {
+                    throw new KeyStoreException("Only 1 private key per keystore allowed for Commons-SSL");
+                } else {
+                    privateKeyAlias = alias;
+                }
+            }
+        }
+        if (privateKeyAlias == null) {
+            throw new KeyStoreException("No private keys found in keystore!");
+        }
+        PrivateKey key = (PrivateKey) jks.getKey(privateKeyAlias, password);
+        Certificate[] chain = jks.getCertificateChain(privateKeyAlias);
+        X509Certificate[] x509Chain = Certificates.x509ifyChain(chain);
+        X509Certificate theOne = buildChain(key, x509Chain);
+        // The theOne is not null, then our chain was probably altered.
+        // Need to trim out the newly introduced null entries at the end of
+        // our chain.
+        if (theOne != null) {
+            x509Chain = Certificates.trimChain(x509Chain);
+            jks.deleteEntry(privateKeyAlias);
+            jks.setKeyEntry(privateKeyAlias, key, password, x509Chain);
+        }
+    }
+
+    protected static class BuildResult {
+        protected final Key key;
+        protected final X509Certificate[] chain;
+        protected final KeyStore jks;
+
+        protected BuildResult(Key key, Certificate[] chain, KeyStore jks) {
+            this.key = key;
+            this.jks = jks;
+            if (chain == null) {
+                this.chain = null;
+            } else if (chain instanceof X509Certificate[]) {
+                this.chain = (X509Certificate[]) chain;
+            } else {
+                X509Certificate[] x509 = new X509Certificate[chain.length];
+                System.arraycopy(chain, 0, x509, 0, chain.length);
+                this.chain = x509;
+            }
+        }
+    }
+
+
+    public static BuildResult parse(byte[] stuff, char[] password)
+        throws IOException, CertificateException, KeyStoreException,
+        ProbablyBadPasswordException {
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        Key key = null;
+        Certificate[] chain = null;
+        try {
+            PKCS8Key pkcs8Key = new PKCS8Key(stuff, password);
+            key = pkcs8Key.getPrivateKey();
+        }
+        catch (ProbablyBadPasswordException pbpe) {
+            throw pbpe;
+        }
+        catch (GeneralSecurityException gse) {
+            // no luck
+        }
+
+        List pemItems = PEMUtil.decode(stuff);
+        Iterator it = pemItems.iterator();
+        LinkedList certificates = new LinkedList();
+        while (it.hasNext()) {
+            PEMItem item = (PEMItem) it.next();
+            byte[] derBytes = item.getDerBytes();
+            String type = item.pemType.trim().toUpperCase();
+            if (type.startsWith("CERT") ||
+                type.startsWith("X509") ||
+                type.startsWith("PKCS7")) {
+                ByteArrayInputStream in = new ByteArrayInputStream(derBytes);
+                X509Certificate c = (X509Certificate) cf.generateCertificate(in);
+                certificates.add(c);
+            }
+            chain = toChain(certificates);
+        }
+
+        if (chain != null || key != null) {
+            return new BuildResult(key, chain, null);
+        }
+
+        boolean isProbablyPKCS12 = false;
+        boolean isASN = false;
+        boolean isProbablyJKS = stuff.length >= 4 &&
+                                stuff[0] == (byte) 0xFE &&
+                                stuff[1] == (byte) 0xED &&
+                                stuff[2] == (byte) 0xFE &&
+                                stuff[3] == (byte) 0xED;
+
+        ASN1Structure asn1 = null;
+        try {
+            asn1 = ASN1Util.analyze(stuff);
+            isASN = true;
+            isProbablyPKCS12 = asn1.oids.contains(PKCS7_ENCRYPTED);
+            if (!isProbablyPKCS12 && asn1.bigPayload != null) {
+                asn1 = ASN1Util.analyze(asn1.bigPayload);
+                isProbablyPKCS12 = asn1.oids.contains(PKCS7_ENCRYPTED);
+            }
+        }
+        catch (Exception e) {
+            // isProbablyPKCS12 and isASN are set properly by now.
+        }
+
+        ByteArrayInputStream stuffStream = new ByteArrayInputStream(stuff);
+        if (isProbablyJKS) {
+            try {
+                return tryJKS("jks", stuffStream, password);
+            }
+            catch (ProbablyBadPasswordException pbpe) {
+                throw pbpe;
+            }
+            catch (GeneralSecurityException gse) {
+                // jks didn't work.
+            }
+            catch (IOException ioe) {
+                // jks didn't work.
+            }
+        }
+        if (isASN) {
+            if (isProbablyPKCS12) {
+                try {
+                    return tryJKS("pkcs12", stuffStream, password);
+                }
+                catch (ProbablyBadPasswordException pbpe) {
+                    throw pbpe;
+                }
+                catch (GeneralSecurityException gse) {
+                    // pkcs12 didn't work.
+                }
+                catch (IOException ioe) {
+                    // pkcs12 didn't work.
+                }
+            } else {
+                // Okay, it's ASN.1, but it's not PKCS12.  Only one possible
+                // interesting things remains:  X.509.
+                stuffStream.reset();
+
+                try {
+                    certificates = new LinkedList();
+                    Collection certs = cf.generateCertificates(stuffStream);
+                    it = certs.iterator();
+                    while (it.hasNext()) {
+                        X509Certificate x509 = (X509Certificate) it.next();
+                        certificates.add(x509);
+                    }
+                    chain = toChain(certificates);
+                    if (chain != null && chain.length > 0) {
+                        return new BuildResult(null, chain, null);
+                    }
+                }
+                catch (CertificateException ce) {
+                    // oh well
+                }
+
+                stuffStream.reset();
+                // Okay, still no luck.  Maybe it's an ASN.1 DER stream
+                // containing only a single certificate?  (I don't completely
+                // trust CertificateFactory.generateCertificates).
+                try {
+                    Certificate c = cf.generateCertificate(stuffStream);
+                    X509Certificate x509 = (X509Certificate) c;
+                    chain = toChain(Collections.singleton(x509));
+                    if (chain != null && chain.length > 0) {
+                        return new BuildResult(null, chain, null);
+                    }
+                }
+                catch (CertificateException ce) {
+                    // oh well
+                }
+            }
+        }
+
+        if (!isProbablyJKS) {
+            String hex = Hex.encode(stuff, 0, 4);
+            try {
+                BuildResult br = tryJKS("jks", stuffStream, password);
+                // no exception thrown, so must be JKS.
+                System.out.println("Please report bug!");
+                System.out.println("JKS usually start with binary FE ED FE ED, but this JKS started with: [" + hex + "]");
+                return br;
+            }
+            catch (ProbablyBadPasswordException pbpe) {
+                System.out.println("Please report bug!");
+                System.out.println("JKS usually start with binary FE ED FE ED, but this JKS started with: [" + hex + "]");
+                throw pbpe;
+            }
+            catch (GeneralSecurityException gse) {
+                // jks didn't work.
+            }
+            catch (IOException ioe) {
+                // jks didn't work.
+            }
+        }
+
+        if (!isProbablyPKCS12) {
+            try {
+                BuildResult br = tryJKS("pkcs12", stuffStream, password);
+                // no exception thrown, so must be PKCS12.
+                System.out.println("Please report bug!");
+                System.out.println("PKCS12 detection failed to realize this was PKCS12!");
+                System.out.println(asn1);
+                return br;
+            }
+            catch (ProbablyBadPasswordException pbpe) {
+                System.out.println("Please report bug!");
+                System.out.println("PKCS12 detection failed to realize this was PKCS12!");
+                System.out.println(asn1);
+                throw pbpe;
+            }
+            catch (GeneralSecurityException gse) {
+                // pkcs12 didn't work.
+            }
+            catch (IOException ioe) {
+                // pkcs12 didn't work.
+            }
+        }
+        throw new KeyStoreException("failed to extract any certificates or private keys - maybe bad password?");
+    }
+
+    private static BuildResult tryJKS(String keystoreType,
+                                      ByteArrayInputStream in,
+                                      char[] password)
+        throws GeneralSecurityException, IOException {
+        in.reset();
+        keystoreType = keystoreType.trim().toLowerCase();
+        boolean isPKCS12 = "pkcs12".equals(keystoreType);
+        KeyStore jksKeyStore = KeyStore.getInstance(keystoreType);
+        try {
+            Key key = null;
+            Certificate[] chain = null;
+            jksKeyStore.load(in, password);
+            Enumeration en = jksKeyStore.aliases();
+            while (en.hasMoreElements()) {
+                String alias = (String) en.nextElement();
+                if (jksKeyStore.isKeyEntry(alias)) {
+                    key = jksKeyStore.getKey(alias, password);
+                    if (key != null && key instanceof PrivateKey) {
+                        chain = jksKeyStore.getCertificateChain(alias);
+                        break;
+                    }
+                }
+                if (isPKCS12 && en.hasMoreElements()) {
+                    System.out.println("what kind of weird pkcs12 file has more than one alias?");
+                }
+            }
+            if (isPKCS12) {
+                // PKCS12 is supposed to be just a key and a chain, anyway.
+                jksKeyStore = null;
+            }
+            return new BuildResult(key, chain, jksKeyStore);
+        }
+        catch (GeneralSecurityException gse) {
+            throw gse;
+        }
+        catch (IOException ioe) {
+            ioe.printStackTrace();
+
+            String msg = ioe.getMessage();
+            msg = msg != null ? msg.trim().toLowerCase() : "";
+            if (isPKCS12) {
+                int x = msg.indexOf("failed to decrypt");
+                int y = msg.indexOf("verify mac");
+                x = Math.max(x, y);
+                if (x >= 0) {
+                    throw new ProbablyBadPasswordException("Probably bad PKCS12 password: " + ioe);
+                }
+            } else {
+                int x = msg.indexOf("password");
+                if (x >= 0) {
+                    throw new ProbablyBadPasswordException("Probably bad JKS password: " + ioe);
+                }
+            }
+            ioe.printStackTrace();
+            throw ioe;
+        }
+    }
+
+    private static X509Certificate[] toChain(Collection certs) {
+        if (certs != null && !certs.isEmpty()) {
+            X509Certificate[] x509Chain = new X509Certificate[certs.size()];
+            certs.toArray(x509Chain);
+            return x509Chain;
+        } else {
+            return null;
+        }
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        if (args.length < 2) {
+            System.out.println("KeyStoreBuilder:  creates '[alias].jks' (Java Key Store)");
+            System.out.println("    -topk8 mode:  creates '[alias].pem' (x509 chain + unencrypted pkcs8)");
+            System.out.println("[alias] will be set to the first CN value of the X509 certificate.");
+            System.out.println("-------------------------------------------------------------------");
+            System.out.println("Usage1: [password] [file:pkcs12]");
+            System.out.println("Usage2: [password] [file:private-key] [file:certificate-chain]");
+            System.out.println("Usage3: -topk8 [password] [file:jks]");
+            System.out.println("-------------------------------------------------------------------");
+            System.out.println("[private-key] can be openssl format, or pkcs8.");
+            System.out.println("[password] decrypts [private-key], and also encrypts outputted JKS file.");
+            System.out.println("All files can be PEM or DER.");
+            System.exit(1);
+        }
+        char[] password = args[0].toCharArray();
+        boolean toPKCS8 = false;
+        if ("-topk8".equalsIgnoreCase(args[0])) {
+            toPKCS8 = true;
+            password = args[1].toCharArray();
+            args[1] = args[2];
+            args[2] = null;
+        }
+
+        FileInputStream fin1 = new FileInputStream(args[1]);
+        byte[] bytes1 = Util.streamToBytes(fin1);
+        byte[] bytes2 = null;
+        if (args.length > 2 && args[2] != null) {
+            FileInputStream fin2 = new FileInputStream(args[2]);
+            bytes2 = Util.streamToBytes(fin2);
+        }
+
+        KeyStore ks = build(bytes1, bytes2, password);
+        Enumeration en = ks.aliases();
+        String alias = null;
+        while (en.hasMoreElements()) {
+            if (alias == null) {
+                alias = (String) en.nextElement();
+            } else {
+                System.out.println("Generated keystore contains more than 1 alias!?!?");
+            }
+        }
+
+        String suffix = toPKCS8 ? ".pem" : ".jks";
+        File f = new File(alias + suffix);
+        int count = 1;
+        while (f.exists()) {
+            f = new File(alias + "_" + count + suffix);
+            count++;
+        }
+
+        FileOutputStream jks = new FileOutputStream(f);
+        if (toPKCS8) {
+            List pemItems = new LinkedList();
+            PrivateKey key = (PrivateKey) ks.getKey(alias, password);
+            Certificate[] chain = ks.getCertificateChain(alias);
+            byte[] pkcs8DerBytes = null;
+            if (key instanceof RSAPrivateCrtKey) {
+                RSAPrivateCrtKey rsa = (RSAPrivateCrtKey) key;
+                ASN1EncodableVector vec = new ASN1EncodableVector();
+                vec.add(new DERInteger(BigInteger.ZERO));
+                vec.add(new DERInteger(rsa.getModulus()));
+                vec.add(new DERInteger(rsa.getPublicExponent()));
+                vec.add(new DERInteger(rsa.getPrivateExponent()));
+                vec.add(new DERInteger(rsa.getPrimeP()));
+                vec.add(new DERInteger(rsa.getPrimeQ()));
+                vec.add(new DERInteger(rsa.getPrimeExponentP()));
+                vec.add(new DERInteger(rsa.getPrimeExponentQ()));
+                vec.add(new DERInteger(rsa.getCrtCoefficient()));
+                DERSequence seq = new DERSequence(vec);
+                byte[] derBytes = PKCS8Key.encode(seq);
+                PKCS8Key pkcs8 = new PKCS8Key(derBytes, null);
+                pkcs8DerBytes = pkcs8.getDecryptedBytes();
+            } else if (key instanceof DSAPrivateKey) {
+                DSAPrivateKey dsa = (DSAPrivateKey) key;
+                DSAParams params = dsa.getParams();
+                BigInteger g = params.getG();
+                BigInteger p = params.getP();
+                BigInteger q = params.getQ();
+                BigInteger x = dsa.getX();
+                BigInteger y = q.modPow(x, p);
+
+                ASN1EncodableVector vec = new ASN1EncodableVector();
+                vec.add(new DERInteger(BigInteger.ZERO));
+                vec.add(new DERInteger(p));
+                vec.add(new DERInteger(q));
+                vec.add(new DERInteger(g));
+                vec.add(new DERInteger(y));
+                vec.add(new DERInteger(x));
+                DERSequence seq = new DERSequence(vec);
+                byte[] derBytes = PKCS8Key.encode(seq);
+                PKCS8Key pkcs8 = new PKCS8Key(derBytes, null);
+                pkcs8DerBytes = pkcs8.getDecryptedBytes();
+            }
+            if (chain != null && chain.length > 0) {
+                for (int i = 0; i < chain.length; i++) {
+                    X509Certificate x509 = (X509Certificate) chain[i];
+                    byte[] derBytes = x509.getEncoded();
+                    PEMItem item = new PEMItem(derBytes, "CERTIFICATE");
+                    pemItems.add(item);
+                }
+            }
+            if (pkcs8DerBytes != null) {
+                PEMItem item = new PEMItem(pkcs8DerBytes, "PRIVATE KEY");
+                pemItems.add(item);
+            }
+            byte[] pem = PEMUtil.encode(pemItems);
+            jks.write(pem);
+        } else {
+            ks.store(jks, password);
+        }
+        jks.flush();
+        jks.close();
+        System.out.println("Successfuly wrote: [" + f.getPath() + "]");
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/LDAPSocket.java b/src/java/org/apache/commons/ssl/LDAPSocket.java
new file mode 100644
index 0000000..9a2fd78
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/LDAPSocket.java
@@ -0,0 +1,83 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/LDAPSocket.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.SocketFactory;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 28-Feb-2006
+ */
+public class LDAPSocket extends SSLClient {
+    private final static LDAPSocket instance;
+
+    static {
+        LDAPSocket sf = null;
+        try {
+            sf = new LDAPSocket();
+        }
+        catch (Exception e) {
+            System.out.println("could not create LDAPSocket: " + e);
+            e.printStackTrace();
+        }
+        finally {
+            instance = sf;
+        }
+    }
+
+    private LDAPSocket() throws GeneralSecurityException, IOException {
+        super();
+
+        // For now we setup the usual trust infrastructure, but consumers
+        // are encouraged to call getInstance().addTrustMaterial() or
+        // getInstance().setTrustMaterial() to customize the trust.
+        if (TrustMaterial.JSSE_CACERTS != null) {
+            setTrustMaterial(TrustMaterial.JSSE_CACERTS);
+        } else {
+            setTrustMaterial(TrustMaterial.CACERTS);
+        }
+    }
+
+    public static SocketFactory getDefault() {
+        return getInstance();
+    }
+
+    public static LDAPSocket getInstance() {
+        return instance;
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/LogHelper.java b/src/java/org/apache/commons/ssl/LogHelper.java
new file mode 100644
index 0000000..63c80d3
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/LogHelper.java
@@ -0,0 +1,87 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/LogHelper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.log4j.Logger;
+
+/**
+ * <p/>
+ * Wraps a Log4j Logger.  This non-public class is the one actually interacting
+ * with the log4j.jar library.  That way LogWrapper can safely attempt to use
+ * log4j.jar, but still degrade gracefully and provide logging via standard-out
+ * even if log4j is unavailable.
+ * <p/>
+ * The interactions with log4j.jar could be done directly inside LogWrapper
+ * as long as the Java code is compiled by Java 1.4 or greater (still works
+ * at runtime in Java 1.3).  The interactions with log4j.jar only need to be
+ * pushed out into a separate class like this for people using a Java 1.3
+ * compiler, which creates bytecode that is more strict with depedency
+ * checking.
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 3-Aug-2006
+ */
+final class LogHelper {
+    private final Logger l;
+
+    LogHelper(Class c) { l = Logger.getLogger(c); }
+
+    LogHelper(String s) { l = Logger.getLogger(s); }
+
+    void debug(Object o) { l.debug(o); }
+
+    void debug(Object o, Throwable t) { l.debug(o, t); }
+
+    void info(Object o) { l.info(o); }
+
+    void info(Object o, Throwable t) { l.info(o, t); }
+
+    void warn(Object o) { l.warn(o); }
+
+    void warn(Object o, Throwable t) { l.warn(o, t); }
+
+    void error(Object o) { l.error(o); }
+
+    void error(Object o, Throwable t) { l.error(o, t); }
+
+    void fatal(Object o) { l.fatal(o); }
+
+    void fatal(Object o, Throwable t) { l.fatal(o, t); }
+
+    boolean isDebugEnabled() { return l.isDebugEnabled(); }
+
+    boolean isInfoEnabled() { return l.isInfoEnabled(); }
+
+    Object getLog4jLogger() { return l; }
+}
diff --git a/src/java/org/apache/commons/ssl/LogWrapper.java b/src/java/org/apache/commons/ssl/LogWrapper.java
new file mode 100644
index 0000000..3646b76
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/LogWrapper.java
@@ -0,0 +1,295 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/LogWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * <p/>
+ * LogWrapper can be used for situations where log4j might not be available on
+ * the classpath.  It presents the most basic and critical components of the
+ * log4j API, and passes all log calls through to log4j if possible.  If log4j
+ * is not available, logging is sent to standard-out by default.
+ * <p/>
+ * This default logging to standard-out (which only occurs if log4j is NOT
+ * available) can be disabled or changed via the static setBackupStream() and
+ * setBackupLogFile() methods.
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 3-Aug-2006
+ */
+public class LogWrapper {
+
+    // final static String[] LEVELS = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
+    final static String[] LEVELS = {"+", " ", "!", "*", "#"};
+    final static String TIMESTAMP_PATTERN = "zzz:yyyy-MM-dd/HH:mm:ss.SSS";
+    final static int TIMESTAMP_LENGTH = TIMESTAMP_PATTERN.length();
+    final static String LINE_SEPARATOR = System.getProperty("line.separator");
+    final static DateFormat DF = new SimpleDateFormat(TIMESTAMP_PATTERN);
+
+    private final static LogWrapper NOOP = new LogWrapper();
+
+    /** Should we print DEBUG statements if log4j is not available? */
+    private final static boolean DEBUG = true;
+
+    /** true if log4j is available */
+    public final static boolean log4j;
+
+    /**
+     * OutputStream to log to if log4j is not available.  Set it to null to
+     * disable.
+     */
+    private static volatile OutputStream backup = System.out;
+
+    /** The wrappingPrintStream is lazy-initted if we have to log a stacktrace. */
+    private static volatile PrintStream wrappingPrintStream = null;
+
+    private final LogHelper h;
+
+    static {
+        boolean avail = false;
+        try {
+            // LogHelper's constructor will blow up if log4j.jar isn't on the
+            // classpath.
+            LogHelper lh = new LogHelper(LogWrapper.class);
+            lh.hashCode();
+            avail = true;
+        }
+        catch (Throwable t) {
+            avail = false;
+        }
+        finally {
+            log4j = avail;
+        }
+    }
+
+    public static boolean isLog4jAvailable() { return log4j; }
+
+    public static LogWrapper getLogger(Class c) {
+        return log4j ? new LogWrapper(c) : NOOP;
+    }
+
+    public static LogWrapper getLogger(String s) {
+        return log4j ? new LogWrapper(s) : NOOP;
+    }
+
+    private LogWrapper() { this.h = null; }
+
+    private LogWrapper(Class c) { this.h = new LogHelper(c); }
+
+    private LogWrapper(String s) { this.h = new LogHelper(s); }
+
+    public void debug(Object o) {
+        if (t(0, o, null)) {
+            h.debug(o);
+        }
+    }
+
+    public void debug(Object o, Throwable t) {
+        if (t(0, o, t)) {
+            h.debug(o, t);
+        }
+    }
+
+    public void info(Object o) {
+        if (t(1, o, null)) {
+            h.info(o);
+        }
+    }
+
+    public void info(Object o, Throwable t) {
+        if (t(1, o, t)) {
+            h.info(o, t);
+        }
+    }
+
+    public void warn(Object o) {
+        if (t(2, o, null)) {
+            h.warn(o);
+        }
+    }
+
+    public void warn(Object o, Throwable t) {
+        if (t(2, o, t)) {
+            h.warn(o, t);
+        }
+    }
+
+    public void error(Object o) {
+        if (t(3, o, null)) {
+            h.error(o);
+        }
+    }
+
+    public void error(Object o, Throwable t) {
+        if (t(3, o, t)) {
+            h.error(o, t);
+        }
+    }
+
+    public void fatal(Object o) {
+        if (t(4, o, null)) {
+            h.fatal(o);
+        }
+    }
+
+    public void fatal(Object o, Throwable t) {
+        if (t(4, o, t)) {
+            h.fatal(o, t);
+        }
+    }
+
+    public boolean isDebugEnabled() { return log4j ? h.isDebugEnabled() : DEBUG;}
+
+    public boolean isInfoEnabled() { return !log4j || h.isInfoEnabled(); }
+
+    public Object getLog4jLogger() { return log4j ? h.getLog4jLogger() : null; }
+
+
+    /**
+     * Tests if log4j is available.  If not, logs to backup OutputStream (if
+     * backup != null).
+     *
+     * @param level log4j logging level for this statement
+     * @param o     object to log
+     * @param t     throwable to log
+     * @return true if log4j is available, false if log4j is not.  If it returns
+     *         false, as a side-effect, it will also log the statement.
+     */
+    private boolean t(int level, Object o, Throwable t) {
+        if (log4j) {
+            return true;
+        } else {
+            // LogWrapper doesn't log debug statements if Log4j is not available
+            // and DEBUG is false.
+            if (backup != null && (DEBUG || level > 0)) {
+                String s = "";  // log4j allows null
+                if (o != null) {
+                    try {
+                        s = (String) o;
+                    }
+                    catch (ClassCastException cce) {
+                        s = o.toString();
+                    }
+                }
+                int len = s.length() + TIMESTAMP_LENGTH + 9;
+                String timestamp = DF.format(new Date());
+                StringBuffer buf = new StringBuffer(len);
+                buf.append(timestamp);
+                if (LEVELS[level].length() == 1) {
+                    buf.append(LEVELS[level]);
+                } else {
+                    buf.append(' ');
+                    buf.append(LEVELS[level]);
+                    buf.append(' ');
+                }
+                buf.append(s);
+                buf.append(LINE_SEPARATOR);
+                s = buf.toString();
+                byte[] logBytes = s.getBytes();
+                try {
+                    if (t == null) {
+                        backup.write(logBytes);
+                    } else {
+                        synchronized (backup) {
+                            backup.write(logBytes);
+                            if (t != null) {
+                                if (wrappingPrintStream == null) {
+                                    wrappingPrintStream = new PrintStream(backup, false);
+                                }
+                                t.printStackTrace(wrappingPrintStream);
+                                wrappingPrintStream.flush();
+                            }
+                        }
+                    }
+                    backup.flush();   // J2RE 1.5.0 IBM J9 2.3 Linux x86-32 needs this.
+                }
+                catch (IOException ioe) {
+                    throw new RuntimeException(ioe.toString());
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Set file to log to if log4j is not available.
+     *
+     * @param f path to use for backup log file (if log4j not available)
+     * @throws IOException if we can't write to the given path
+     */
+    public static void setBackupLogFile(String f)
+        throws IOException {
+        if (!log4j) {
+            OutputStream out = new FileOutputStream(f, true);
+            out = new BufferedOutputStream(out);
+            setBackupStream(out);
+        }
+    }
+
+    /**
+     * Set PrintStream to log to if log4j is not available.  Set to null to
+     * disable.  Default value is System.out.
+     *
+     * @param os outputstream to use for backup logging (if log4j not available)
+     */
+    public static void setBackupStream(OutputStream os) {
+        // synchronize on the old backup - don't want to pull the rug out from
+        // under him if he's working on a big stacktrace or something like that.
+        if (backup != null) {
+            synchronized (backup) {
+                wrappingPrintStream = null;
+                backup = os;
+            }
+        } else {
+            wrappingPrintStream = null;
+            backup = os;
+        }
+    }
+
+    /**
+     * Get the PrintStream we're logging to if log4j is not available.
+     *
+     * @return OutputStream we're using as our log4j replacement.
+     */
+    public static OutputStream getBackupStream() { return backup; }
+
+}
diff --git a/src/java/org/apache/commons/ssl/OpenSSL.java b/src/java/org/apache/commons/ssl/OpenSSL.java
new file mode 100644
index 0000000..f580d4a
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/OpenSSL.java
@@ -0,0 +1,720 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/OpenSSL.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.util.Hex;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.StringTokenizer;
+
+/**
+ * Class for encrypting or decrypting data with a password (PBE - password
+ * based encryption).  Compatible with "openssl enc" unix utility.  An OpenSSL
+ * compatible cipher name must be specified along with the password (try "man enc" on a
+ * unix box to see what's possible).  Some examples:
+ * <ul><li>des, des3, des-ede3-cbc
+ * <li>aes128, aes192, aes256, aes-256-cbc
+ * <li>rc2, rc4, bf</ul>
+ * <pre>
+ * <em style="color: green;">// Encrypt!</em>
+ * byte[] encryptedData = OpenSSL.encrypt( "des3", password, data );
+ * </pre>
+ * <p/>
+ * If you want to specify a raw key and iv directly (without using PBE), use
+ * the methods that take byte[] key, byte[] iv.  Those byte[] arrays can be
+ * the raw binary, or they can be ascii (hex representation: '0' - 'F').  If
+ * you want to use PBE to derive the key and iv, then use the methods that
+ * take char[] password.
+ * <p/>
+ * This class is able to decrypt files encrypted with "openssl" unix utility.
+ * <p/>
+ * The "openssl" unix utility is able to decrypt files encrypted by this class.
+ * <p/>
+ * This class is also able to encrypt and decrypt its own files.
+ *
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at gmail.com</a>
+ * @since 18-Oct-2007
+ */
+public class OpenSSL {
+
+
+    /**
+     * Decrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher    The OpenSSL compatible cipher to use (try "man enc" on a
+     *                  unix box to see what's possible).  Some examples:
+     *                  <ul><li>des, des3, des-ede3-cbc
+     *                  <li>aes128, aes192, aes256, aes-256-cbc
+     *                  <li>rc2, rc4, bf</ul>
+     * @param pwd       password to use for this PBE decryption
+     * @param encrypted byte array to decrypt.  Can be raw, or base64.
+     * @return decrypted bytes
+     * @throws IOException              problems with encrypted bytes (unlikely!)
+     * @throws GeneralSecurityException problems decrypting
+     */
+    public static byte[] decrypt(String cipher, char[] pwd, byte[] encrypted)
+        throws IOException, GeneralSecurityException {
+        ByteArrayInputStream in = new ByteArrayInputStream(encrypted);
+        InputStream decrypted = decrypt(cipher, pwd, in);
+        return Util.streamToBytes(decrypted);
+    }
+
+    /**
+     * Decrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher    The OpenSSL compatible cipher to use (try "man enc" on a
+     *                  unix box to see what's possible).  Some examples:
+     *                  <ul><li>des, des3, des-ede3-cbc
+     *                  <li>aes128, aes192, aes256, aes-256-cbc
+     *                  <li>rc2, rc4, bf</ul>
+     * @param pwd       password to use for this PBE decryption
+     * @param encrypted InputStream to decrypt.  Can be raw, or base64.
+     * @return decrypted bytes as an InputStream
+     * @throws IOException              problems with InputStream
+     * @throws GeneralSecurityException problems decrypting
+     */
+    public static InputStream decrypt(String cipher, char[] pwd,
+                                      InputStream encrypted)
+        throws IOException, GeneralSecurityException {
+        CipherInfo cipherInfo = lookup(cipher);
+        boolean salted = false;
+
+        // First 16 bytes of raw binary will hopefully be OpenSSL's
+        // "Salted__[8 bytes of hex]" thing.  Might be in Base64, though.
+        byte[] saltLine = Util.streamToBytes(encrypted, 16);
+        if (saltLine.length <= 0) {
+            throw new IOException("encrypted InputStream is empty");
+        }
+        String firstEightBytes = "";
+        if (saltLine.length >= 8) {
+            firstEightBytes = new String(saltLine, 0, 8);
+        }
+        if ("SALTED__".equalsIgnoreCase(firstEightBytes)) {
+            salted = true;
+        } else {
+            // Maybe the reason we didn't find the salt is because we're in
+            // base64.
+            if (Base64.isArrayByteBase64(saltLine)) {
+                InputStream head = new ByteArrayInputStream(saltLine);
+                // Need to put that 16 byte "saltLine" back into the Stream.
+                encrypted = new ComboInputStream(head, encrypted);
+                encrypted = new Base64InputStream(encrypted, true);
+                saltLine = Util.streamToBytes(encrypted, 16);
+
+                if (saltLine.length >= 8) {
+                    firstEightBytes = new String(saltLine, 0, 8);
+                }
+                if ("SALTED__".equalsIgnoreCase(firstEightBytes)) {
+                    salted = true;
+                }
+            }
+        }
+
+        byte[] salt = null;
+        if (salted) {
+            salt = new byte[8];
+            System.arraycopy(saltLine, 8, salt, 0, 8);
+        } else {
+            // Encrypted data wasn't salted.  Need to put the "saltLine" we
+            // extracted back into the stream.
+            InputStream head = new ByteArrayInputStream(saltLine);
+            encrypted = new ComboInputStream(head, encrypted);
+        }
+
+        int keySize = cipherInfo.keySize;
+        int ivSize = cipherInfo.ivSize;
+        boolean des2 = cipherInfo.des2;
+        DerivedKey dk = deriveKey(pwd, salt, keySize, ivSize, des2);
+        Cipher c = PKCS8Key.generateCipher(
+            cipherInfo.javaCipher, cipherInfo.blockMode, dk, des2, null, true
+        );
+
+        return new CipherInputStream(encrypted, c);
+    }
+
+    /**
+     * Encrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
+     *               unix box to see what's possible).  Some examples:
+     *               <ul><li>des, des3, des-ede3-cbc
+     *               <li>aes128, aes192, aes256, aes-256-cbc
+     *               <li>rc2, rc4, bf</ul>
+     * @param pwd    password to use for this PBE encryption
+     * @param data   byte array to encrypt
+     * @return encrypted bytes as an array in base64.  First 16 bytes include the
+     *         special OpenSSL "Salted__" info encoded into base64.
+     * @throws IOException              problems with the data byte array
+     * @throws GeneralSecurityException problems encrypting
+     */
+    public static byte[] encrypt(String cipher, char[] pwd, byte[] data)
+        throws IOException, GeneralSecurityException {
+        // base64 is the default output format.
+        return encrypt(cipher, pwd, data, true);
+    }
+
+    /**
+     * Encrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher The OpenSSL compatible cipher to use (try "man enc" on a
+     *               unix box to see what's possible).  Some examples:
+     *               <ul><li>des, des3, des-ede3-cbc
+     *               <li>aes128, aes192, aes256, aes-256-cbc
+     *               <li>rc2, rc4, bf</ul>
+     * @param pwd    password to use for this PBE encryption
+     * @param data   InputStream to encrypt
+     * @return encrypted bytes as an InputStream.  First 16 bytes include the
+     *         special OpenSSL "Salted__" info encoded into base64.
+     * @throws IOException              problems with the data InputStream
+     * @throws GeneralSecurityException problems encrypting
+     */
+    public static InputStream encrypt(String cipher, char[] pwd,
+                                      InputStream data)
+        throws IOException, GeneralSecurityException {
+        // base64 is the default output format.
+        return encrypt(cipher, pwd, data, true);
+    }
+
+    /**
+     * Encrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher   The OpenSSL compatible cipher to use (try "man enc" on a
+     *                 unix box to see what's possible).  Some examples:
+     *                 <ul><li>des, des3, des-ede3-cbc
+     *                 <li>aes128, aes192, aes256, aes-256-cbc
+     *                 <li>rc2, rc4, bf</ul>
+     * @param pwd      password to use for this PBE encryption
+     * @param data     byte array to encrypt
+     * @param toBase64 true if resulting InputStream should contain base64,
+     *                 <br>false if InputStream should contain raw binary.
+     * @return encrypted bytes as an array.  First 16 bytes include the
+     *         special OpenSSL "Salted__" info.
+     * @throws IOException              problems with the data byte array
+     * @throws GeneralSecurityException problems encrypting
+     */
+    public static byte[] encrypt(String cipher, char[] pwd, byte[] data,
+                                 boolean toBase64)
+        throws IOException, GeneralSecurityException {
+        // we use a salt by default.
+        return encrypt(cipher, pwd, data, toBase64, true);
+    }
+
+    /**
+     * Encrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher   The OpenSSL compatible cipher to use (try "man enc" on a
+     *                 unix box to see what's possible).  Some examples:
+     *                 <ul><li>des, des3, des-ede3-cbc
+     *                 <li>aes128, aes192, aes256, aes-256-cbc
+     *                 <li>rc2, rc4, bf</ul>
+     * @param pwd      password to use for this PBE encryption
+     * @param data     InputStream to encrypt
+     * @param toBase64 true if resulting InputStream should contain base64,
+     *                 <br>false if InputStream should contain raw binary.
+     * @return encrypted bytes as an InputStream.  First 16 bytes include the
+     *         special OpenSSL "Salted__" info.
+     * @throws IOException              problems with the data InputStream
+     * @throws GeneralSecurityException problems encrypting
+     */
+    public static InputStream encrypt(String cipher, char[] pwd,
+                                      InputStream data, boolean toBase64)
+        throws IOException, GeneralSecurityException {
+        // we use a salt by default.
+        return encrypt(cipher, pwd, data, toBase64, true);
+    }
+
+    /**
+     * Encrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher   The OpenSSL compatible cipher to use (try "man enc" on a
+     *                 unix box to see what's possible).  Some examples:
+     *                 <ul><li>des, des3, des-ede3-cbc
+     *                 <li>aes128, aes192, aes256, aes-256-cbc
+     *                 <li>rc2, rc4, bf</ul>
+     * @param pwd      password to use for this PBE encryption
+     * @param data     byte array to encrypt
+     * @param toBase64 true if resulting InputStream should contain base64,
+     *                 <br>false if InputStream should contain raw binary.
+     * @param useSalt  true if a salt should be used to derive the key.
+     *                 <br>false otherwise.  (Best security practises
+     *                 always recommend using a salt!).
+     * @return encrypted bytes as an array.  First 16 bytes include the
+     *         special OpenSSL "Salted__" info if <code>useSalt</code> is true.
+     * @throws IOException              problems with the data InputStream
+     * @throws GeneralSecurityException problems encrypting
+     */
+    public static byte[] encrypt(String cipher, char[] pwd, byte[] data,
+                                 boolean toBase64, boolean useSalt)
+        throws IOException, GeneralSecurityException {
+        ByteArrayInputStream in = new ByteArrayInputStream(data);
+        InputStream encrypted = encrypt(cipher, pwd, in, toBase64, useSalt);
+        return Util.streamToBytes(encrypted);
+    }
+
+    /**
+     * Encrypts data using a password and an OpenSSL compatible cipher
+     * name.
+     *
+     * @param cipher   The OpenSSL compatible cipher to use (try "man enc" on a
+     *                 unix box to see what's possible).  Some examples:
+     *                 <ul><li>des, des3, des-ede3-cbc
+     *                 <li>aes128, aes192, aes256, aes-256-cbc
+     *                 <li>rc2, rc4, bf</ul>
+     * @param pwd      password to use for this PBE encryption
+     * @param data     InputStream to encrypt
+     * @param toBase64 true if resulting InputStream should contain base64,
+     *                 <br>false if InputStream should contain raw binary.
+     * @param useSalt  true if a salt should be used to derive the key.
+     *                 <br>false otherwise.  (Best security practises
+     *                 always recommend using a salt!).
+     * @return encrypted bytes as an InputStream.  First 16 bytes include the
+     *         special OpenSSL "Salted__" info if <code>useSalt</code> is true.
+     * @throws IOException              problems with the data InputStream
+     * @throws GeneralSecurityException problems encrypting
+     */
+    public static InputStream encrypt(String cipher, char[] pwd,
+                                      InputStream data, boolean toBase64,
+                                      boolean useSalt)
+        throws IOException, GeneralSecurityException {
+        CipherInfo cipherInfo = lookup(cipher);
+        byte[] salt = null;
+        if (useSalt) {
+            SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
+            salt = new byte[8];
+            rand.nextBytes(salt);
+        }
+
+        int keySize = cipherInfo.keySize;
+        int ivSize = cipherInfo.ivSize;
+        boolean des2 = cipherInfo.des2;
+        DerivedKey dk = deriveKey(pwd, salt, keySize, ivSize, des2);
+        Cipher c = PKCS8Key.generateCipher(
+            cipherInfo.javaCipher, cipherInfo.blockMode, dk, des2, null, false
+        );
+
+        InputStream cipherStream = new CipherInputStream(data, c);
+
+        if (useSalt) {
+            byte[] saltLine = new byte[16];
+            byte[] salted = "Salted__".getBytes();
+            System.arraycopy(salted, 0, saltLine, 0, salted.length);
+            System.arraycopy(salt, 0, saltLine, salted.length, salt.length);
+            InputStream head = new ByteArrayInputStream(saltLine);
+            cipherStream = new ComboInputStream(head, cipherStream);
+        }
+        if (toBase64) {
+            cipherStream = new Base64InputStream(cipherStream, false);
+        }
+        return cipherStream;
+    }
+
+
+    public static byte[] decrypt(String cipher, byte[] key, byte[] iv,
+                                 byte[] encrypted)
+        throws IOException, GeneralSecurityException {
+        ByteArrayInputStream in = new ByteArrayInputStream(encrypted);
+        InputStream decrypted = decrypt(cipher, key, iv, in);
+        return Util.streamToBytes(decrypted);
+    }
+
+    public static InputStream decrypt(String cipher, byte[] key, byte[] iv,
+                                      InputStream encrypted)
+        throws IOException, GeneralSecurityException {
+        CipherInfo cipherInfo = lookup(cipher);
+        byte[] firstLine = Util.streamToBytes(encrypted, 16);
+        if (Base64.isArrayByteBase64(firstLine)) {
+            InputStream head = new ByteArrayInputStream(firstLine);
+            // Need to put that 16 byte "firstLine" back into the Stream.
+            encrypted = new ComboInputStream(head, encrypted);
+            encrypted = new Base64InputStream(encrypted, true);
+        } else {
+            // Encrypted data wasn't base64.  Need to put the "firstLine" we
+            // extracted back into the stream.
+            InputStream head = new ByteArrayInputStream(firstLine);
+            encrypted = new ComboInputStream(head, encrypted);
+        }
+
+        int keySize = cipherInfo.keySize;
+        int ivSize = cipherInfo.ivSize;
+        if (key.length == keySize / 4) // Looks like key is in hex
+        {
+            key = Hex.decode(key);
+        }
+        if (iv.length == ivSize / 4) // Looks like IV is in hex
+        {
+            iv = Hex.decode(iv);
+        }
+        DerivedKey dk = new DerivedKey(key, iv);
+        Cipher c = PKCS8Key.generateCipher(cipherInfo.javaCipher,
+            cipherInfo.blockMode,
+            dk, cipherInfo.des2, null, true);
+        return new CipherInputStream(encrypted, c);
+    }
+
+    public static byte[] encrypt(String cipher, byte[] key, byte[] iv,
+                                 byte[] data)
+        throws IOException, GeneralSecurityException {
+        return encrypt(cipher, key, iv, data, true);
+    }
+
+    public static byte[] encrypt(String cipher, byte[] key, byte[] iv,
+                                 byte[] data, boolean toBase64)
+        throws IOException, GeneralSecurityException {
+        ByteArrayInputStream in = new ByteArrayInputStream(data);
+        InputStream encrypted = encrypt(cipher, key, iv, in, toBase64);
+        return Util.streamToBytes(encrypted);
+    }
+
+
+    public static InputStream encrypt(String cipher, byte[] key, byte[] iv,
+                                      InputStream data)
+        throws IOException, GeneralSecurityException {
+        return encrypt(cipher, key, iv, data, true);
+    }
+
+    public static InputStream encrypt(String cipher, byte[] key, byte[] iv,
+                                      InputStream data, boolean toBase64)
+        throws IOException, GeneralSecurityException {
+        CipherInfo cipherInfo = lookup(cipher);
+        int keySize = cipherInfo.keySize;
+        int ivSize = cipherInfo.ivSize;
+        if (key.length == keySize / 4) {
+            key = Hex.decode(key);
+        }
+        if (iv.length == ivSize / 4) {
+            iv = Hex.decode(iv);
+        }
+        DerivedKey dk = new DerivedKey(key, iv);
+        Cipher c = PKCS8Key.generateCipher(cipherInfo.javaCipher,
+            cipherInfo.blockMode,
+            dk, cipherInfo.des2, null, false);
+
+        InputStream cipherStream = new CipherInputStream(data, c);
+        if (toBase64) {
+            cipherStream = new Base64InputStream(cipherStream, false);
+        }
+        return cipherStream;
+    }
+
+
+    public static DerivedKey deriveKey(char[] password, byte[] salt,
+                                       int keySize, boolean des2)
+        throws NoSuchAlgorithmException {
+        return deriveKey(password, salt, keySize, 0, des2);
+    }
+
+    public static DerivedKey deriveKey(char[] password, byte[] salt,
+                                       int keySize, int ivSize, boolean des2)
+        throws NoSuchAlgorithmException {
+        if (des2) {
+            keySize = 128;
+        }
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        byte[] pwdAsBytes = new byte[password.length];
+        for (int i = 0; i < password.length; i++) {
+            pwdAsBytes[i] = (byte) password[i];
+        }
+
+        md.reset();
+        byte[] keyAndIv = new byte[(keySize / 8) + (ivSize / 8)];
+        if (salt == null || salt.length == 0) {
+            // Unsalted!  Bad idea!
+            salt = null;
+        }
+        byte[] result;
+        int currentPos = 0;
+        while (currentPos < keyAndIv.length) {
+            md.update(pwdAsBytes);
+            if (salt != null) {
+                // First 8 bytes of salt ONLY!  That wasn't obvious to me
+                // when using AES encrypted private keys in "Traditional
+                // SSLeay Format".
+                //
+                // Example:
+                // DEK-Info: AES-128-CBC,8DA91D5A71988E3D4431D9C2C009F249
+                //
+                // Only the first 8 bytes are salt, but the whole thing is
+                // re-used again later as the IV.  MUCH gnashing of teeth!
+                md.update(salt, 0, 8);
+            }
+            result = md.digest();
+            int stillNeed = keyAndIv.length - currentPos;
+            // Digest gave us more than we need.  Let's truncate it.
+            if (result.length > stillNeed) {
+                byte[] b = new byte[stillNeed];
+                System.arraycopy(result, 0, b, 0, b.length);
+                result = b;
+            }
+            System.arraycopy(result, 0, keyAndIv, currentPos, result.length);
+            currentPos += result.length;
+            if (currentPos < keyAndIv.length) {
+                // Next round starts with a hash of the hash.
+                md.reset();
+                md.update(result);
+            }
+        }
+        if (des2) {
+            keySize = 192;
+            byte[] buf = new byte[keyAndIv.length + 8];
+            // Make space where 3rd key needs to go (16th - 24th bytes):
+            System.arraycopy(keyAndIv, 0, buf, 0, 16);
+            if (ivSize > 0) {
+                System.arraycopy(keyAndIv, 16, buf, 24, keyAndIv.length - 16);
+            }
+            keyAndIv = buf;
+            // copy first 8 bytes into last 8 bytes to create 2DES key.
+            System.arraycopy(keyAndIv, 0, keyAndIv, 16, 8);
+        }
+        if (ivSize == 0) {
+            // if ivSize == 0, then "keyAndIv" array is actually all key.
+
+            // Must be "Traditional SSLeay Format" encrypted private key in
+            // PEM.  The "salt" in its entirety (not just first 8 bytes) will
+            // probably be re-used later as the IV (initialization vector).
+            return new DerivedKey(keyAndIv, salt);
+        } else {
+            byte[] key = new byte[keySize / 8];
+            byte[] iv = new byte[ivSize / 8];
+            System.arraycopy(keyAndIv, 0, key, 0, key.length);
+            System.arraycopy(keyAndIv, key.length, iv, 0, iv.length);
+            return new DerivedKey(key, iv);
+        }
+    }
+
+
+    public static class CipherInfo {
+        public final String javaCipher;
+        public final String blockMode;
+        public final int keySize;
+        public final int ivSize;
+        public final boolean des2;
+
+        public CipherInfo(String javaCipher, String blockMode, int keySize,
+                          int ivSize, boolean des2) {
+            this.javaCipher = javaCipher;
+            this.blockMode = blockMode;
+            this.keySize = keySize;
+            this.ivSize = ivSize;
+            this.des2 = des2;
+        }
+
+        public String toString() {
+            return javaCipher + "/" + blockMode + " " + keySize + "bit  des2=" + des2;
+        }
+    }
+
+    /**
+     * Converts the way OpenSSL names its ciphers into a Java-friendly naming.
+     *
+     * @param openSSLCipher OpenSSL cipher name, e.g. "des3" or "des-ede3-cbc".
+     *                      Try "man enc" on a unix box to see what's possible.
+     * @return CipherInfo object with the Java-friendly cipher information.
+     */
+    public static CipherInfo lookup(String openSSLCipher) {
+        openSSLCipher = openSSLCipher.trim();
+        if (openSSLCipher.charAt(0) == '-') {
+            openSSLCipher = openSSLCipher.substring(1);
+        }
+        String javaCipher = openSSLCipher.toUpperCase();
+        String blockMode = "CBC";
+        int keySize = -1;
+        int ivSize = 64;
+        boolean des2 = false;
+
+
+        StringTokenizer st = new StringTokenizer(openSSLCipher, "-");
+        if (st.hasMoreTokens()) {
+            javaCipher = st.nextToken().toUpperCase();
+            if (st.hasMoreTokens()) {
+                // Is this the middle token?  Or the last token?
+                String tok = st.nextToken();
+                if (st.hasMoreTokens()) {
+                    try {
+                        keySize = Integer.parseInt(tok);
+                    }
+                    catch (NumberFormatException nfe) {
+                        // I guess 2nd token isn't an integer
+                        String upper = tok.toUpperCase();
+                        if (upper.startsWith("EDE3")) {
+                            javaCipher = "DESede";
+                        } else if (upper.startsWith("EDE")) {
+                            javaCipher = "DESede";
+                            des2 = true;
+                        }
+                    }
+                    blockMode = st.nextToken().toUpperCase();
+                } else {
+                    try {
+                        keySize = Integer.parseInt(tok);
+                    }
+                    catch (NumberFormatException nfe) {
+                        // It's the last token, so must be mode (usually "CBC").
+                        blockMode = tok.toUpperCase();
+                        if (blockMode.startsWith("EDE3")) {
+                            javaCipher = "DESede";
+                            blockMode = "ECB";
+                        } else if (blockMode.startsWith("EDE")) {
+                            javaCipher = "DESede";
+                            blockMode = "ECB";
+                            des2 = true;
+                        }
+                    }
+                }
+            }
+        }
+        if (javaCipher.startsWith("BF")) {
+            javaCipher = "Blowfish";
+        } else if (javaCipher.startsWith("TWOFISH")) {
+            javaCipher = "Twofish";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("IDEA")) {
+            javaCipher = "IDEA";
+        } else if (javaCipher.startsWith("CAST6")) {
+            javaCipher = "CAST6";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("CAST")) {
+            javaCipher = "CAST5";
+        } else if (javaCipher.startsWith("GOST")) {
+            keySize = 256;
+        } else if (javaCipher.startsWith("DESX")) {
+            javaCipher = "DESX";
+        } else if ("DES3".equals(javaCipher)) {
+            javaCipher = "DESede";
+        } else if ("DES2".equals(javaCipher)) {
+            javaCipher = "DESede";
+            des2 = true;
+        } else if (javaCipher.startsWith("RIJNDAEL")) {
+            javaCipher = "Rijndael";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("SEED")) {
+            javaCipher = "SEED";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("SERPENT")) {
+            javaCipher = "Serpent";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("Skipjack")) {
+            javaCipher = "Skipjack";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("RC6")) {
+            javaCipher = "RC6";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("TEA")) {
+            javaCipher = "TEA";
+        } else if (javaCipher.startsWith("XTEA")) {
+            javaCipher = "XTEA";
+        } else if (javaCipher.startsWith("AES")) {
+            if (javaCipher.startsWith("AES128")) {
+                keySize = 128;
+            } else if (javaCipher.startsWith("AES192")) {
+                keySize = 192;
+            } else if (javaCipher.startsWith("AES256")) {
+                keySize = 256;
+            }
+            javaCipher = "AES";
+            ivSize = 128;
+        } else if (javaCipher.startsWith("CAMELLIA")) {
+            if (javaCipher.startsWith("CAMELLIA128")) {
+                keySize = 128;
+            } else if (javaCipher.startsWith("CAMELLIA192")) {
+                keySize = 192;
+            } else if (javaCipher.startsWith("CAMELLIA256")) {
+                keySize = 256;
+            }
+            javaCipher = "CAMELLIA";
+            ivSize = 128;
+        }
+        if (keySize == -1) {
+            if (javaCipher.startsWith("DESede")) {
+                keySize = 192;
+            } else if (javaCipher.startsWith("DES")) {
+                keySize = 64;
+            } else {
+                // RC2, RC4, RC5 and Blowfish ?
+                keySize = 128;
+            }
+        }
+        return new CipherInfo(javaCipher, blockMode, keySize, ivSize, des2);
+    }
+
+
+    /**
+     * @param args command line arguments: [password] [cipher] [file-to-decrypt]
+     *             <br>[cipher] == OpenSSL cipher name, e.g. "des3" or "des-ede3-cbc".
+     *             Try "man enc" on a unix box to see what's possible.
+     * @throws IOException              problems with the [file-to-decrypt]
+     * @throws GeneralSecurityException decryption problems
+     */
+    public static void main(String[] args)
+        throws IOException, GeneralSecurityException {
+        if (args.length < 3) {
+            System.out.println(Version.versionString());
+            System.out.println("Pure-java utility to decrypt files previously encrypted by \'openssl enc\'");
+            System.out.println();
+            System.out.println("Usage:  java -cp commons-ssl.jar org.apache.commons.ssl.OpenSSL [args]");
+            System.out.println("        [args]   == [password] [cipher] [file-to-decrypt]");
+            System.out.println("        [cipher] == des, des3, des-ede3-cbc, aes256, rc2, rc4, bf, bf-cbc, etc...");
+            System.out.println("                    Try 'man enc' on a unix box to see what's possible.");
+            System.out.println();
+            System.out.println("This utility can handle base64 or raw, salted or unsalted.");
+            System.out.println();
+            System.exit(1);
+        }
+        char[] password = args[0].toCharArray();
+
+        InputStream in = new FileInputStream(args[2]);
+        in = decrypt(args[1], password, in);
+
+        // in = encrypt( args[ 1 ], pwdAsBytes, in, true );
+
+        Util.pipeStream(in, System.out, false);
+        byte[] output = Util.streamToBytes(in);
+        System.out.write(output);
+        System.out.flush();
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/OpenSSLTest.java b/src/java/org/apache/commons/ssl/OpenSSLTest.java
new file mode 100644
index 0000000..1b1c034
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/OpenSSLTest.java
@@ -0,0 +1,92 @@
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.util.Hex;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+
+/**
+ * @author Julius Davies
+ * @since 3-Jul-2007
+ */
+public class OpenSSLTest {
+
+    public static void main(String[] args) throws Exception {
+        String path = args[0];
+        File f = new File(path);
+        if (f.isDirectory()) {
+            File[] files = f.listFiles();
+            Arrays.sort(files);
+            for (int i = 0; i < files.length; i++) {
+                process(files[i], 0);
+            }
+        } else {
+            System.out.println("Attempting decrypt!");
+
+            String keyS = "1234567890ABDEF01234567890ABDEFF";
+            String ivS = "1234567890ABDEF01234567890ABDEFF";
+            byte[] key = Hex.decode(keyS.getBytes());
+            byte[] iv = Hex.decode(ivS.getBytes());
+            FileInputStream in = new FileInputStream(f);
+            InputStream decrypted = OpenSSL.decrypt("aes128", key, iv, in);
+            byte[] b = Util.streamToBytes(decrypted);
+            System.out.println(new String(b));
+        }
+    }
+
+
+    private static void process(File f, int depth) {
+        String name = f.getName();
+        if ("CVS".equalsIgnoreCase(name)) {
+            return;
+        }
+        if (name.toUpperCase().startsWith("README")) {
+            return;
+        }
+
+        if (f.isDirectory()) {
+            if (depth <= 3) {
+                File[] files = f.listFiles();
+                Arrays.sort(files);
+                for (int i = 0; i < files.length; i++) {
+                    process(files[i], depth + 1);
+                }
+            } else {
+                System.out.println("IGNORING [" + f + "].  Directory too deep (" + depth + ").");
+            }
+        } else {
+            if (f.isFile() && f.canRead()) {
+                String fileName = f.getName();
+                int x = fileName.indexOf('.');
+                if (x < 0) {
+                    return;
+                }
+                String cipher = fileName.substring(0, x);
+                String cipherPadded = Util.pad(cipher, 20, false);
+                String filePadded = Util.pad(fileName, 25, false);
+                try {
+                    FileInputStream in = new FileInputStream(f);
+                    byte[] encrypted = Util.streamToBytes(in);
+                    char[] pwd = "changeit".toCharArray();
+
+                    byte[] result = OpenSSL.decrypt(cipher, pwd, encrypted);
+                    String s = new String(result, "ISO-8859-1");
+
+                    boolean success = "Hello World!".equals(s);
+                    if (success) {
+                        System.out.println("SUCCESS \t" + cipherPadded + "\t" + filePadded);
+                    } else {
+                        System.out.println("FAILURE*\t" + cipherPadded + "\t" + filePadded + "\tDECRYPT RESULTS DON'T MATCH");
+                    }
+                }
+                catch (Exception e) {
+                    System.out.println("FAILURE*\t" + cipherPadded + "\t" + filePadded + "\t" + e);
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/PBETestCreate.java b/src/java/org/apache/commons/ssl/PBETestCreate.java
new file mode 100644
index 0000000..f962e10
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/PBETestCreate.java
@@ -0,0 +1,79 @@
+package org.apache.commons.ssl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeSet;
+
+/**
+ * @author Julius Davies
+ * @since 4-Jul-2007
+ */
+public class PBETestCreate {
+
+    public static void main(String[] args) throws Exception {
+        FileInputStream in = new FileInputStream(args[0]);
+        Properties p = new Properties();
+        p.load(in);
+        in.close();
+
+        String targetDir = p.getProperty("target");
+        File dir = new File(targetDir);
+        dir.mkdirs();
+        if (!dir.exists()) {
+            throw new IOException(dir.getCanonicalPath() + " doesn't exist!");
+        }
+
+        TreeSet ciphers = new TreeSet();
+        Iterator it = p.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            String key = (String) entry.getKey();
+            if (!"target".equalsIgnoreCase(key)) {
+                ciphers.add(key);
+                ciphers.add(key + "-cbc");
+                ciphers.add(key + "-cfb");
+                ciphers.add(key + "-cfb1");
+                ciphers.add(key + "-cfb8");
+                ciphers.add(key + "-ecb");
+                ciphers.add(key + "-ofb");
+            }
+        }
+
+        byte[] toEncrypt = "Hello World!".getBytes("UTF-8");
+        char[] pwd = "changeit".toCharArray();
+        it = ciphers.iterator();
+        while (it.hasNext()) {
+            String cipher = (String) it.next();
+            String cipherPadded = Util.pad(cipher, 15, false);
+            String fileNameBase64 = cipher + ".base64";
+            String fileNameRaw = cipher + ".raw";
+            String d = dir.getCanonicalPath() + "/";
+            try {
+                byte[] base64 = OpenSSL.encrypt(cipher, pwd, toEncrypt, true);
+                FileOutputStream out = new FileOutputStream(d + fileNameBase64);
+                out.write(base64);
+                out.close();
+            }
+            catch (Exception e) {
+                System.err.println("FAILURE \t" + cipherPadded + "\t" + fileNameBase64 + "\t" + e);
+            }
+
+            try {
+                byte[] raw = OpenSSL.encrypt(cipher, pwd, toEncrypt, false);
+                FileOutputStream out = new FileOutputStream(d + fileNameRaw);
+                out.write(raw);
+                out.close();
+            }
+            catch (Exception e) {
+                System.err.println("FAILURE \t" + cipherPadded + "\t" + fileNameRaw + "\t" + e);
+            }
+
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/PEMItem.java b/src/java/org/apache/commons/ssl/PEMItem.java
new file mode 100644
index 0000000..9b40464
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/PEMItem.java
@@ -0,0 +1,106 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/PEMItem.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.util.Hex;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 13-Aug-2006
+ */
+public class PEMItem {
+    public final static String DEK_INFO = "dek-info";
+
+    private final byte[] derBytes;
+    public final String pemType;
+    public final Map properties;
+
+    public final String dekInfo;
+    public final byte[] iv;
+    public final String cipher;
+    public final boolean des2;
+    public final String mode;
+    public final int keySizeInBits;
+
+    public PEMItem(byte[] derBytes, String type) {
+        this(derBytes, type, null);
+    }
+
+    public PEMItem(byte[] derBytes, String type, Map properties) {
+        this.derBytes = derBytes;
+        this.pemType = type;
+        if (properties == null) {
+            properties = new TreeMap(); // empty map
+        }
+        this.properties = Collections.unmodifiableMap(properties);
+        String di = (String) properties.get(DEK_INFO);
+        String diCipher = "";
+        String diIV = "";
+        if (di != null) {
+            StringTokenizer st = new StringTokenizer(di, ",");
+            if (st.hasMoreTokens()) {
+                diCipher = st.nextToken().trim().toLowerCase();
+            }
+            if (st.hasMoreTokens()) {
+                diIV = st.nextToken().trim().toLowerCase();
+            }
+        }
+        this.dekInfo = diCipher;
+        this.iv = Hex.decode(diIV);
+        if (!"".equals(diCipher)) {
+            OpenSSL.CipherInfo cipherInfo = OpenSSL.lookup(diCipher);
+            this.cipher = cipherInfo.javaCipher;
+            this.mode = cipherInfo.blockMode;
+            this.keySizeInBits = cipherInfo.keySize;
+            this.des2 = cipherInfo.des2;
+        } else {
+            this.mode = "";
+            cipher = "UNKNOWN";
+            keySizeInBits = -1;
+            des2 = false;
+        }
+    }
+
+    public byte[] getDerBytes() {
+        byte[] b = new byte[derBytes.length];
+        System.arraycopy(derBytes, 0, b, 0, derBytes.length);
+        return b;
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/PEMUtil.java b/src/java/org/apache/commons/ssl/PEMUtil.java
new file mode 100644
index 0000000..69cab97
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/PEMUtil.java
@@ -0,0 +1,238 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/PEMUtil.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 13-Aug-2006
+ */
+public class PEMUtil {
+    final static String LINE_SEPARATOR = System.getProperty("line.separator");
+
+    public static byte[] encode(Collection items) throws IOException {
+        final byte[] LINE_SEPARATOR_BYTES = LINE_SEPARATOR.getBytes("UTF-8");
+        ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
+        Iterator it = items.iterator();
+        while (it.hasNext()) {
+            PEMItem item = (PEMItem) it.next();
+            out.write("-----BEGIN ".getBytes("UTF-8"));
+            out.write(item.pemType.getBytes("UTF-8"));
+            out.write("-----".getBytes("UTF-8"));
+            out.write(LINE_SEPARATOR_BYTES);
+
+            byte[] derBytes = item.getDerBytes();
+            ByteArrayInputStream bin = new ByteArrayInputStream(derBytes);
+            byte[] line = Util.streamToBytes(bin, 48);
+            while (line.length == 48) {
+                byte[] base64Line = Base64.encodeBase64(line);
+                out.write(base64Line);
+                out.write(LINE_SEPARATOR_BYTES);
+                line = Util.streamToBytes(bin, 48);
+            }
+            if (line.length > 0) {
+                byte[] base64Line = Base64.encodeBase64(line);
+                out.write(base64Line);
+                out.write(LINE_SEPARATOR_BYTES);
+            }
+            out.write("-----END ".getBytes("UTF-8"));
+            out.write(item.pemType.getBytes("UTF-8"));
+            out.write("-----".getBytes("UTF-8"));
+            out.write(LINE_SEPARATOR_BYTES);
+        }
+        return out.toByteArray();
+    }
+
+    public static List decode(byte[] pemBytes) {
+        LinkedList pemItems = new LinkedList();
+        ByteArrayInputStream in = new ByteArrayInputStream(pemBytes);
+        String line = Util.readLine(in);
+        while (line != null) {
+            int len = 0;
+            byte[] decoded;
+            ArrayList listOfByteArrays = new ArrayList(64);
+            Map properties = new HashMap();
+            String type = "[unknown]";
+            while (line != null && !beginBase64(line)) {
+                line = Util.readLine(in);
+            }
+            if (line != null) {
+                String upperLine = line.toUpperCase();
+                int x = upperLine.indexOf("-BEGIN") + "-BEGIN".length();
+                int y = upperLine.indexOf("-", x);
+                type = upperLine.substring(x, y).trim();
+                line = Util.readLine(in);
+            }
+            while (line != null && !endBase64(line)) {
+                line = Util.trim(line);
+                if (!"".equals(line)) {
+                    int x = line.indexOf(':');
+                    if (x > 0) {
+                        String k = line.substring(0, x).trim();
+                        String v = "";
+                        if (line.length() > x + 1) {
+                            v = line.substring(x + 1).trim();
+                        }
+                        properties.put(k.toLowerCase(), v.toLowerCase());
+                    } else {
+                        byte[] base64 = line.getBytes();
+                        byte[] rawBinary = Base64.decodeBase64(base64);
+                        listOfByteArrays.add(rawBinary);
+                        len += rawBinary.length;
+                    }
+                }
+                line = Util.readLine(in);
+            }
+            if (line != null) {
+                line = Util.readLine(in);
+            }
+
+            if (!listOfByteArrays.isEmpty()) {
+                decoded = new byte[len];
+                int pos = 0;
+                Iterator it = listOfByteArrays.iterator();
+                while (it.hasNext()) {
+                    byte[] oneLine = (byte[]) it.next();
+                    System.arraycopy(oneLine, 0, decoded, pos, oneLine.length);
+                    pos += oneLine.length;
+                }
+                PEMItem item = new PEMItem(decoded, type, properties);
+                pemItems.add(item);
+            }
+        }
+
+        // closing ByteArrayInputStream is a NO-OP
+        // in.close();
+
+        return pemItems;
+    }
+
+    private static boolean beginBase64(String line) {
+        line = line != null ? line.trim().toUpperCase() : "";
+        int x = line.indexOf("-BEGIN");
+        return x > 0 && startsAndEndsWithDashes(line);
+    }
+
+    private static boolean endBase64(String line) {
+        line = line != null ? line.trim().toUpperCase() : "";
+        int x = line.indexOf("-END");
+        return x > 0 && startsAndEndsWithDashes(line);
+    }
+
+    private static boolean startsAndEndsWithDashes(String line) {
+        line = Util.trim(line);
+        char c = line.charAt(0);
+        char d = line.charAt(line.length() - 1);
+        return c == '-' && d == '-';
+    }
+
+    public static String formatRSAPrivateKey(RSAPrivateCrtKey key) {
+        StringBuffer buf = new StringBuffer(2048);
+        buf.append("Private-Key:");
+        buf.append(LINE_SEPARATOR);
+        buf.append("modulus:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getModulus(), 129 * 2));
+        buf.append(LINE_SEPARATOR);
+        buf.append("publicExponent: ");
+        buf.append(key.getPublicExponent());
+        buf.append(LINE_SEPARATOR);
+        buf.append("privateExponent:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getPrivateExponent(), 128 * 2));
+        buf.append(LINE_SEPARATOR);
+        buf.append("prime1:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getPrimeP(), 65 * 2));
+        buf.append(LINE_SEPARATOR);
+        buf.append("prime2:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getPrimeQ(), 65 * 2));
+        buf.append(LINE_SEPARATOR);
+        buf.append("exponent1:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getPrimeExponentP(), 65 * 2));
+        buf.append(LINE_SEPARATOR);
+        buf.append("exponent2:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getPrimeExponentQ(), 65 * 2));
+        buf.append(LINE_SEPARATOR);
+        buf.append("coefficient:");
+        buf.append(LINE_SEPARATOR);
+        buf.append(formatBigInteger(key.getCrtCoefficient(), 65 * 2));
+        return buf.toString();
+    }
+
+    public static String formatBigInteger(BigInteger bi, int length) {
+        String s = bi.toString(16);
+        StringBuffer buf = new StringBuffer(s.length());
+        int zeroesToAppend = length - s.length();
+        int count = 0;
+        buf.append("    ");
+        for (int i = 0; i < zeroesToAppend; i++) {
+            count++;
+            buf.append('0');
+            if (i % 2 == 1) {
+                buf.append(':');
+            }
+        }
+        for (int i = 0; i < s.length() - 2; i++) {
+            count++;
+            buf.append(s.charAt(i));
+            if (i % 2 == 1) {
+                buf.append(':');
+            }
+            if (count % 30 == 0) {
+                buf.append(LINE_SEPARATOR);
+                buf.append("    ");
+            }
+        }
+        buf.append(s.substring(s.length() - 2));
+        return buf.toString();
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/PKCS8Key.java b/src/java/org/apache/commons/ssl/PKCS8Key.java
new file mode 100644
index 0000000..195b02a
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/PKCS8Key.java
@@ -0,0 +1,1034 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/PKCS8Key.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.apache.commons.ssl.asn1.ASN1EncodableVector;
+import org.apache.commons.ssl.asn1.ASN1OutputStream;
+import org.apache.commons.ssl.asn1.DEREncodable;
+import org.apache.commons.ssl.asn1.DERInteger;
+import org.apache.commons.ssl.asn1.DERNull;
+import org.apache.commons.ssl.asn1.DERObjectIdentifier;
+import org.apache.commons.ssl.asn1.DEROctetString;
+import org.apache.commons.ssl.asn1.DERSequence;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.RC5ParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Utility for decrypting PKCS8 private keys.  Way easier to use than
+ * javax.crypto.EncryptedPrivateKeyInfo since all you need is the byte[] array
+ * and the password.  You don't need to know anything else about the PKCS8
+ * key you pass in.
+ * </p><p>
+ * Can handle base64 PEM, or raw DER.
+ * Can handle PKCS8 Version 1.5 and 2.0.
+ * Can also handle OpenSSL encrypted or unencrypted private keys (DSA or RSA).
+ * </p><p>
+ * The PKCS12 key derivation (the "pkcs12()" method) comes from BouncyCastle.
+ * </p>
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @author <a href="bouncycastle.org">bouncycastle.org</a>
+ * @since 7-Nov-2006
+ */
+public class PKCS8Key {
+    public final static String RSA_OID = "1.2.840.113549.1.1.1";
+    public final static String DSA_OID = "1.2.840.10040.4.1";
+
+    public final static String PKCS8_UNENCRYPTED = "PRIVATE KEY";
+    public final static String PKCS8_ENCRYPTED = "ENCRYPTED PRIVATE KEY";
+    public final static String OPENSSL_RSA = "RSA PRIVATE KEY";
+    public final static String OPENSSL_DSA = "DSA PRIVATE KEY";
+
+    private final PrivateKey privateKey;
+    private final byte[] decryptedBytes;
+    private final String transformation;
+    private final int keySize;
+    private final boolean isDSA;
+    private final boolean isRSA;
+
+    static {
+        JavaImpl.load();
+    }
+
+    /**
+     * @param in       pkcs8 file to parse (pem or der, encrypted or unencrypted)
+     * @param password password to decrypt the pkcs8 file.  Ignored if the
+     *                 supplied pkcs8 is already unencrypted.
+     * @throws GeneralSecurityException If a parsing or decryption problem
+     *                                  occured.
+     * @throws IOException              If the supplied InputStream could not be read.
+     */
+    public PKCS8Key(final InputStream in, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(Util.streamToBytes(in), password);
+    }
+
+    /**
+     * @param in       pkcs8 file to parse (pem or der, encrypted or unencrypted)
+     * @param password password to decrypt the pkcs8 file.  Ignored if the
+     *                 supplied pkcs8 is already unencrypted.
+     * @throws GeneralSecurityException If a parsing or decryption problem
+     *                                  occured.
+     */
+    public PKCS8Key(final ByteArrayInputStream in, char[] password)
+        throws GeneralSecurityException {
+        this(Util.streamToBytes(in), password);
+    }
+
+    /**
+     * @param encoded  pkcs8 file to parse (pem or der, encrypted or unencrypted)
+     * @param password password to decrypt the pkcs8 file.  Ignored if the
+     *                 supplied pkcs8 is already unencrypted.
+     * @throws GeneralSecurityException If a parsing or decryption problem
+     *                                  occured.
+     */
+    public PKCS8Key(final byte[] encoded, char[] password)
+        throws GeneralSecurityException {
+        DecryptResult decryptResult =
+            new DecryptResult("UNENCRYPTED", 0, encoded);
+
+        List pemItems = PEMUtil.decode(encoded);
+        PEMItem keyItem = null;
+        byte[] derBytes = null;
+        if (pemItems.isEmpty()) {
+            // must be DER encoded - PEMUtil wasn't able to extract anything.
+            derBytes = encoded;
+        } else {
+            Iterator it = pemItems.iterator();
+            boolean opensslRSA = false;
+            boolean opensslDSA = false;
+
+            while (it.hasNext()) {
+                PEMItem item = (PEMItem) it.next();
+                String type = item.pemType.trim().toUpperCase();
+                boolean plainPKCS8 = type.startsWith(PKCS8_UNENCRYPTED);
+                boolean encryptedPKCS8 = type.startsWith(PKCS8_ENCRYPTED);
+                boolean rsa = type.startsWith(OPENSSL_RSA);
+                boolean dsa = type.startsWith(OPENSSL_DSA);
+                if (plainPKCS8 || encryptedPKCS8 || rsa || dsa) {
+                    opensslRSA = opensslRSA || rsa;
+                    opensslDSA = opensslDSA || dsa;
+                    if (derBytes != null) {
+                        throw new ProbablyNotPKCS8Exception("More than one pkcs8 or OpenSSL key found in the supplied PEM Base64 stream");
+                    }
+                    derBytes = item.getDerBytes();
+                    keyItem = item;
+                    decryptResult = new DecryptResult("UNENCRYPTED", 0, derBytes);
+                }
+            }
+            // after the loop is finished, did we find anything?
+            if (derBytes == null) {
+                throw new ProbablyNotPKCS8Exception("No pkcs8 or OpenSSL key found in the supplied PEM Base64 stream");
+            }
+
+            if (opensslDSA || opensslRSA) {
+                String c = keyItem.cipher.trim();
+                boolean encrypted = !"UNKNOWN".equals(c) && !"".equals(c);
+                if (encrypted) {
+                    decryptResult = opensslDecrypt(keyItem, password);
+                }
+
+                String oid = RSA_OID;
+                if (opensslDSA) {
+                    oid = DSA_OID;
+                }
+                derBytes = formatAsPKCS8(decryptResult.bytes, oid, null);
+
+                String tf = decryptResult.transformation;
+                int ks = decryptResult.keySize;
+                decryptResult = new DecryptResult(tf, ks, derBytes);
+            }
+        }
+
+        ASN1Structure pkcs8;
+        try {
+            pkcs8 = ASN1Util.analyze(derBytes);
+        }
+        catch (Exception e) {
+            throw new ProbablyNotPKCS8Exception("asn1 parse failure: " + e);
+        }
+
+        String oid = RSA_OID;
+        // With the OpenSSL unencrypted private keys in DER format, the only way
+        // to even have a hope of guessing what we've got (DSA or RSA?) is to
+        // count the number of DERIntegers occurring in the first DERSequence.
+        int derIntegerCount = -1;
+        if (pkcs8.derIntegers != null) {
+            derIntegerCount = pkcs8.derIntegers.size();
+        }
+        switch (derIntegerCount) {
+            case 6:
+                oid = DSA_OID;
+            case 9:
+                derBytes = formatAsPKCS8(derBytes, oid, pkcs8);
+                pkcs8.oid1 = oid;
+
+                String tf = decryptResult.transformation;
+                int ks = decryptResult.keySize;
+                decryptResult = new DecryptResult(tf, ks, derBytes);
+                break;
+            default:
+                break;
+        }
+
+        oid = pkcs8.oid1;
+        if (!oid.startsWith("1.2.840.113549.1")) {
+            boolean isOkay = false;
+            if (oid.startsWith("1.2.840.10040.4.")) {
+                String s = oid.substring("1.2.840.10040.4.".length());
+                // 1.2.840.10040.4.1 -- id-dsa
+                // 1.2.840.10040.4.3 -- id-dsa-with-sha1
+                isOkay = s.equals("1") || s.startsWith("1.") ||
+                         s.equals("3") || s.startsWith("3.");
+            }
+            if (!isOkay) {
+                throw new ProbablyNotPKCS8Exception("Valid ASN.1, but not PKCS8 or OpenSSL format.  OID=" + oid);
+            }
+        }
+
+        boolean isRSA = RSA_OID.equals(oid);
+        boolean isDSA = DSA_OID.equals(oid);
+        boolean encrypted = !isRSA && !isDSA;
+        byte[] decryptedPKCS8 = encrypted ? null : derBytes;
+
+        if (encrypted) {
+            decryptResult = decryptPKCS8(pkcs8, password);
+            decryptedPKCS8 = decryptResult.bytes;
+        }
+        if (encrypted) {
+            try {
+                pkcs8 = ASN1Util.analyze(decryptedPKCS8);
+            }
+            catch (Exception e) {
+                throw new ProbablyBadPasswordException("Decrypted stream not ASN.1.  Probably bad decryption password.");
+            }
+            oid = pkcs8.oid1;
+            isDSA = DSA_OID.equals(oid);
+        }
+
+        KeySpec spec = new PKCS8EncodedKeySpec(decryptedPKCS8);
+        String type = "RSA";
+        PrivateKey pk;
+        try {
+            KeyFactory KF;
+            if (isDSA) {
+                type = "DSA";
+                KF = KeyFactory.getInstance("DSA");
+            } else {
+                KF = KeyFactory.getInstance("RSA");
+            }
+            pk = KF.generatePrivate(spec);
+        }
+        catch (Exception e) {
+            throw new ProbablyBadPasswordException("Cannot create " + type + " private key from decrypted stream.  Probably bad decryption password. " + e);
+        }
+        if (pk != null) {
+            this.privateKey = pk;
+            this.isDSA = isDSA;
+            this.isRSA = !isDSA;
+            this.decryptedBytes = decryptedPKCS8;
+            this.transformation = decryptResult.transformation;
+            this.keySize = decryptResult.keySize;
+        } else {
+            throw new GeneralSecurityException("KeyFactory.generatePrivate() returned null and didn't throw exception!");
+        }
+    }
+
+    public boolean isRSA() {
+        return isRSA;
+    }
+
+    public boolean isDSA() {
+        return isDSA;
+    }
+
+    public String getTransformation() {
+        return transformation;
+    }
+
+    public int getKeySize() {
+        return keySize;
+    }
+
+    public byte[] getDecryptedBytes() {
+        return decryptedBytes;
+    }
+
+    public PrivateKey getPrivateKey() {
+        return privateKey;
+    }
+
+    public static class DecryptResult {
+        public final String transformation;
+        public final int keySize;
+        public final byte[] bytes;
+
+        protected DecryptResult(String transformation, int keySize,
+                                byte[] decryptedBytes) {
+            this.transformation = transformation;
+            this.keySize = keySize;
+            this.bytes = decryptedBytes;
+        }
+    }
+
+    private static DecryptResult opensslDecrypt(final PEMItem item,
+                                                final char[] password)
+        throws GeneralSecurityException {
+        final String cipher = item.cipher;
+        final String mode = item.mode;
+        final int keySize = item.keySizeInBits;
+        final byte[] salt = item.iv;
+        final boolean des2 = item.des2;
+        final DerivedKey dk = OpenSSL.deriveKey(password, salt, keySize, des2);
+        return decrypt(cipher, mode, dk, des2, null, item.getDerBytes());
+    }
+
+    public static Cipher generateCipher(String cipher, String mode,
+                                        final DerivedKey dk,
+                                        final boolean des2,
+                                        final byte[] iv,
+                                        final boolean decryptMode)
+        throws NoSuchAlgorithmException, NoSuchPaddingException,
+        InvalidKeyException, InvalidAlgorithmParameterException {
+        if (des2 && dk.key.length >= 24) {
+            // copy first 8 bytes into last 8 bytes to create 2DES key.
+            System.arraycopy(dk.key, 0, dk.key, 16, 8);
+        }
+
+        final int keySize = dk.key.length * 8;
+        cipher = cipher.trim();
+        String cipherUpper = cipher.toUpperCase();
+        mode = mode.trim().toUpperCase();
+        // Is the cipher even available?
+        Cipher.getInstance(cipher);
+        String padding = "PKCS5Padding";
+        if (mode.startsWith("CFB") || mode.startsWith("OFB")) {
+            padding = "NoPadding";
+        }
+
+        String transformation = cipher + "/" + mode + "/" + padding;
+        if (cipherUpper.startsWith("RC4")) {
+            // RC4 does not take mode or padding.
+            transformation = cipher;
+        }
+
+        SecretKey secret = new SecretKeySpec(dk.key, cipher);
+        IvParameterSpec ivParams;
+        if (iv != null) {
+            ivParams = new IvParameterSpec(iv);
+        } else {
+            ivParams = dk.iv != null ? new IvParameterSpec(dk.iv) : null;
+        }
+
+        Cipher c = Cipher.getInstance(transformation);
+        int cipherMode = Cipher.ENCRYPT_MODE;
+        if (decryptMode) {
+            cipherMode = Cipher.DECRYPT_MODE;
+        }
+
+        // RC2 requires special params to inform engine of keysize.
+        if (cipherUpper.startsWith("RC2")) {
+            RC2ParameterSpec rcParams;
+            if (mode.startsWith("ECB") || ivParams == null) {
+                // ECB doesn't take an IV.
+                rcParams = new RC2ParameterSpec(keySize);
+            } else {
+                rcParams = new RC2ParameterSpec(keySize, ivParams.getIV());
+            }
+            c.init(cipherMode, secret, rcParams);
+        } else if (cipherUpper.startsWith("RC5")) {
+            RC5ParameterSpec rcParams;
+            if (mode.startsWith("ECB") || ivParams == null) {
+                // ECB doesn't take an IV.
+                rcParams = new RC5ParameterSpec(16, 12, 32);
+            } else {
+                rcParams = new RC5ParameterSpec(16, 12, 32, ivParams.getIV());
+            }
+            c.init(cipherMode, secret, rcParams);
+        } else if (mode.startsWith("ECB") || cipherUpper.startsWith("RC4")) {
+            // RC4 doesn't require any params.
+            // Any cipher using ECB does not require an IV.
+            c.init(cipherMode, secret);
+        } else {
+            // DES, DESede, AES, BlowFish require IVParams (when in CBC, CFB,
+            // or OFB mode).  (In ECB mode they don't require IVParams).
+            c.init(cipherMode, secret, ivParams);
+        }
+        return c;
+    }
+
+    public static DecryptResult decrypt(String cipher, String mode,
+                                        final DerivedKey dk,
+                                        final boolean des2,
+                                        final byte[] iv,
+                                        final byte[] encryptedBytes)
+
+        throws NoSuchAlgorithmException, NoSuchPaddingException,
+        InvalidKeyException, InvalidAlgorithmParameterException,
+        IllegalBlockSizeException, BadPaddingException {
+        Cipher c = generateCipher(cipher, mode, dk, des2, iv, true);
+        final String transformation = c.getAlgorithm();
+        final int keySize = dk.key.length * 8;
+        byte[] decryptedBytes = c.doFinal(encryptedBytes);
+        return new DecryptResult(transformation, keySize, decryptedBytes);
+    }
+
+    private static DecryptResult decryptPKCS8(ASN1Structure pkcs8,
+                                              char[] password)
+        throws GeneralSecurityException {
+        boolean isVersion1 = true;
+        boolean isVersion2 = false;
+        boolean usePKCS12PasswordPadding = false;
+        boolean use2DES = false;
+        String cipher = null;
+        String hash = null;
+        int keySize = -1;
+        // Almost all PKCS8 encrypted keys use CBC.  Looks like the AES OID's can
+        // support different modes, and RC4 doesn't use any mode at all!
+        String mode = "CBC";
+
+        // In PKCS8 Version 2 the IV is stored in the ASN.1 structure for
+        // us, so we don't need to derive it.  Just leave "ivSize" set to 0 for
+        // those ones.
+        int ivSize = 0;
+
+        String oid = pkcs8.oid1;
+        if (oid.startsWith("1.2.840.113549.1.12."))  // PKCS12 key derivation!
+        {
+            usePKCS12PasswordPadding = true;
+
+            // Let's trim this OID to make life a little easier.
+            oid = oid.substring("1.2.840.113549.1.12.".length());
+
+            if (oid.equals("1.1") || oid.startsWith("1.1.")) {
+                // 1.2.840.113549.1.12.1.1
+                hash = "SHA1";
+                cipher = "RC4";
+                keySize = 128;
+            } else if (oid.equals("1.2") || oid.startsWith("1.2.")) {
+                // 1.2.840.113549.1.12.1.2
+                hash = "SHA1";
+                cipher = "RC4";
+                keySize = 40;
+            } else if (oid.equals("1.3") || oid.startsWith("1.3.")) {
+                // 1.2.840.113549.1.12.1.3
+                hash = "SHA1";
+                cipher = "DESede";
+                keySize = 192;
+            } else if (oid.equals("1.4") || oid.startsWith("1.4.")) {
+                // DES2 !!!
+
+                // 1.2.840.113549.1.12.1.4
+                hash = "SHA1";
+                cipher = "DESede";
+                keySize = 192;
+                use2DES = true;
+                // later on we'll copy the first 8 bytes of the 24 byte DESede key
+                // over top the last 8 bytes, making the key look like K1-K2-K1
+                // instead of the usual K1-K2-K3.
+            } else if (oid.equals("1.5") || oid.startsWith("1.5.")) {
+                // 1.2.840.113549.1.12.1.5
+                hash = "SHA1";
+                cipher = "RC2";
+                keySize = 128;
+            } else if (oid.equals("1.6") || oid.startsWith("1.6.")) {
+                // 1.2.840.113549.1.12.1.6
+                hash = "SHA1";
+                cipher = "RC2";
+                keySize = 40;
+            }
+        } else if (oid.startsWith("1.2.840.113549.1.5.")) {
+            // Let's trim this OID to make life a little easier.
+            oid = oid.substring("1.2.840.113549.1.5.".length());
+
+            if (oid.equals("1") || oid.startsWith("1.")) {
+                // 1.2.840.113549.1.5.1 -- pbeWithMD2AndDES-CBC
+                hash = "MD2";
+                cipher = "DES";
+                keySize = 64;
+            } else if (oid.equals("3") || oid.startsWith("3.")) {
+                // 1.2.840.113549.1.5.3 -- pbeWithMD5AndDES-CBC
+                hash = "MD5";
+                cipher = "DES";
+                keySize = 64;
+            } else if (oid.equals("4") || oid.startsWith("4.")) {
+                // 1.2.840.113549.1.5.4 -- pbeWithMD2AndRC2_CBC
+                hash = "MD2";
+                cipher = "RC2";
+                keySize = 64;
+            } else if (oid.equals("6") || oid.startsWith("6.")) {
+                // 1.2.840.113549.1.5.6 -- pbeWithMD5AndRC2_CBC
+                hash = "MD5";
+                cipher = "RC2";
+                keySize = 64;
+            } else if (oid.equals("10") || oid.startsWith("10.")) {
+                // 1.2.840.113549.1.5.10 -- pbeWithSHA1AndDES-CBC
+                hash = "SHA1";
+                cipher = "DES";
+                keySize = 64;
+            } else if (oid.equals("11") || oid.startsWith("11.")) {
+                // 1.2.840.113549.1.5.11 -- pbeWithSHA1AndRC2_CBC
+                hash = "SHA1";
+                cipher = "RC2";
+                keySize = 64;
+            } else if (oid.equals("12") || oid.startsWith("12.")) {
+                // 1.2.840.113549.1.5.12 - id-PBKDF2 - Key Derivation Function
+                isVersion2 = true;
+            } else if (oid.equals("13") || oid.startsWith("13.")) {
+                // 1.2.840.113549.1.5.13 - id-PBES2: PBES2 encryption scheme
+                isVersion2 = true;
+            } else if (oid.equals("14") || oid.startsWith("14.")) {
+                // 1.2.840.113549.1.5.14 - id-PBMAC1 message authentication scheme
+                isVersion2 = true;
+            }
+        }
+        if (isVersion2) {
+            isVersion1 = false;
+            hash = "HmacSHA1";
+            oid = pkcs8.oid2;
+
+            // really ought to be:
+            //
+            // if ( oid.startsWith( "1.2.840.113549.1.5.12" ) )
+            //
+            // but all my tests still pass, and I figure this to be more robust:
+            if (pkcs8.oid3 != null) {
+                oid = pkcs8.oid3;
+            }
+            if (oid.startsWith("1.3.6.1.4.1.3029.1.2")) {
+                // 1.3.6.1.4.1.3029.1.2 - Blowfish
+                cipher = "Blowfish";
+                mode = "CBC";
+                keySize = 128;
+            } else if (oid.startsWith("1.3.14.3.2.")) {
+                oid = oid.substring("1.3.14.3.2.".length());
+                if (oid.equals("6") || oid.startsWith("6.")) {
+                    // 1.3.14.3.2.6 - desECB
+                    cipher = "DES";
+                    mode = "ECB";
+                    keySize = 64;
+                } else if (oid.equals("7") || oid.startsWith("7.")) {
+                    // 1.3.14.3.2.7 - desCBC
+                    cipher = "DES";
+                    mode = "CBC";
+                    keySize = 64;
+                } else if (oid.equals("8") || oid.startsWith("8.")) {
+                    // 1.3.14.3.2.8 - desOFB
+                    cipher = "DES";
+                    mode = "OFB";
+                    keySize = 64;
+                } else if (oid.equals("9") || oid.startsWith("9.")) {
+                    // 1.3.14.3.2.9 - desCFB
+                    cipher = "DES";
+                    mode = "CFB";
+                    keySize = 64;
+                } else if (oid.equals("17") || oid.startsWith("17.")) {
+                    // 1.3.14.3.2.17 - desEDE
+                    cipher = "DESede";
+                    mode = "CBC";
+                    keySize = 192;
+
+                    // If the supplied IV is all zeroes, then this is DES2
+                    // (Well, that's what happened when I played with OpenSSL!)
+                    if (allZeroes(pkcs8.iv)) {
+                        mode = "ECB";
+                        use2DES = true;
+                        pkcs8.iv = null;
+                    }
+                }
+            }
+
+            // AES
+            // 2.16.840.1.101.3.4.1.1  - id-aes128-ECB
+            // 2.16.840.1.101.3.4.1.2  - id-aes128-CBC
+            // 2.16.840.1.101.3.4.1.3  - id-aes128-OFB
+            // 2.16.840.1.101.3.4.1.4  - id-aes128-CFB
+            // 2.16.840.1.101.3.4.1.21 - id-aes192-ECB
+            // 2.16.840.1.101.3.4.1.22 - id-aes192-CBC
+            // 2.16.840.1.101.3.4.1.23 - id-aes192-OFB
+            // 2.16.840.1.101.3.4.1.24 - id-aes192-CFB
+            // 2.16.840.1.101.3.4.1.41 - id-aes256-ECB
+            // 2.16.840.1.101.3.4.1.42 - id-aes256-CBC
+            // 2.16.840.1.101.3.4.1.43 - id-aes256-OFB
+            // 2.16.840.1.101.3.4.1.44 - id-aes256-CFB
+            else if (oid.startsWith("2.16.840.1.101.3.4.1.")) {
+                cipher = "AES";
+                if (pkcs8.iv == null) {
+                    ivSize = 128;
+                }
+                oid = oid.substring("2.16.840.1.101.3.4.1.".length());
+                int x = oid.indexOf('.');
+                int finalDigit;
+                if (x >= 0) {
+                    finalDigit = Integer.parseInt(oid.substring(0, x));
+                } else {
+                    finalDigit = Integer.parseInt(oid);
+                }
+                switch (finalDigit % 10) {
+                    case 1:
+                        mode = "ECB";
+                        break;
+                    case 2:
+                        mode = "CBC";
+                        break;
+                    case 3:
+                        mode = "OFB";
+                        break;
+                    case 4:
+                        mode = "CFB";
+                        break;
+                    default:
+                        throw new RuntimeException("Unknown AES final digit: " + finalDigit);
+                }
+                switch (finalDigit / 10) {
+                    case 0:
+                        keySize = 128;
+                        break;
+                    case 2:
+                        keySize = 192;
+                        break;
+                    case 4:
+                        keySize = 256;
+                        break;
+                    default:
+                        throw new RuntimeException("Unknown AES final digit: " + finalDigit);
+                }
+            } else if (oid.startsWith("1.2.840.113549.3.")) {
+                // Let's trim this OID to make life a little easier.
+                oid = oid.substring("1.2.840.113549.3.".length());
+
+                if (oid.equals("2") || oid.startsWith("2.")) {
+                    // 1.2.840.113549.3.2 - RC2-CBC
+                    // Note:  keysize determined in PKCS8 Version 2.0 ASN.1 field.
+                    cipher = "RC2";
+                    keySize = pkcs8.keySize * 8;
+                } else if (oid.equals("4") || oid.startsWith("4.")) {
+                    // 1.2.840.113549.3.4 - RC4
+                    // Note:  keysize determined in PKCS8 Version 2.0 ASN.1 field.
+                    cipher = "RC4";
+                    keySize = pkcs8.keySize * 8;
+                } else if (oid.equals("7") || oid.startsWith("7.")) {
+                    // 1.2.840.113549.3.7 - DES-EDE3-CBC
+                    cipher = "DESede";
+                    keySize = 192;
+                } else if (oid.equals("9") || oid.startsWith("9.")) {
+                    // 1.2.840.113549.3.9 - RC5 CBC Pad
+                    // Note:  keysize determined in PKCS8 Version 2.0 ASN.1 field.
+                    keySize = pkcs8.keySize * 8;
+                    cipher = "RC5";
+
+                    // Need to find out more about RC5.
+                    // How do I create the RC5ParameterSpec?
+                    // (int version, int rounds, int wordSize, byte[] iv)
+                }
+            }
+        }
+
+        // The pkcs8 structure has been thoroughly examined.  If we don't have
+        // a cipher or hash at this point, then we don't support the file we
+        // were given.
+        if (cipher == null || hash == null) {
+            throw new ProbablyNotPKCS8Exception("Unsupported PKCS8 format. oid1=[" + pkcs8.oid1 + "], oid2=[" + pkcs8.oid2 + "]");
+        }
+
+        // In PKCS8 Version 1.5 we need to derive an 8 byte IV.  In those cases
+        // the ASN.1 structure doesn't have the IV, anyway, so I can use that
+        // to decide whether to derive one or not.
+        //
+        // Note:  if AES, then IV has to be 16 bytes.
+        if (pkcs8.iv == null) {
+            ivSize = 64;
+        }
+
+        byte[] salt = pkcs8.salt;
+        int ic = pkcs8.iterationCount;
+
+        // PKCS8 converts the password to a byte[] array using a simple
+        // cast.  This byte[] array is ignored if we're using the PKCS12
+        // key derivation, since that employs a different technique.
+        byte[] pwd = new byte[password.length];
+        for (int i = 0; i < pwd.length; i++) {
+            pwd[i] = (byte) password[i];
+        }
+
+        DerivedKey dk;
+        if (usePKCS12PasswordPadding) {
+            MessageDigest md = MessageDigest.getInstance(hash);
+            dk = deriveKeyPKCS12(password, salt, ic, keySize, ivSize, md);
+        } else {
+            if (isVersion1) {
+                MessageDigest md = MessageDigest.getInstance(hash);
+                dk = deriveKeyV1(pwd, salt, ic, keySize, ivSize, md);
+            } else {
+                Mac mac = Mac.getInstance(hash);
+                dk = deriveKeyV2(pwd, salt, ic, keySize, ivSize, mac);
+            }
+        }
+
+
+        return decrypt(cipher, mode, dk, use2DES, pkcs8.iv, pkcs8.bigPayload);
+    }
+
+
+    public static DerivedKey deriveKeyV1(byte[] password, byte[] salt,
+                                         int iterations, int keySizeInBits,
+                                         int ivSizeInBits, MessageDigest md) {
+        int keySize = keySizeInBits / 8;
+        int ivSize = ivSizeInBits / 8;
+        md.reset();
+        md.update(password);
+        byte[] result = md.digest(salt);
+        for (int i = 1; i < iterations; i++) {
+            // Hash of the hash for each of the iterations.
+            result = md.digest(result);
+        }
+        byte[] key = new byte[keySize];
+        byte[] iv = new byte[ivSize];
+        System.arraycopy(result, 0, key, 0, key.length);
+        System.arraycopy(result, key.length, iv, 0, iv.length);
+        return new DerivedKey(key, iv);
+    }
+
+    public static DerivedKey deriveKeyPKCS12(char[] password, byte[] salt,
+                                             int iterations, int keySizeInBits,
+                                             int ivSizeInBits,
+                                             MessageDigest md) {
+        byte[] pwd;
+        if (password.length > 0) {
+            pwd = new byte[(password.length + 1) * 2];
+            for (int i = 0; i < password.length; i++) {
+                pwd[i * 2] = (byte) (password[i] >>> 8);
+                pwd[i * 2 + 1] = (byte) password[i];
+            }
+        } else {
+            pwd = new byte[0];
+        }
+        int keySize = keySizeInBits / 8;
+        int ivSize = ivSizeInBits / 8;
+        byte[] key = pkcs12(1, keySize, salt, pwd, iterations, md);
+        byte[] iv = pkcs12(2, ivSize, salt, pwd, iterations, md);
+        return new DerivedKey(key, iv);
+    }
+
+    /**
+     * This PKCS12 key derivation code comes from BouncyCastle.
+     *
+     * @param idByte         1 == key, 2 == iv
+     * @param n              keysize or ivsize
+     * @param salt           8 byte salt
+     * @param password       password
+     * @param iterationCount iteration-count
+     * @param md             The message digest to use
+     * @return byte[] the derived key
+     */
+    private static byte[] pkcs12(int idByte, int n, byte[] salt,
+                                 byte[] password, int iterationCount,
+                                 MessageDigest md) {
+        int u = md.getDigestLength();
+        // sha1, md2, md5 all use 512 bits.  But future hashes might not.
+        int v = 512 / 8;
+        md.reset();
+        byte[] D = new byte[v];
+        byte[] dKey = new byte[n];
+        for (int i = 0; i != D.length; i++) {
+            D[i] = (byte) idByte;
+        }
+        byte[] S;
+        if ((salt != null) && (salt.length != 0)) {
+            S = new byte[v * ((salt.length + v - 1) / v)];
+            for (int i = 0; i != S.length; i++) {
+                S[i] = salt[i % salt.length];
+            }
+        } else {
+            S = new byte[0];
+        }
+        byte[] P;
+        if ((password != null) && (password.length != 0)) {
+            P = new byte[v * ((password.length + v - 1) / v)];
+            for (int i = 0; i != P.length; i++) {
+                P[i] = password[i % password.length];
+            }
+        } else {
+            P = new byte[0];
+        }
+        byte[] I = new byte[S.length + P.length];
+        System.arraycopy(S, 0, I, 0, S.length);
+        System.arraycopy(P, 0, I, S.length, P.length);
+        byte[] B = new byte[v];
+        int c = (n + u - 1) / u;
+        for (int i = 1; i <= c; i++) {
+            md.update(D);
+            byte[] result = md.digest(I);
+            for (int j = 1; j != iterationCount; j++) {
+                result = md.digest(result);
+            }
+            for (int j = 0; j != B.length; j++) {
+                B[j] = result[j % result.length];
+            }
+            for (int j = 0; j < (I.length / v); j++) {
+                /*
+                     * add a + b + 1, returning the result in a. The a value is treated
+                     * as a BigInteger of length (b.length * 8) bits. The result is
+                     * modulo 2^b.length in case of overflow.
+                     */
+                int aOff = j * v;
+                int bLast = B.length - 1;
+                int x = (B[bLast] & 0xff) + (I[aOff + bLast] & 0xff) + 1;
+                I[aOff + bLast] = (byte) x;
+                x >>>= 8;
+                for (int k = B.length - 2; k >= 0; k--) {
+                    x += (B[k] & 0xff) + (I[aOff + k] & 0xff);
+                    I[aOff + k] = (byte) x;
+                    x >>>= 8;
+                }
+            }
+            if (i == c) {
+                System.arraycopy(result, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
+            } else {
+                System.arraycopy(result, 0, dKey, (i - 1) * u, result.length);
+            }
+        }
+        return dKey;
+    }
+
+    public static DerivedKey deriveKeyV2(byte[] password, byte[] salt,
+                                         int iterations, int keySizeInBits,
+                                         int ivSizeInBits, Mac mac)
+        throws InvalidKeyException {
+        int keySize = keySizeInBits / 8;
+        int ivSize = ivSizeInBits / 8;
+
+        // Because we're using an Hmac, we need to initialize with a SecretKey.
+        // HmacSHA1 doesn't need SecretKeySpec's 2nd parameter, hence the "N/A".
+        SecretKeySpec sk = new SecretKeySpec(password, "N/A");
+        mac.init(sk);
+        int macLength = mac.getMacLength();
+        int derivedKeyLength = keySize + ivSize;
+        int blocks = (derivedKeyLength + macLength - 1) / macLength;
+        byte[] blockIndex = new byte[4];
+        byte[] finalResult = new byte[blocks * macLength];
+        for (int i = 1; i <= blocks; i++) {
+            int offset = (i - 1) * macLength;
+            blockIndex[0] = (byte) (i >>> 24);
+            blockIndex[1] = (byte) (i >>> 16);
+            blockIndex[2] = (byte) (i >>> 8);
+            blockIndex[3] = (byte) i;
+            mac.reset();
+            mac.update(salt);
+            byte[] result = mac.doFinal(blockIndex);
+            System.arraycopy(result, 0, finalResult, offset, result.length);
+            for (int j = 1; j < iterations; j++) {
+                mac.reset();
+                result = mac.doFinal(result);
+                for (int k = 0; k < result.length; k++) {
+                    finalResult[offset + k] ^= result[k];
+                }
+            }
+        }
+        byte[] key = new byte[keySize];
+        byte[] iv = new byte[ivSize];
+        System.arraycopy(finalResult, 0, key, 0, key.length);
+        System.arraycopy(finalResult, key.length, iv, 0, iv.length);
+        return new DerivedKey(key, iv);
+    }
+
+    public static byte[] formatAsPKCS8(byte[] privateKey, String oid,
+                                       ASN1Structure pkcs8) {
+        DERInteger derZero = new DERInteger(BigInteger.ZERO);
+        ASN1EncodableVector outterVec = new ASN1EncodableVector();
+        ASN1EncodableVector innerVec = new ASN1EncodableVector();
+        DEROctetString octetsToAppend;
+        try {
+            DERObjectIdentifier derOID = new DERObjectIdentifier(oid);
+            innerVec.add(derOID);
+            if (DSA_OID.equals(oid)) {
+                if (pkcs8 == null) {
+                    try {
+                        pkcs8 = ASN1Util.analyze(privateKey);
+                    }
+                    catch (Exception e) {
+                        throw new RuntimeException("asn1 parse failure " + e);
+                    }
+                }
+                if (pkcs8.derIntegers == null || pkcs8.derIntegers.size() < 6) {
+                    throw new RuntimeException("invalid DSA key - can't find P, Q, G, X");
+                }
+
+                DERInteger[] ints = new DERInteger[pkcs8.derIntegers.size()];
+                pkcs8.derIntegers.toArray(ints);
+                DERInteger p = ints[1];
+                DERInteger q = ints[2];
+                DERInteger g = ints[3];
+                DERInteger x = ints[5];
+
+                byte[] encodedX = encode(x);
+                octetsToAppend = new DEROctetString(encodedX);
+                ASN1EncodableVector pqgVec = new ASN1EncodableVector();
+                pqgVec.add(p);
+                pqgVec.add(q);
+                pqgVec.add(g);
+                DERSequence pqg = new DERSequence(pqgVec);
+                innerVec.add(pqg);
+            } else {
+                innerVec.add(DERNull.INSTANCE);
+                octetsToAppend = new DEROctetString(privateKey);
+            }
+
+            DERSequence inner = new DERSequence(innerVec);
+            outterVec.add(derZero);
+            outterVec.add(inner);
+            outterVec.add(octetsToAppend);
+            DERSequence outter = new DERSequence(outterVec);
+            return encode(outter);
+        }
+        catch (IOException ioe) {
+            throw JavaImpl.newRuntimeException(ioe);
+        }
+    }
+
+    private static boolean allZeroes(byte[] b) {
+        for (int i = 0; i < b.length; i++) {
+            if (b[i] != 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static byte[] encode(DEREncodable der) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+        ASN1OutputStream out = new ASN1OutputStream(baos);
+        out.writeObject(der);
+        out.close();
+        return baos.toByteArray();
+    }
+
+    public static void main(String[] args) throws Exception {
+        String password = "changeit";
+        if (args.length == 0) {
+            System.out.println("Usage1:  [password] [file:private-key]      Prints decrypted PKCS8 key (base64).");
+            System.out.println("Usage2:  [password] [file1] [file2] etc...  Checks that all private keys are equal.");
+            System.out.println("Usage2 assumes that all files can be decrypted with the same password.");
+        } else if (args.length == 1 || args.length == 2) {
+            FileInputStream in = new FileInputStream(args[args.length - 1]);
+            if (args.length == 2) {
+                password = args[0];
+            }
+            byte[] bytes = Util.streamToBytes(in);
+            PKCS8Key key = new PKCS8Key(bytes, password.toCharArray());
+            PEMItem item = new PEMItem(key.getDecryptedBytes(), "PRIVATE KEY");
+            byte[] pem = PEMUtil.encode(Collections.singleton(item));
+            System.out.write(pem);
+        } else {
+            byte[] original = null;
+            File f = new File(args[0]);
+            int i = 0;
+            if (!f.exists()) {
+                // File0 doesn't exist, so it must be a password!
+                password = args[0];
+                i++;
+            }
+            for (; i < args.length; i++) {
+                FileInputStream in = new FileInputStream(args[i]);
+                byte[] bytes = Util.streamToBytes(in);
+                PKCS8Key key = null;
+                try {
+                    key = new PKCS8Key(bytes, password.toCharArray());
+                }
+                catch (Exception e) {
+                    System.out.println(" FAILED! " + args[i] + " " + e);
+                }
+                if (key != null) {
+                    byte[] decrypted = key.getDecryptedBytes();
+                    int keySize = key.getKeySize();
+                    String keySizeStr = "" + keySize;
+                    if (keySize < 10) {
+                        keySizeStr = "  " + keySizeStr;
+                    } else if (keySize < 100) {
+                        keySizeStr = " " + keySizeStr;
+                    }
+                    StringBuffer buf = new StringBuffer(key.getTransformation());
+                    int maxLen = "Blowfish/CBC/PKCS5Padding".length();
+                    for (int j = buf.length(); j < maxLen; j++) {
+                        buf.append(' ');
+                    }
+                    String transform = buf.toString();
+                    String type = key.isDSA() ? "DSA" : "RSA";
+
+                    if (original == null) {
+                        original = decrypted;
+                        System.out.println("   SUCCESS    \t" + type + "\t" + transform + "\t" + keySizeStr + "\t" + args[i]);
+                    } else {
+                        boolean identical = Arrays.equals(original, decrypted);
+                        if (!identical) {
+                            System.out.println("***FAILURE*** \t" + type + "\t" + transform + "\t" + keySizeStr + "\t" + args[i]);
+                        } else {
+                            System.out.println("   SUCCESS    \t" + type + "\t" + transform + "\t" + keySizeStr + "\t" + args[i]);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/Ping.java b/src/java/org/apache/commons/ssl/Ping.java
new file mode 100644
index 0000000..87bdf60
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Ping.java
@@ -0,0 +1,464 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Ping.java $
+ * $Revision: 129 $
+ * $Date: 2007-11-14 19:21:33 -0800 (Wed, 14 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLSocket;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 30-Mar-2006
+ */
+public class Ping {
+    protected static SortedSet ARGS = new TreeSet();
+    protected static Map ARGS_MATCH = new HashMap();
+    protected final static Arg ARG_TARGET = new Arg("-t", "--target", "[hostname[:port]]              default port=443", true);
+    protected final static Arg ARG_BIND = new Arg("-b", "--bind", "[hostname[:port]]              default port=0 \"ANY\"");
+    protected final static Arg ARG_PROXY = new Arg("-r", "--proxy", "[hostname[:port]]              default port=80");
+    protected final static Arg ARG_TRUST_CERT = new Arg("-tm", "--trust-cert", "[path to trust material]       {pem, der, crt, jks}");
+    protected final static Arg ARG_CLIENT_CERT = new Arg("-km", "--client-cert", "[path to client's private key] {jks, pkcs12, pkcs8}");
+    protected final static Arg ARG_CERT_CHAIN = new Arg("-cc", "--cert-chain", "[path to client's cert chain for pkcs8/OpenSSL key]");
+    protected final static Arg ARG_PASSWORD = new Arg("-p", "--password", "[client cert password]");
+    protected final static Arg ARG_HOST_HEADER = new Arg("-h", "--host-header", "[http-host-header]      in case -t is an IP address");
+    protected final static Arg ARG_PATH = new Arg("-u", "--path", "[path for GET/HEAD request]    default=/");
+    protected final static Arg ARG_METHOD = new Arg("-m", "--method", "[http method to use]           default=HEAD");
+
+    private static HostPort target;
+    private static HostPort local;
+    private static HostPort proxy;
+    private static String hostHeader;
+    private static String httpMethod = "HEAD";
+    private static String path = "/";
+    private static InetAddress targetAddress;
+    private static InetAddress localAddress;
+    private static int targetPort = 443;
+    private static int localPort = 0;
+    private static File clientCert;
+    private static File certChain;
+    private static char[] password;
+    private static TrustChain trustChain = new TrustChain();
+
+    static {
+        ARGS = Collections.unmodifiableSortedSet(ARGS);
+        ARGS_MATCH = Collections.unmodifiableMap(ARGS_MATCH);
+    }
+
+    public static void main(String[] args) throws Exception {
+        boolean showUsage = args.length == 0;
+        Exception parseException = null;
+        if (!showUsage) {
+            try {
+                parseArgs(args);
+            }
+            catch (Exception e) {
+                parseException = e;
+                showUsage = true;
+            }
+        }
+        if (showUsage) {
+            if (parseException != null) {
+                System.out.println();
+                System.out.println("* Error: " + parseException.getMessage() + ".");
+                parseException.printStackTrace(System.out);
+                System.out.println();
+            }
+            System.out.println("Usage:  java -jar not-yet-commons-ssl-0.3.9.jar [options]");
+            System.out.println(Version.versionString());
+            System.out.println("Options:   (*=required)");
+            Iterator it = ARGS.iterator();
+            while (it.hasNext()) {
+                Arg a = (Arg) it.next();
+                String s = Util.pad(a.shortArg, 3, false);
+                String l = Util.pad(a.longArg, 18, false);
+                String required = a.isRequired ? "*" : " ";
+                String d = a.description;
+                System.out.println(required + "  " + s + " " + l + " " + d);
+            }
+            System.out.println();
+            String example = "java -jar commons-ssl.jar -t host.com:443 -c ./client.pfx -p `cat ./pass.txt` ";
+            System.out.println("Example:");
+            System.out.println();
+            System.out.println(example);
+            System.out.println();
+            System.exit(1);
+            return;
+        }
+
+        SSLClient ssl = new SSLClient();
+        Socket s = null;
+        InputStream in = null;
+        OutputStream out = null;
+        Exception socketException = null;
+        Exception trustException = null;
+        Exception hostnameException = null;
+        Exception crlException = null;
+        Exception expiryException = null;
+        String sslCipher = null;
+        try {
+            try {
+                ssl.setCheckHostname(false);
+                ssl.setCheckExpiry(false);
+                ssl.setCheckCRL(false);
+                ssl.addTrustMaterial(TrustMaterial.TRUST_ALL);
+                if (clientCert != null) {
+
+                    KeyMaterial km;
+                    if (certChain != null) {
+                        km = new KeyMaterial(clientCert, certChain, password);
+                    } else {
+                        km = new KeyMaterial(clientCert, password);
+                    }
+                    if (password != null) {
+                        for (int i = 0; i < password.length; i++) {
+                            password[i] = 0;
+                        }
+                    }
+                    ssl.setKeyMaterial(km);
+                }
+
+                if (!trustChain.isEmpty()) {
+                    ssl.addTrustMaterial(trustChain);
+                }
+
+                ssl.setSoTimeout(10000);
+                ssl.setConnectTimeout(5000);
+
+                if (proxy != null) {
+                    s = new Socket(proxy.host, proxy.port,
+                        local.addr, local.port);
+                    s.setSoTimeout(10000);
+                    in = s.getInputStream();
+                    out = s.getOutputStream();
+                    String targetHost = target.host;
+                    String line1 = "CONNECT " + targetHost + ":" + targetPort + " HTTP/1.1\r\n";
+                    String line2 = "Proxy-Connection: keep-alive\r\n";
+                    String line3 = "Host: " + targetHost + "\r\n\r\n";
+                    out.write(line1.getBytes());
+                    out.write(line2.getBytes());
+                    out.write(line3.getBytes());
+                    out.flush();
+
+                    String read1 = Util.readLine(in);
+                    if (read1.startsWith("HTTP/1.1 200")) {
+                        int avail = in.available();
+                        in.skip(avail);
+                        Thread.yield();
+                        avail = in.available();
+                        while (avail != 0) {
+                            in.skip(avail);
+                            Thread.yield();
+                            avail = in.available();
+                        }
+                        s = ssl.createSocket(s, targetHost, targetPort, true);
+                    } else {
+                        System.out.print(line1);
+                        System.out.print(line2);
+                        System.out.print(line3);
+                        System.out.println("Server returned unexpected proxy response!");
+                        System.out.println("=============================================");
+                        System.out.println(read1);
+                        String line = Util.readLine(in);
+                        while (line != null) {
+                            System.out.println(line);
+                            line = Util.readLine(in);
+                        }
+                        System.exit(1);
+                    }
+                } else {
+                    s = ssl.createSocket(targetAddress, targetPort,
+                        localAddress, localPort);
+                }
+
+                sslCipher = ((SSLSocket) s).getSession().getCipherSuite();
+                System.out.println("Cipher: " + sslCipher);
+                System.out.println("================================================================================");
+
+                String line1 = httpMethod + " " + path + " HTTP/1.1";
+                if (hostHeader == null) {
+                    hostHeader = targetAddress.getHostName();
+                }
+                String line2 = "Host: " + hostHeader;
+                byte[] crlf = {'\r', '\n'};
+
+                System.out.println("Writing: ");
+                System.out.println("================================================================================");
+                System.out.println(line1);
+                System.out.println(line2);
+                System.out.println();
+
+                out = s.getOutputStream();
+                out.write(line1.getBytes());
+                out.write(crlf);
+                out.write(line2.getBytes());
+                out.write(crlf);
+                out.write(crlf);
+                out.flush();
+
+                in = s.getInputStream();
+
+                int c = in.read();
+                StringBuffer buf = new StringBuffer();
+                System.out.println("Reading: ");
+                System.out.println("================================================================================");
+                while (c >= 0) {
+                    byte b = (byte) c;
+                    buf.append((char) b);
+                    System.out.print((char) b);
+                    if (-1 == buf.toString().indexOf("\r\n\r\n")) {
+                        c = in.read();
+                    } else {
+                        break;
+                    }
+                }
+            }
+            catch (Exception e) {
+                socketException = e;
+            }
+            trustException = testTrust(ssl, sslCipher);
+            hostnameException = testHostname(ssl);
+            crlException = testCRL(ssl);
+            expiryException = testExpiry(ssl);
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+            if (in != null) {
+                in.close();
+            }
+            if (s != null) {
+                s.close();
+            }
+
+            X509Certificate[] peerChain = ssl.getCurrentServerChain();
+            if (peerChain != null) {
+                String title = "Server Certificate Chain for: ";
+                title = peerChain.length > 1 ? title : "Server Certificate for: ";
+                System.out.println(title + "[" + target + "]");
+                System.out.println("================================================================================");
+                for (int i = 0; i < peerChain.length; i++) {
+                    X509Certificate cert = peerChain[i];
+                    String certAsString = Certificates.toString(cert);
+                    String certAsPEM = Certificates.toPEMString(cert);
+                    if (i > 0) {
+                        System.out.println();
+                    }
+                    System.out.print(certAsString);
+                    System.out.print(certAsPEM);
+                }
+            }
+            if (hostnameException != null) {
+                hostnameException.printStackTrace();
+                System.out.println();
+            }
+            if (crlException != null) {
+                crlException.printStackTrace();
+                System.out.println();
+            }
+            if (expiryException != null) {
+                expiryException.printStackTrace();
+                System.out.println();
+            }
+            if (trustException != null) {
+                trustException.printStackTrace();
+                System.out.println();
+            }
+            if (socketException != null) {
+                socketException.printStackTrace();
+                System.out.println();
+            }
+        }
+    }
+
+    private static Exception testTrust(SSLClient ssl, String cipher) {
+        try {
+            X509Certificate[] chain = ssl.getCurrentServerChain();
+            String authType = Util.cipherToAuthType(cipher);
+            if (authType == null) {
+                // default of "RSA" just for Ping's purposes.
+                authType = "RSA";
+            }
+            if (chain != null) {
+                Object[] trustManagers = TrustMaterial.DEFAULT.getTrustManagers();
+                for (int i = 0; i < trustManagers.length; i++) {
+                    JavaImpl.testTrust(trustManagers[i], chain, authType);
+                }
+            }
+        }
+        catch (Exception e) {
+            return e;
+        }
+        return null;
+    }
+
+    private static Exception testHostname(SSLClient ssl) {
+        try {
+            X509Certificate[] chain = ssl.getCurrentServerChain();
+            if (chain != null) {
+                String hostName = target.host;
+                HostnameVerifier.DEFAULT.check(hostName, chain[0]);
+            }
+        }
+        catch (Exception e) {
+            return e;
+        }
+        return null;
+    }
+
+    private static Exception testCRL(SSLClient ssl) {
+        try {
+            X509Certificate[] chain = ssl.getCurrentServerChain();
+            if (chain != null) {
+                for (int i = 0; i < chain.length; i++) {
+                    Certificates.checkCRL(chain[i]);
+                }
+            }
+        }
+        catch (Exception e) {
+            return e;
+        }
+        return null;
+    }
+
+    private static Exception testExpiry(SSLClient ssl) {
+        try {
+            X509Certificate[] chain = ssl.getCurrentServerChain();
+            if (chain != null) {
+                for (int i = 0; i < chain.length; i++) {
+                    chain[i].checkValidity();
+                }
+            }
+        }
+        catch (Exception e) {
+            return e;
+        }
+        return null;
+    }
+
+
+    public static class Arg implements Comparable {
+        public final String shortArg;
+        public final String longArg;
+        public final String description;
+        public final boolean isRequired;
+        private final int id;
+
+        public Arg(String s, String l, String d) {
+            this(s, l, d, false);
+        }
+
+        public Arg(String s, String l, String d, boolean isRequired) {
+            this.isRequired = isRequired;
+            this.shortArg = s;
+            this.longArg = l;
+            this.description = d;
+            this.id = ARGS.size();
+            ARGS.add(this);
+            if (s != null && s.length() >= 2) {
+                ARGS_MATCH.put(s, this);
+            }
+            if (l != null && l.length() >= 3) {
+                ARGS_MATCH.put(l, this);
+            }
+        }
+
+        public int compareTo(Object o) {
+            return id - ((Arg) o).id;
+        }
+
+        public String toString() {
+            return shortArg + "/" + longArg;
+        }
+    }
+
+    private static void parseArgs(String[] cargs) throws Exception {
+        Map args = Util.parseArgs(cargs);
+        Iterator it = args.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Arg arg = (Arg) entry.getKey();
+            String[] values = (String[]) entry.getValue();
+            if (arg == ARG_TARGET) {
+                target = Util.toAddress(values[0], 443);
+                targetAddress = target.addr;
+                targetPort = target.port;
+            } else if (arg == ARG_BIND) {
+                local = Util.toAddress(values[0], 443);
+                localAddress = local.addr;
+                localPort = local.port;
+            } else if (arg == ARG_PROXY) {
+                proxy = Util.toAddress(values[0], 80);
+            } else if (arg == ARG_CLIENT_CERT) {
+                clientCert = new File(values[0]);
+            } else if (arg == ARG_CERT_CHAIN) {
+                certChain = new File(values[0]);
+            } else if (arg == ARG_PASSWORD) {
+                password = values[0].toCharArray();
+            } else if (arg == ARG_METHOD) {
+                httpMethod = values[0].trim();
+            } else if (arg == ARG_PATH) {
+                path = values[0].trim();
+            } else if (arg == ARG_HOST_HEADER) {
+                hostHeader = values[0].trim();
+            } else if (arg == ARG_TRUST_CERT) {
+                for (int i = 0; i < values.length; i++) {
+                    File f = new File(values[i]);
+                    if (f.exists()) {
+                        TrustMaterial tm = new TrustMaterial(f);
+                        trustChain.addTrustMaterial(tm);
+                    }
+                }
+            }
+        }
+        args.clear();
+        for (int i = 0; i < cargs.length; i++) {
+            cargs[i] = null;
+        }
+
+        if (targetAddress == null) {
+            throw new IllegalArgumentException("\"" + ARG_TARGET + "\" is mandatory");
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/ProbablyBadPasswordException.java b/src/java/org/apache/commons/ssl/ProbablyBadPasswordException.java
new file mode 100644
index 0000000..83e96b6
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/ProbablyBadPasswordException.java
@@ -0,0 +1,51 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/ProbablyBadPasswordException.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+public class ProbablyBadPasswordException extends GeneralSecurityException {
+    public ProbablyBadPasswordException() { super(); }
+
+    public ProbablyBadPasswordException(String s) { super(s); }
+
+    // Need to wait for Java 5.0 !
+    // public ProbablyBadPasswordException( Throwable t ) { super( t ); }
+    // public ProbablyBadPasswordException( String s, Throwable t ) { super( s, t ); }
+
+}
diff --git a/src/java/org/apache/commons/ssl/ProbablyNotPKCS8Exception.java b/src/java/org/apache/commons/ssl/ProbablyNotPKCS8Exception.java
new file mode 100644
index 0000000..d0e54b5
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/ProbablyNotPKCS8Exception.java
@@ -0,0 +1,50 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/ProbablyNotPKCS8Exception.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+public class ProbablyNotPKCS8Exception extends GeneralSecurityException {
+    public ProbablyNotPKCS8Exception() { super(); }
+
+    public ProbablyNotPKCS8Exception(String s) { super(s); }
+
+    // Need to wait for Java 5.0 !
+    // public ProbablyNotPKCS8Exception( Throwable t ) { super( t ); }
+    // public ProbablyNotPKCS8Exception( String s, Throwable t ) { super( s, t ); }
+}
diff --git a/src/java/org/apache/commons/ssl/RMISocketFactoryImpl.java b/src/java/org/apache/commons/ssl/RMISocketFactoryImpl.java
new file mode 100644
index 0000000..3bbe2c5
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/RMISocketFactoryImpl.java
@@ -0,0 +1,578 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/RMISocketFactoryImpl.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ServerSocketFactory;
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLProtocolException;
+import javax.net.ssl.SSLSocket;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.rmi.server.RMISocketFactory;
+import java.security.GeneralSecurityException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+
+/**
+ * An RMISocketFactory ideal for using RMI over SSL.  The server secures both
+ * the registry and the remote objects.  The client assumes that either both
+ * the registry and the remote objects will use SSL, or both will use
+ * plain-socket.  The client is able to auto detect plain-socket registries
+ * and downgrades itself to accomodate those.
+ * <p/>
+ * Unlike most existing RMI over SSL solutions in use (including Java 5's
+ * javax.rmi.ssl.SslRMIClientSocketFactory), this one does proper SSL hostname
+ * verification.  From the client perspective this is straighforward.  From
+ * the server perspective we introduce a clever trick:  we perform an initial
+ * "hostname verification" by trying the current value of
+ * "java.rmi.server.hostname" against our server certificate.  If the
+ * "java.rmi.server.hostname" System Property isn't set, we set it ourselves
+ * using the CN value we extract from our server certificate!  (Some
+ * complications arise should a wildcard certificate show up, but we try our
+ * best to deal with those).
+ * <p/>
+ * An SSL server cannot be started without a private key.  We have defined some
+ * default behaviour for trying to find a private key to use that we believe
+ * is convenient and sensible:
+ * <p/>
+ * If running from inside Tomcat, we try to re-use Tomcat's private key and
+ * certificate chain (assuming Tomcat-SSL on port 8443 is enabled).  If this
+ * isn't available, we look for the "javax.net.ssl.keyStore" System property.
+ * Finally, if that isn't available, we look for "~/.keystore" and assume
+ * a password of "changeit".
+ * <p/>
+ * If after all these attempts we still failed to find a private key, the
+ * RMISocketFactoryImpl() constructor will throw an SSLException.
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Apr-2005
+ */
+public class RMISocketFactoryImpl extends RMISocketFactory {
+    public final static String RMI_HOSTNAME_KEY = "java.rmi.server.hostname";
+    private final static LogWrapper log = LogWrapper.getLogger(RMISocketFactoryImpl.class);
+
+    private volatile SocketFactory defaultClient;
+    private volatile ServerSocketFactory sslServer;
+    private volatile String localBindAddress = null;
+    private volatile int anonymousPort = 31099;
+    private Map clientMap = new TreeMap();
+    private Map serverSockets = new HashMap();
+    private final SocketFactory plainClient = SocketFactory.getDefault();
+
+    public RMISocketFactoryImpl() throws GeneralSecurityException, IOException {
+        this(true);
+    }
+
+    /**
+     * @param createDefaultServer If false, then we only set the default
+     *                            client, and the default server is set to null.
+     *                            If true, then a default server is also created.
+     * @throws GeneralSecurityException bad things
+     * @throws IOException              bad things
+     */
+    public RMISocketFactoryImpl(boolean createDefaultServer)
+        throws GeneralSecurityException, IOException {
+        SSLServer defaultServer = createDefaultServer ? new SSLServer() : null;
+        SSLClient defaultClient = new SSLClient();
+
+        // RMI calls to localhost will not check that host matches CN in
+        // certificate.  Hopefully this is acceptable.  (The registry server
+        // will followup the registry lookup with the proper DNS name to get
+        // the remote object, anyway).
+        HostnameVerifier verifier = HostnameVerifier.DEFAULT_AND_LOCALHOST;
+        defaultClient.setHostnameVerifier(verifier);
+        if (defaultServer != null) {
+            defaultServer.setHostnameVerifier(verifier);
+            // The RMI server will try to re-use Tomcat's "port 8443" SSL
+            // Certificate if possible.
+            defaultServer.useTomcatSSLMaterial();
+            X509Certificate[] x509 = defaultServer.getAssociatedCertificateChain();
+            if (x509 == null || x509.length < 1) {
+                throw new SSLException("Cannot initialize RMI-SSL Server: no KeyMaterial!");
+            }
+            setServer(defaultServer);
+        }
+        setDefaultClient(defaultClient);
+    }
+
+    public void setServer(ServerSocketFactory f)
+        throws GeneralSecurityException, IOException {
+        this.sslServer = f;
+        if (f instanceof SSLServer) {
+            final HostnameVerifier VERIFIER;
+            VERIFIER = HostnameVerifier.DEFAULT_AND_LOCALHOST;
+
+            final SSLServer ssl = (SSLServer) f;
+            final X509Certificate[] chain = ssl.getAssociatedCertificateChain();
+            String[] cns = Certificates.getCNs(chain[0]);
+            String[] subjectAlts = Certificates.getDNSSubjectAlts(chain[0]);
+            LinkedList names = new LinkedList();
+            if (cns != null && cns.length > 0) {
+                // Only first CN is used.  Not going to get into the IE6 nonsense
+                // where all CN values are used.
+                names.add(cns[0]);
+            }
+            if (subjectAlts != null && subjectAlts.length > 0) {
+                names.addAll(Arrays.asList(subjectAlts));
+            }
+
+            String rmiHostName = System.getProperty(RMI_HOSTNAME_KEY);
+            // If "java.rmi.server.hostname" is already set, don't mess with it.
+            // But blowup if it's not going to work with our SSL Server
+            // Certificate!
+            if (rmiHostName != null) {
+                try {
+                    VERIFIER.check(rmiHostName, cns, subjectAlts);
+                }
+                catch (SSLException ssle) {
+                    String s = ssle.toString();
+                    throw new SSLException(RMI_HOSTNAME_KEY + " of " + rmiHostName + " conflicts with SSL Server Certificate: " + s);
+                }
+            } else {
+                // If SSL Cert only contains one non-wild name, just use that and
+                // hope for the best.
+                boolean hopingForBest = false;
+                if (names.size() == 1) {
+                    String name = (String) names.get(0);
+                    if (!name.startsWith("*")) {
+                        System.setProperty(RMI_HOSTNAME_KEY, name);
+                        log.warn("commons-ssl '" + RMI_HOSTNAME_KEY + "' set to '" + name + "' as found in my SSL Server Certificate.");
+                        hopingForBest = true;
+                    }
+                }
+                if (!hopingForBest) {
+                    // Help me, Obi-Wan Kenobi; you're my only hope.  All we can
+                    // do now is grab our internet-facing addresses, reverse-lookup
+                    // on them, and hope that one of them validates against our
+                    // server cert.
+                    Set s = getMyInternetFacingIPs();
+                    Iterator it = s.iterator();
+                    while (it.hasNext()) {
+                        String name = (String) it.next();
+                        try {
+                            VERIFIER.check(name, cns, subjectAlts);
+                            System.setProperty(RMI_HOSTNAME_KEY, name);
+                            log.warn("commons-ssl '" + RMI_HOSTNAME_KEY + "' set to '" + name + "' as found by reverse-dns against my own IP.");
+                            hopingForBest = true;
+                            break;
+                        }
+                        catch (SSLException ssle) {
+                            // next!
+                        }
+                    }
+                }
+                if (!hopingForBest) {
+                    throw new SSLException("'" + RMI_HOSTNAME_KEY + "' not present.  Must work with my SSL Server Certificate's CN field: " + names);
+                }
+            }
+        }
+        trustOurself();
+    }
+
+    public void setLocalBindAddress(String localBindAddress) {
+        this.localBindAddress = localBindAddress;
+    }
+
+    public void setAnonymousPort(int port) {
+        this.anonymousPort = port;
+    }
+
+    public void setDefaultClient(SocketFactory f)
+        throws GeneralSecurityException, IOException {
+        this.defaultClient = f;
+        trustOurself();
+    }
+
+    public void setClient(String host, SocketFactory f)
+        throws GeneralSecurityException, IOException {
+        if (f != null && sslServer != null) {
+            boolean clientIsCommonsSSL = f instanceof SSLClient;
+            boolean serverIsCommonsSSL = sslServer instanceof SSLServer;
+            if (clientIsCommonsSSL && serverIsCommonsSSL) {
+                SSLClient c = (SSLClient) f;
+                SSLServer s = (SSLServer) sslServer;
+                trustEachOther(c, s);
+            }
+        }
+        Set names = hostnamePossibilities(host);
+        Iterator it = names.iterator();
+        synchronized (this) {
+            while (it.hasNext()) {
+                clientMap.put(it.next(), f);
+            }
+        }
+    }
+
+    public void removeClient(String host) {
+        Set names = hostnamePossibilities(host);
+        Iterator it = names.iterator();
+        synchronized (this) {
+            while (it.hasNext()) {
+                clientMap.remove(it.next());
+            }
+        }
+    }
+
+    public synchronized void removeClient(SocketFactory sf) {
+        Iterator it = clientMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Object o = entry.getValue();
+            if (sf.equals(o)) {
+                it.remove();
+            }
+        }
+    }
+
+    private Set hostnamePossibilities(String host) {
+        host = host != null ? host.toLowerCase().trim() : "";
+        if ("".equals(host)) {
+            return Collections.EMPTY_SET;
+        }
+        TreeSet names = new TreeSet();
+        names.add(host);
+        InetAddress[] addresses;
+        try {
+            // If they gave us "hostname.com", this will give us the various
+            // IP addresses:
+            addresses = InetAddress.getAllByName(host);
+            for (int i = 0; i < addresses.length; i++) {
+                String name1 = addresses[i].getHostName();
+                String name2 = addresses[i].getHostAddress();
+                names.add(name1.trim().toLowerCase());
+                names.add(name2.trim().toLowerCase());
+            }
+        }
+        catch (UnknownHostException uhe) {
+            /* oh well, nothing found, nothing to add for this client */
+        }
+
+        try {
+            host = InetAddress.getByName(host).getHostAddress();
+
+            // If they gave us "1.2.3.4", this will hopefully give us
+            // "hostname.com" so that we can then try and find any other
+            // IP addresses associated with that name.
+            host = InetAddress.getByName(host).getHostName();
+            names.add(host.trim().toLowerCase());
+            addresses = InetAddress.getAllByName(host);
+            for (int i = 0; i < addresses.length; i++) {
+                String name1 = addresses[i].getHostName();
+                String name2 = addresses[i].getHostAddress();
+                names.add(name1.trim().toLowerCase());
+                names.add(name2.trim().toLowerCase());
+            }
+        }
+        catch (UnknownHostException uhe) {
+            /* oh well, nothing found, nothing to add for this client */
+        }
+        return names;
+    }
+
+    private void trustOurself()
+        throws GeneralSecurityException, IOException {
+        if (defaultClient == null || sslServer == null) {
+            return;
+        }
+        boolean clientIsCommonsSSL = defaultClient instanceof SSLClient;
+        boolean serverIsCommonsSSL = sslServer instanceof SSLServer;
+        if (clientIsCommonsSSL && serverIsCommonsSSL) {
+            SSLClient c = (SSLClient) defaultClient;
+            SSLServer s = (SSLServer) sslServer;
+            trustEachOther(c, s);
+        }
+    }
+
+    private void trustEachOther(SSLClient client, SSLServer server)
+        throws GeneralSecurityException, IOException {
+        if (client != null && server != null) {
+            // Our own client should trust our own server.
+            X509Certificate[] certs = server.getAssociatedCertificateChain();
+            if (certs != null && certs[0] != null) {
+                TrustMaterial tm = new TrustMaterial(certs[0]);
+                client.addTrustMaterial(tm);
+            }
+
+            // Our own server should trust our own client.
+            certs = client.getAssociatedCertificateChain();
+            if (certs != null && certs[0] != null) {
+                TrustMaterial tm = new TrustMaterial(certs[0]);
+                server.addTrustMaterial(tm);
+            }
+        }
+    }
+
+    public ServerSocketFactory getServer() { return sslServer; }
+
+    public SocketFactory getDefaultClient() { return defaultClient; }
+
+    public synchronized SocketFactory getClient(String host) {
+        host = host != null ? host.trim().toLowerCase() : "";
+        return (SocketFactory) clientMap.get(host);
+    }
+
+    public synchronized ServerSocket createServerSocket(int port)
+        throws IOException {
+        // Re-use existing ServerSocket if possible.
+        if (port == 0) {
+            port = anonymousPort;
+        }
+        Integer key = new Integer(port);
+        ServerSocket ss = (ServerSocket) serverSockets.get(key);
+        if (ss == null || ss.isClosed()) {
+            if (ss != null && ss.isClosed()) {
+                System.out.println("found closed server on port: " + port);
+            }
+            log.debug("commons-ssl RMI server-socket: listening on port " + port);
+            ss = sslServer.createServerSocket(port);
+            serverSockets.put(key, ss);
+        }
+        return ss;
+    }
+
+    public Socket createSocket(String host, int port)
+        throws IOException {
+        host = host != null ? host.trim().toLowerCase() : "";
+        InetAddress local = null;
+        String bindAddress = localBindAddress;
+        if (bindAddress == null) {
+            bindAddress = System.getProperty(RMI_HOSTNAME_KEY);
+            if (bindAddress != null) {
+                local = InetAddress.getByName(bindAddress);
+                if (!local.isLoopbackAddress()) {
+                    String ip = local.getHostAddress();
+                    Set myInternetIps = getMyInternetFacingIPs();
+                    if (!myInternetIps.contains(ip)) {
+                        log.warn("Cannot bind to " + ip + " since it doesn't exist on this machine.");
+                        // Not going to be able to bind as this.  Our RMI_HOSTNAME_KEY
+                        // must be set to some kind of proxy in front of us.  So we
+                        // still want to use it, but we can't bind to it.
+                        local = null;
+                        bindAddress = null;
+                    }
+                }
+            }
+        }
+        if (bindAddress == null) {
+            // Our last resort - let's make sure we at least use something that's
+            // internet facing!
+            bindAddress = getMyDefaultIP();
+        }
+        if (local == null && bindAddress != null) {
+            local = InetAddress.getByName(bindAddress);
+            localBindAddress = local.getHostName();
+        }
+
+        SocketFactory sf;
+        synchronized (this) {
+            sf = (SocketFactory) clientMap.get(host);
+        }
+        if (sf == null) {
+            sf = defaultClient;
+        }
+
+        Socket s = null;
+        SSLSocket ssl = null;
+        int soTimeout = Integer.MIN_VALUE;
+        IOException reasonForPlainSocket = null;
+        boolean tryPlain = false;
+        try {
+            s = sf.createSocket(host, port, local, 0);
+            soTimeout = s.getSoTimeout();
+            if (!(s instanceof SSLSocket)) {
+                // Someone called setClient() or setDefaultClient() and passed in
+                // a plain socket factory.  Okay, nothing to see, move along.
+                return s;
+            } else {
+                ssl = (SSLSocket) s;
+            }
+
+            // If we don't get the peer certs in 15 seconds, revert to plain
+            // socket.
+            ssl.setSoTimeout(15000);
+            ssl.getSession().getPeerCertificates();
+
+            // Everything worked out okay, so go back to original soTimeout.
+            ssl.setSoTimeout(soTimeout);
+            return ssl;
+        }
+        catch (IOException ioe) {
+            // SSL didn't work.  Let's analyze the IOException to see if maybe
+            // we're accidentally attempting to talk to a plain-socket RMI
+            // server.
+            Throwable t = ioe;
+            while (!tryPlain && t != null) {
+                tryPlain = tryPlain || t instanceof EOFException;
+                tryPlain = tryPlain || t instanceof InterruptedIOException;
+                tryPlain = tryPlain || t instanceof SSLProtocolException;
+                t = t.getCause();
+            }
+            if (!tryPlain && ioe instanceof SSLPeerUnverifiedException) {
+                try {
+                    if (ssl != null) {
+                        ssl.startHandshake();
+                    }
+                }
+                catch (IOException ioe2) {
+                    // Stacktrace from startHandshake() will be more descriptive
+                    // then the one we got from getPeerCertificates().
+                    ioe = ioe2;
+                    t = ioe2;
+                    while (!tryPlain && t != null) {
+                        tryPlain = tryPlain || t instanceof EOFException;
+                        tryPlain = tryPlain || t instanceof InterruptedIOException;
+                        tryPlain = tryPlain || t instanceof SSLProtocolException;
+                        t = t.getCause();
+                    }
+                }
+            }
+            if (!tryPlain) {
+                log.debug("commons-ssl RMI-SSL failed: " + ioe);
+                throw ioe;
+            } else {
+                reasonForPlainSocket = ioe;
+            }
+        }
+        finally {
+            // Some debug logging:
+            boolean isPlain = tryPlain || (s != null && ssl == null);
+            String socket = isPlain ? "RMI plain-socket " : "RMI ssl-socket ";
+            String localIP = local != null ? local.getHostAddress() : "ANY";
+            StringBuffer buf = new StringBuffer(64);
+            buf.append(socket);
+            buf.append(localIP);
+            buf.append(" --> ");
+            buf.append(host);
+            buf.append(":");
+            buf.append(port);
+            log.debug(buf.toString());
+        }
+
+        // SSL didn't work.  Remote server either timed out, or sent EOF, or
+        // there was some kind of SSLProtocolException.  (Any other problem
+        // would have caused an IOException to be thrown, so execution wouldn't
+        // have made it this far).  Maybe plain socket will work in these three
+        // cases.
+        sf = plainClient;
+        s = JavaImpl.connect(null, sf, host, port, local, 0, 15000);
+        if (soTimeout != Integer.MIN_VALUE) {
+            s.setSoTimeout(soTimeout);
+        }
+
+        try {
+            // Plain socket worked!  Let's remember that for next time an RMI call
+            // against this host happens.
+            setClient(host, plainClient);
+            String msg = "RMI downgrading from SSL to plain-socket for " + host + " because of " + reasonForPlainSocket;
+            log.warn(msg, reasonForPlainSocket);
+        }
+        catch (GeneralSecurityException gse) {
+            throw new RuntimeException("can't happen because we're using plain socket", gse);
+            // won't happen because we're using plain socket, not SSL.
+        }
+
+        return s;
+    }
+
+
+    public static String getMyDefaultIP() {
+        String anInternetIP = "64.111.122.211";
+        String ip = null;
+        try {
+            DatagramSocket dg = new DatagramSocket();
+            dg.setSoTimeout(250);
+            // 64.111.122.211 is juliusdavies.ca.
+            // This code doesn't actually send any packets (so no firewalls can
+            // get in the way).  It's just a neat trick for getting our
+            // internet-facing interface card.
+            InetAddress addr = InetAddress.getByName(anInternetIP);
+            dg.connect(addr, 12345);
+            InetAddress localAddr = dg.getLocalAddress();
+            ip = localAddr.getHostAddress();
+            // log.debug( "Using bogus UDP socket (" + anInternetIP + ":12345), I think my IP address is: " + ip );
+            dg.close();
+            if (localAddr.isLoopbackAddress() || "0.0.0.0".equals(ip)) {
+                ip = null;
+            }
+        }
+        catch (IOException ioe) {
+            log.debug("Bogus UDP didn't work: " + ioe);
+        }
+        return ip;
+    }
+
+    public static SortedSet getMyInternetFacingIPs() throws SocketException {
+        TreeSet set = new TreeSet();
+        Enumeration en = NetworkInterface.getNetworkInterfaces();
+        while (en.hasMoreElements()) {
+            NetworkInterface ni = (NetworkInterface) en.nextElement();
+            Enumeration en2 = ni.getInetAddresses();
+            while (en2.hasMoreElements()) {
+                InetAddress addr = (InetAddress) en2.nextElement();
+                if (!addr.isLoopbackAddress()) {
+                    String ip = addr.getHostAddress();
+                    String reverse = addr.getHostName();
+                    // IP:
+                    set.add(ip);
+                    // Reverse-Lookup:
+                    set.add(reverse);
+
+                }
+            }
+        }
+        return set;
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSL.java b/src/java/org/apache/commons/ssl/SSL.java
new file mode 100644
index 0000000..f688694
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSL.java
@@ -0,0 +1,739 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSL.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Not thread-safe.  (But who would ever share this thing across multiple
+ * threads???)
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since May 1, 2006
+ */
+public class SSL {
+    private final static String[] KNOWN_PROTOCOLS =
+        {"TLSv1", "SSLv3", "SSLv2", "SSLv2Hello"};
+
+    // SUPPORTED_CIPHERS_ARRAY is initialized in the static constructor.
+    private final static String[] SUPPORTED_CIPHERS;
+
+    public final static SortedSet KNOWN_PROTOCOLS_SET;
+    public final static SortedSet SUPPORTED_CIPHERS_SET;
+
+    // RC4
+    public final static String SSL_RSA_WITH_RC4_128_SHA = "SSL_RSA_WITH_RC4_128_SHA";
+
+    // 3DES
+    public final static String SSL_RSA_WITH_3DES_EDE_CBC_SHA = "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
+    public final static String SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
+    public final static String SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
+
+    // AES-128
+    public final static String TLS_RSA_WITH_AES_128_CBC_SHA = "TLS_RSA_WITH_AES_128_CBC_SHA";
+    public final static String TLS_DHE_RSA_WITH_AES_128_CBC_SHA = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
+    public final static String TLS_DHE_DSS_WITH_AES_128_CBC_SHA = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
+
+    // AES-256
+    public final static String TLS_RSA_WITH_AES_256_CBC_SHA = "TLS_RSA_WITH_AES_256_CBC_SHA";
+    public final static String TLS_DHE_RSA_WITH_AES_256_CBC_SHA = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
+    public final static String TLS_DHE_DSS_WITH_AES_256_CBC_SHA = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
+
+    static {
+        TreeSet ts = new TreeSet(Collections.reverseOrder());
+        ts.addAll(Arrays.asList(KNOWN_PROTOCOLS));
+        KNOWN_PROTOCOLS_SET = Collections.unmodifiableSortedSet(ts);
+
+        // SSLSocketFactory.getDefault() sometimes blocks on FileInputStream
+        // reads of "/dev/random" (Linux only?).  You might find you system
+        // stuck here.  Move the mouse around a little!
+        SSLSocketFactory s = (SSLSocketFactory) SSLSocketFactory.getDefault();
+        ts = new TreeSet();
+        SUPPORTED_CIPHERS = s.getSupportedCipherSuites();
+        Arrays.sort(SUPPORTED_CIPHERS);
+        ts.addAll(Arrays.asList(SUPPORTED_CIPHERS));
+        SUPPORTED_CIPHERS_SET = Collections.unmodifiableSortedSet(ts);
+    }
+
+    private Object sslContext = null;
+    private int initCount = 0;
+    private SSLSocketFactory socketFactory = null;
+    private SSLServerSocketFactory serverSocketFactory = null;
+    private HostnameVerifier hostnameVerifier = HostnameVerifier.DEFAULT;
+    private boolean checkHostname = true;
+    private final ArrayList allowedNames = new ArrayList();
+    private boolean checkCRL = true;
+    private boolean checkExpiry = true;
+    private boolean useClientMode = false;
+    private boolean useClientModeDefault = true;
+    private int soTimeout = 24 * 60 * 60 * 1000; // default: one day
+    private int connectTimeout = 60 * 60 * 1000; // default: one hour
+    private TrustChain trustChain = null;
+    private KeyMaterial keyMaterial = null;
+    private String[] enabledCiphers = null;
+    private String[] enabledProtocols = null;
+    private String defaultProtocol = "TLS";
+    private X509Certificate[] currentServerChain;
+    private X509Certificate[] currentClientChain;
+    private boolean wantClientAuth = true;
+    private boolean needClientAuth = false;
+    private SSLWrapperFactory sslWrapperFactory = SSLWrapperFactory.NO_WRAP;
+
+    protected final boolean usingSystemProperties;
+
+    public SSL()
+        throws GeneralSecurityException, IOException {
+        boolean usingSysProps = false;
+        Properties props = System.getProperties();
+        boolean ksSet = props.containsKey("javax.net.ssl.keyStore");
+        boolean tsSet = props.containsKey("javax.net.ssl.trustStore");
+        if (ksSet) {
+            String path = System.getProperty("javax.net.ssl.keyStore");
+            String pwd = System.getProperty("javax.net.ssl.keyStorePassword");
+            pwd = pwd != null ? pwd : ""; // JSSE default is "".
+            File f = new File(path);
+            if (f.exists()) {
+                KeyMaterial km = new KeyMaterial(path, pwd.toCharArray());
+                setKeyMaterial(km);
+                usingSysProps = true;
+            }
+        }
+        boolean trustMaterialSet = false;
+        if (tsSet) {
+            String path = System.getProperty("javax.net.ssl.trustStore");
+            String pwd = System.getProperty("javax.net.ssl.trustStorePassword");
+            boolean pwdWasNull = pwd == null;
+            pwd = pwdWasNull ? "" : pwd; // JSSE default is "".
+            File f = new File(path);
+            if (f.exists()) {
+                TrustMaterial tm;
+                try {
+                    tm = new TrustMaterial(path, pwd.toCharArray());
+                }
+                catch (GeneralSecurityException gse) {
+                    // Probably a bad password.  If we're using the default password,
+                    // let's try and survive this setback.
+                    if (pwdWasNull) {
+                        tm = new TrustMaterial(path);
+                    } else {
+                        throw gse;
+                    }
+                }
+
+                setTrustMaterial(tm);
+                usingSysProps = true;
+                trustMaterialSet = true;
+            }
+        }
+
+        /*
+            No default trust material was set.  We'll use the JSSE standard way
+            where we test for "JSSE_CACERTS" first, and then fall back on
+            "CACERTS".  We could just leave TrustMaterial null, but then our
+            setCheckCRL() and setCheckExpiry() features won't work.  We need a
+            non-null TrustMaterial object in order to intercept and decorate
+            the JVM's default TrustManager.
+          */
+        if (!trustMaterialSet) {
+            setTrustMaterial(TrustMaterial.DEFAULT);
+        }
+        this.usingSystemProperties = usingSysProps;
+
+        // By default we only use the strong ciphers (128 bit and higher).
+        // Consumers can call "useDefaultJavaCiphers()" to get the 40 and 56 bit
+        // ciphers back that Java normally has turned on.
+        useStrongCiphers();
+        dirtyAndReloadIfYoung();
+    }
+
+    private void dirty() {
+        this.sslContext = null;
+        this.socketFactory = null;
+        this.serverSocketFactory = null;
+    }
+
+    private void dirtyAndReloadIfYoung()
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        dirty();
+        if (initCount >= 0 && initCount <= 5) {
+            // The first five init's we do early (before any sockets are
+            // created) in the hope that will trigger any explosions nice
+            // and early, with the correct exception type.
+
+            // After the first five init's, we revert to a regular
+            // dirty / init pattern, and the "init" happens very late:
+            // just before the socket is created.  If badness happens, a
+            // wrapping RuntimeException will be thrown.
+            init();
+        }
+    }
+
+    public SSLContext getSSLContext()
+        throws GeneralSecurityException, IOException
+
+    {
+        Object obj = getSSLContextAsObject();
+        if (JavaImpl.isJava13()) {
+            try {
+                return (SSLContext) obj;
+            }
+            catch (ClassCastException cce) {
+                throw new ClassCastException("When using Java13 SSL, you must call SSL.getSSLContextAsObject() - " + cce);
+            }
+        }
+        return (SSLContext) obj;
+    }
+
+    /**
+     * @return com.sun.net.ssl.SSLContext or javax.net.ssl.SSLContext depending
+     *         on the JSSE implementation we're using.
+     * @throws GeneralSecurityException problem creating SSLContext
+     * @throws IOException              problem creating SSLContext
+     */
+    public Object getSSLContextAsObject()
+        throws GeneralSecurityException, IOException
+
+    {
+        if (sslContext == null) {
+            init();
+        }
+        return sslContext;
+    }
+
+    public void addTrustMaterial(TrustChain trustChain)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        if (this.trustChain == null || trustChain == TrustMaterial.TRUST_ALL) {
+            this.trustChain = trustChain;
+        } else {
+            this.trustChain.addTrustMaterial(trustChain);
+        }
+        dirtyAndReloadIfYoung();
+    }
+
+    public void setTrustMaterial(TrustChain trustChain)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        this.trustChain = trustChain;
+        dirtyAndReloadIfYoung();
+    }
+
+    public void setKeyMaterial(KeyMaterial keyMaterial)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        this.keyMaterial = keyMaterial;
+        dirtyAndReloadIfYoung();
+    }
+
+    public X509Certificate[] getAssociatedCertificateChain() {
+        if (keyMaterial != null) {
+            return keyMaterial.getAssociatedCertificateChain();
+        } else {
+            return null;
+        }
+    }
+
+    public String[] getEnabledCiphers() {
+        return enabledCiphers != null ? enabledCiphers : getDefaultCipherSuites();
+    }
+
+    public void useDefaultJavaCiphers() {
+        this.enabledCiphers = null;
+    }
+
+    public void useStrongCiphers() {
+        LinkedList list = new LinkedList();
+        addCipher(list, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, false);
+        addCipher(list, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, false);
+        addCipher(list, SSL_RSA_WITH_3DES_EDE_CBC_SHA, false);
+        addCipher(list, SSL_RSA_WITH_RC4_128_SHA, false);
+        addCipher(list, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, false);
+        addCipher(list, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, false);
+        addCipher(list, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, false);
+        addCipher(list, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, false);
+        addCipher(list, TLS_RSA_WITH_AES_128_CBC_SHA, false);
+        addCipher(list, TLS_RSA_WITH_AES_256_CBC_SHA, false);
+        String[] strongCiphers = new String[list.size()];
+        list.toArray(strongCiphers);
+        String[] currentCiphers = getEnabledCiphers();
+        // Current ciphers must be default or something.  Odd that it's null,
+        // though.
+        if (currentCiphers == null) {
+            setEnabledCiphers(strongCiphers);
+        }
+
+        Arrays.sort(strongCiphers);
+        Arrays.sort(currentCiphers);
+        // Let's only call "setEnabledCiphers" if our array is actually different
+        // than what's already set.
+        if (!Arrays.equals(strongCiphers, currentCiphers)) {
+            setEnabledCiphers(strongCiphers);
+        }
+    }
+
+    public void setEnabledCiphers(String[] ciphers) {
+        HashSet desired = new HashSet(Arrays.asList(ciphers));
+        desired.removeAll(SUPPORTED_CIPHERS_SET);
+        if (!desired.isEmpty()) {
+            throw new IllegalArgumentException("following ciphers not supported: " + desired);
+        }
+        this.enabledCiphers = ciphers;
+    }
+
+    public String[] getEnabledProtocols() {
+        return enabledProtocols != null ? enabledProtocols : KNOWN_PROTOCOLS;
+    }
+
+    public void setEnabledProtocols(String[] protocols) {
+        HashSet desired = new HashSet(Arrays.asList(protocols));
+        desired.removeAll(KNOWN_PROTOCOLS_SET);
+        if (!desired.isEmpty()) {
+            throw new IllegalArgumentException("following protocols not supported: " + desired);
+        }
+        this.enabledProtocols = protocols;
+    }
+
+    public String getDefaultProtocol() {
+        return defaultProtocol;
+    }
+
+    public void setDefaultProtocol(String protocol) {
+        this.defaultProtocol = protocol;
+        dirty();
+    }
+
+    public boolean getCheckHostname() {
+        return checkHostname;
+    }
+
+    /**
+     * @return String[] array of alternate "allowed names" to try against a
+     *         server's x509 CN field if the host/ip we used didn't match.
+     *         Returns an empty list if there are no "allowedNames" currently
+     *         set.
+     */
+    public List getAllowedNames() {
+        return Collections.unmodifiableList(allowedNames);
+    }
+
+    /**
+     * Offers a secure way to use virtual-hosting and SSL in some situations:
+     * for example you want to connect to "bar.com" but you know in advance
+     * that the SSL Certificate on that server only contains "CN=foo.com".  If
+     * you setAllowedNames( new String[] { "foo.com" } ) on your SSLClient in
+     * advance, you can connect securely, while still using "bar.com" as the
+     * host.
+     * <p/>
+     * Here's a code example using "cucbc.com" to connect, but anticipating
+     * "www.cucbc.com" in the server's certificate:
+     * <pre>
+     * SSLClient client = new SSLClient();
+     * client.setAllowedNames( new String[] { "www.cucbc.com" } );
+     * Socket s = client.createSocket( "cucbc.com", 443 );
+     * </pre>
+     * <p/>
+     * This technique is also useful if you don't want to use DNS, and want to
+     * connect using the IP address.
+     *
+     * @param allowedNames Collection of alternate "allowed names" to try against
+     *                     a server's x509 CN field if the host/ip we used didn't
+     *                     match.  Set to null to force strict matching against
+     *                     host/ip passed into createSocket().  Null is the
+     *                     default value.  Must be set in advance, before
+     *                     createSocket() is called.
+     */
+    public void addAllowedNames(Collection allowedNames) {
+        this.allowedNames.addAll(allowedNames);
+    }
+
+    public void addAllowedName(String allowedName) {
+        this.allowedNames.add(allowedName);
+    }
+
+    public void clearAllowedNames() {
+        this.allowedNames.clear();
+    }
+
+    public void setCheckHostname(boolean checkHostname) {
+        this.checkHostname = checkHostname;
+    }
+
+    public void setHostnameVerifier(HostnameVerifier verifier) {
+        if (verifier == null) {
+            verifier = HostnameVerifier.DEFAULT;
+        }
+        this.hostnameVerifier = verifier;
+    }
+
+    public HostnameVerifier getHostnameVerifier() {
+        return hostnameVerifier;
+    }
+
+    public boolean getCheckCRL() {
+        return checkCRL;
+    }
+
+    public void setCheckCRL(boolean checkCRL) {
+        this.checkCRL = checkCRL;
+    }
+
+    public boolean getCheckExpiry() {
+        return checkExpiry;
+    }
+
+    public void setCheckExpiry(boolean checkExpiry) {
+        this.checkExpiry = checkExpiry;
+    }
+
+    public void setSoTimeout(int soTimeout) {
+        if (soTimeout < 0) {
+            throw new IllegalArgumentException("soTimeout must not be negative");
+        }
+        this.soTimeout = soTimeout;
+    }
+
+    public int getSoTimeout() {
+        return soTimeout;
+    }
+
+    public void setConnectTimeout(int connectTimeout) {
+        if (connectTimeout < 0) {
+            throw new IllegalArgumentException("connectTimeout must not be negative");
+        }
+        this.connectTimeout = connectTimeout;
+    }
+
+    public void setUseClientMode(boolean useClientMode) {
+        this.useClientModeDefault = false;
+        this.useClientMode = useClientMode;
+    }
+
+    public boolean getUseClientModeDefault() {
+        return useClientModeDefault;
+    }
+
+    public boolean getUseClientMode() {
+        return useClientMode;
+    }
+
+    public void setWantClientAuth(boolean wantClientAuth) {
+        this.wantClientAuth = wantClientAuth;
+    }
+
+    public void setNeedClientAuth(boolean needClientAuth) {
+        this.needClientAuth = needClientAuth;
+    }
+
+    public boolean getWantClientAuth() {
+        return wantClientAuth;
+    }
+
+    public boolean getNeedClientAuth() {
+        return needClientAuth;
+    }
+
+    public SSLWrapperFactory getSSLWrapperFactory() {
+        return this.sslWrapperFactory;
+    }
+
+    public void setSSLWrapperFactory(SSLWrapperFactory wf) {
+        this.sslWrapperFactory = wf;
+    }
+
+    private void initThrowRuntime() {
+        try {
+            init();
+        }
+        catch (GeneralSecurityException gse) {
+            throw JavaImpl.newRuntimeException(gse);
+        }
+        catch (IOException ioe) {
+            throw JavaImpl.newRuntimeException(ioe);
+        }
+    }
+
+    private void init()
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        socketFactory = null;
+        serverSocketFactory = null;
+        this.sslContext = JavaImpl.init(this, trustChain, keyMaterial);
+        initCount++;
+    }
+
+    public void doPreConnectSocketStuff(SSLSocket s)
+        throws IOException {
+        if (!useClientModeDefault) {
+            s.setUseClientMode(useClientMode);
+        }
+        if (soTimeout > 0) {
+            s.setSoTimeout(soTimeout);
+        }
+        if (enabledProtocols != null) {
+            JavaImpl.setEnabledProtocols(s, enabledProtocols);
+        }
+        if (enabledCiphers != null) {
+            s.setEnabledCipherSuites(enabledCiphers);
+        }
+    }
+
+    public void doPostConnectSocketStuff(SSLSocket s, String host)
+        throws IOException {
+        if (checkHostname) {
+            int size = allowedNames.size() + 1;
+            String[] hosts = new String[size];
+            // hosts[ 0 ] MUST ALWAYS be the host given to createSocket().
+            hosts[0] = host;
+            int i = 1;
+            for (Iterator it = allowedNames.iterator(); it.hasNext(); i++) {
+                hosts[i] = (String) it.next();
+            }
+            hostnameVerifier.check(hosts, s);
+        }
+    }
+
+    public SSLSocket createSocket() throws IOException {
+        return sslWrapperFactory.wrap(JavaImpl.createSocket(this));
+    }
+
+    /**
+     * Attempts to get a new socket connection to the given host within the
+     * given time limit.
+     *
+     * @param remoteHost the host name/IP
+     * @param remotePort the port on the host
+     * @param localHost  the local host name/IP to bind the socket to
+     * @param localPort  the port on the local machine
+     * @param timeout    the connection timeout (0==infinite)
+     * @return Socket a new socket
+     * @throws IOException          if an I/O error occurs while creating the socket
+     * @throws UnknownHostException if the IP address of the host cannot be
+     *                              determined
+     */
+    public Socket createSocket(String remoteHost, int remotePort,
+                               InetAddress localHost, int localPort,
+                               int timeout)
+        throws IOException {
+        // Only use our factory-wide connectTimeout if this method was passed
+        // in a timeout of 0 (infinite).
+        int factoryTimeout = getConnectTimeout();
+        int connectTimeout = timeout == 0 ? factoryTimeout : timeout;
+        SSLSocket s = JavaImpl.createSocket(this, remoteHost, remotePort,
+            localHost, localPort,
+            connectTimeout);
+        return sslWrapperFactory.wrap(s);
+    }
+
+    public Socket createSocket(Socket s, String remoteHost, int remotePort,
+                               boolean autoClose)
+        throws IOException {
+        SSLSocketFactory sf = getSSLSocketFactory();
+        s = sf.createSocket(s, remoteHost, remotePort, autoClose);
+        doPreConnectSocketStuff((SSLSocket) s);
+        doPostConnectSocketStuff((SSLSocket) s, remoteHost);
+        return sslWrapperFactory.wrap((SSLSocket) s);
+    }
+
+    public ServerSocket createServerSocket() throws IOException {
+        SSLServerSocket ss = JavaImpl.createServerSocket(this);
+        return getSSLWrapperFactory().wrap(ss, this);
+    }
+
+    /**
+     * Attempts to get a new socket connection to the given host within the
+     * given time limit.
+     *
+     * @param localHost the local host name/IP to bind against (null == ANY)
+     * @param port      the port to listen on
+     * @param backlog   number of connections allowed to queue up for accept().
+     * @return SSLServerSocket a new server socket
+     * @throws IOException if an I/O error occurs while creating thesocket
+     */
+    public ServerSocket createServerSocket(int port, int backlog,
+                                           InetAddress localHost)
+        throws IOException {
+        SSLServerSocketFactory f = getSSLServerSocketFactory();
+        ServerSocket ss = f.createServerSocket(port, backlog, localHost);
+        SSLServerSocket s = (SSLServerSocket) ss;
+        doPreConnectServerSocketStuff(s);
+        return getSSLWrapperFactory().wrap(s, this);
+    }
+
+    public void doPreConnectServerSocketStuff(SSLServerSocket s)
+        throws IOException {
+        if (soTimeout > 0) {
+            s.setSoTimeout(soTimeout);
+        }
+        if (enabledProtocols != null) {
+            JavaImpl.setEnabledProtocols(s, enabledProtocols);
+        }
+        if (enabledCiphers != null) {
+            s.setEnabledCipherSuites(enabledCiphers);
+        }
+
+        /*
+          setNeedClientAuth( false ) has an annoying side effect:  it seems to
+          reset setWantClient( true ) back to to false.  So I do things this
+          way to make sure setting things "true" happens after setting things
+          "false" - giving "true" priority.
+          */
+        if (!wantClientAuth) {
+            JavaImpl.setWantClientAuth(s, wantClientAuth);
+        }
+        if (!needClientAuth) {
+            s.setNeedClientAuth(needClientAuth);
+        }
+        if (wantClientAuth) {
+            JavaImpl.setWantClientAuth(s, wantClientAuth);
+        }
+        if (needClientAuth) {
+            s.setNeedClientAuth(needClientAuth);
+        }
+    }
+
+    public SSLSocketFactory getSSLSocketFactory() {
+        if (sslContext == null) {
+            initThrowRuntime();
+        }
+        if (socketFactory == null) {
+            socketFactory = JavaImpl.getSSLSocketFactory(sslContext);
+        }
+        return socketFactory;
+    }
+
+    public SSLServerSocketFactory getSSLServerSocketFactory() {
+        if (sslContext == null) {
+            initThrowRuntime();
+        }
+        if (serverSocketFactory == null) {
+            serverSocketFactory = JavaImpl.getSSLServerSocketFactory(sslContext);
+        }
+        return serverSocketFactory;
+    }
+
+    public int getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    public String[] getDefaultCipherSuites() {
+        return getSSLSocketFactory().getDefaultCipherSuites();
+    }
+
+    public String[] getSupportedCipherSuites() {
+        String[] s = new String[SUPPORTED_CIPHERS.length];
+        System.arraycopy(SUPPORTED_CIPHERS, 0, s, 0, s.length);
+        return s;
+    }
+
+    public TrustChain getTrustChain() {
+        return trustChain;
+    }
+
+    public void setCurrentServerChain(X509Certificate[] chain) {
+        this.currentServerChain = chain;
+    }
+
+    public void setCurrentClientChain(X509Certificate[] chain) {
+        this.currentClientChain = chain;
+    }
+
+    public X509Certificate[] getCurrentServerChain() {
+        return currentServerChain;
+    }
+
+    public X509Certificate[] getCurrentClientChain() {
+        return currentClientChain;
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < SUPPORTED_CIPHERS.length; i++) {
+            System.out.println(SUPPORTED_CIPHERS[i]);
+        }
+        System.out.println();
+        System.out.println("----------------------------------------------");
+        addCipher(null, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, true);
+        addCipher(null, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, true);
+        addCipher(null, SSL_RSA_WITH_3DES_EDE_CBC_SHA, true);
+        addCipher(null, SSL_RSA_WITH_RC4_128_SHA, true);
+        addCipher(null, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, true);
+        addCipher(null, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, true);
+        addCipher(null, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true);
+        addCipher(null, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, true);
+        addCipher(null, TLS_RSA_WITH_AES_128_CBC_SHA, true);
+        addCipher(null, TLS_RSA_WITH_AES_256_CBC_SHA, true);
+    }
+
+    private static void addCipher(List l, String c, boolean printOnStandardOut) {
+        boolean supported = false;
+        if (c != null && SUPPORTED_CIPHERS_SET.contains(c)) {
+            if (l != null) {
+                l.add(c);
+            }
+            supported = true;
+        }
+        if (printOnStandardOut) {
+            System.out.println(c + ":\t" + supported);
+        }
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLClient.java b/src/java/org/apache/commons/ssl/SSLClient.java
new file mode 100644
index 0000000..626c0b1
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLClient.java
@@ -0,0 +1,233 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLClient.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 27-Feb-2006
+ */
+public class SSLClient extends SSLSocketFactory {
+    private final SSL ssl;
+
+    public SSLClient()
+        throws GeneralSecurityException, IOException {
+        this.ssl = new SSL();
+    }
+
+    public void addTrustMaterial(TrustChain trustChain)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        ssl.addTrustMaterial(trustChain);
+    }
+
+    public void setTrustMaterial(TrustChain trustChain)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        ssl.setTrustMaterial(trustChain);
+    }
+
+    public void setKeyMaterial(KeyMaterial keyMaterial)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        ssl.setKeyMaterial(keyMaterial);
+    }
+
+    public void addAllowedName(String s) { ssl.addAllowedName(s); }
+
+    public void addAllowedNames(Collection c) { ssl.addAllowedNames(c); }
+
+    public void clearAllowedNames() { ssl.clearAllowedNames(); }
+
+    public void setCheckCRL(boolean b) { ssl.setCheckCRL(b); }
+
+    public void setCheckExpiry(boolean b) { ssl.setCheckExpiry(b); }
+
+    public void setCheckHostname(boolean b) { ssl.setCheckHostname(b); }
+
+    public void setConnectTimeout(int i) { ssl.setConnectTimeout(i); }
+
+    public void setDefaultProtocol(String s) { ssl.setDefaultProtocol(s); }
+
+    public void useDefaultJavaCiphers() { ssl.useDefaultJavaCiphers(); }
+
+    public void useStrongCiphers() { ssl.useStrongCiphers(); }
+
+    public void setEnabledCiphers(String[] ciphers) {
+        ssl.setEnabledCiphers(ciphers);
+    }
+
+    public void setEnabledProtocols(String[] protocols) {
+        ssl.setEnabledProtocols(protocols);
+    }
+
+    public void setHostnameVerifier(HostnameVerifier verifier) {
+        ssl.setHostnameVerifier(verifier);
+    }
+
+    public void setSoTimeout(int soTimeout) { ssl.setSoTimeout(soTimeout); }
+
+    public void setSSLWrapperFactory(SSLWrapperFactory wf) {
+        ssl.setSSLWrapperFactory(wf);
+    }
+
+    public void setNeedClientAuth(boolean b) { ssl.setNeedClientAuth(b); }
+
+    public void setWantClientAuth(boolean b) { ssl.setWantClientAuth(b); }
+
+    public void setUseClientMode(boolean b) { ssl.setUseClientMode(b); }
+
+    public List getAllowedNames() { return ssl.getAllowedNames(); }
+
+    public X509Certificate[] getAssociatedCertificateChain() {
+        return ssl.getAssociatedCertificateChain();
+    }
+
+    public boolean getCheckCRL() { return ssl.getCheckCRL(); }
+
+    public boolean getCheckExpiry() { return ssl.getCheckExpiry(); }
+
+    public boolean getCheckHostname() { return ssl.getCheckHostname(); }
+
+    public int getConnectTimeout() { return ssl.getConnectTimeout(); }
+
+    public String getDefaultProtocol() { return ssl.getDefaultProtocol(); }
+
+    public String[] getEnabledCiphers() { return ssl.getEnabledCiphers(); }
+
+    public String[] getEnabledProtocols() { return ssl.getEnabledProtocols(); }
+
+    public HostnameVerifier getHostnameVerifier() {
+        return ssl.getHostnameVerifier();
+    }
+
+    public int getSoTimeout() { return ssl.getSoTimeout(); }
+
+    public SSLWrapperFactory getSSLWrapperFactory() {
+        return ssl.getSSLWrapperFactory();
+    }
+
+    public boolean getNeedClientAuth() { return ssl.getNeedClientAuth(); }
+
+    public boolean getWantClientAuth() { return ssl.getWantClientAuth(); }
+
+    public boolean getUseClientMode() { /* SSLClient's default is true. */
+        return ssl.getUseClientModeDefault() || ssl.getUseClientMode();
+    }
+
+    public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
+        return ssl.getSSLContext();
+    }
+
+    public TrustChain getTrustChain() { return ssl.getTrustChain(); }
+
+    public X509Certificate[] getCurrentServerChain() {
+        return ssl.getCurrentServerChain();
+    }
+
+    public String[] getDefaultCipherSuites() {
+        return ssl.getDefaultCipherSuites();
+    }
+
+    public String[] getSupportedCipherSuites() {
+        return ssl.getSupportedCipherSuites();
+    }
+
+    public Socket createSocket() throws IOException {
+        return ssl.createSocket();
+    }
+
+    public Socket createSocket(String host, int port)
+        throws IOException {
+        return createSocket(host, port, null, 0);
+    }
+
+    public Socket createSocket(InetAddress host, int port)
+        throws IOException {
+        return createSocket(host.getHostName(), port);
+    }
+
+    public Socket createSocket(InetAddress host, int port,
+                               InetAddress localHost, int localPort)
+        throws IOException {
+        return createSocket(host.getHostName(), port, localHost, localPort);
+    }
+
+    public Socket createSocket(String host, int port,
+                               InetAddress localHost, int localPort)
+        throws IOException {
+        return createSocket(host, port, localHost, localPort, 0);
+    }
+
+    /**
+     * Attempts to get a new socket connection to the given host within the
+     * given time limit.
+     *
+     * @param host      the host name/IP
+     * @param port      the port on the host
+     * @param localHost the local host name/IP to bind the socket to
+     * @param localPort the port on the local machine
+     * @param timeout   the connection timeout (0==infinite)
+     * @return Socket a new socket
+     * @throws IOException          if an I/O error occurs while creating thesocket
+     * @throws UnknownHostException if the IP address of the host cannot be
+     *                              determined
+     */
+    public Socket createSocket(String host, int port, InetAddress localHost,
+                               int localPort, int timeout)
+        throws IOException {
+        return ssl.createSocket(host, port, localHost, localPort, timeout);
+    }
+
+    public Socket createSocket(Socket s, String remoteHost, int remotePort,
+                               boolean autoClose)
+        throws IOException {
+        return ssl.createSocket(s, remoteHost, remotePort, autoClose);
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLEchoServer.java b/src/java/org/apache/commons/ssl/SSLEchoServer.java
new file mode 100644
index 0000000..632606e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLEchoServer.java
@@ -0,0 +1,142 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLEchoServer.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 2-May-2006
+ */
+public class SSLEchoServer {
+
+    public static void main(String[] args) throws Exception {
+        int port = 7443;
+        if (args.length >= 1) {
+            port = Integer.parseInt(args[0]);
+        }
+
+        SSLServer ssl = new SSLServer();
+        // ssl.setCheckExpiry( false );
+        // ssl.setNeedClientAuth( true );
+        ssl.addTrustMaterial(TrustMaterial.TRUST_ALL);
+        SSLServerSocket ss = (SSLServerSocket) ssl.createServerSocket(port, 3);
+        System.out.println("SSL Echo server listening on port: " + port);
+        while (true) {
+            SSLSocket s = (SSLSocket) ss.accept();
+            s.setSoTimeout(30000);
+            EchoRunnable r = new EchoRunnable(s);
+            new Thread(r).start();
+        }
+
+    }
+
+    public static class EchoRunnable implements Runnable {
+        private SSLSocket s;
+
+        public EchoRunnable(SSLSocket s) {
+            this.s = s;
+        }
+
+        public void run() {
+            InputStream in = null;
+            OutputStream out = null;
+            System.out.println("Socket accepted!");
+            try {
+                SSLSession session = s.getSession();
+
+                try {
+                    Certificate[] certs = JavaImpl.getPeerCertificates(session);
+                    if (certs != null) {
+                        for (int i = 0; i < certs.length; i++) {
+                            // log client cert info
+                            X509Certificate cert = (X509Certificate) certs[i];
+                            String s = "client cert " + i + ":";
+                            s += JavaImpl.getSubjectX500(cert);
+                            System.out.println(s);
+                            System.out.println(Certificates.toString(cert));
+                        }
+                    }
+                }
+                catch (SSLPeerUnverifiedException sslpue) {
+                    // oh well, no client cert for us
+                }
+
+                in = s.getInputStream();
+                out = s.getOutputStream();
+                String line = Util.readLine(in);
+                if (line != null && line.indexOf("HTTP") > 0) {
+                    out.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());
+                    out.flush();
+                }
+                while (line != null) {
+                    String echo = "ECHO:>" + line + "\n";
+                    out.write(echo.getBytes());
+                    out.flush();
+                    line = Util.readLine(in);
+                }
+            }
+            catch (IOException ioe) {
+                try {
+                    if (out != null) {
+                        out.close();
+                    }
+                    if (in != null) {
+                        in.close();
+                    }
+                    s.close();
+                }
+                catch (Exception e) {
+                }
+
+                if (ioe instanceof InterruptedIOException) {
+                    System.out.println("Socket closed after 30 second timeout.");
+                } else {
+                    ioe.printStackTrace();
+                }
+
+            }
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLProxyServer.java b/src/java/org/apache/commons/ssl/SSLProxyServer.java
new file mode 100644
index 0000000..ed3d62d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLProxyServer.java
@@ -0,0 +1,193 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLProxyServer.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 5-May-2006
+ */
+public class SSLProxyServer {
+
+    public static void main(String[] args) throws Exception {
+        int port = 7444;
+        if (args.length >= 1) {
+            port = Integer.parseInt(args[0]);
+        }
+
+        ServerSocket ss = new ServerSocket(port);
+
+        System.out.println("SSL Proxy server listening on port: " + port);
+        while (true) {
+            Socket s = ss.accept();
+            s.setSoTimeout(10000);
+            ProxyRunnable r = new ProxyRunnable(s);
+            new Thread(r).start();
+        }
+
+    }
+
+    public static class ProxyRunnable implements Runnable {
+        private Socket s;
+
+        public ProxyRunnable(Socket s) {
+            this.s = s;
+        }
+
+        public void run() {
+            InputStream in = null;
+            OutputStream out = null;
+            InputStream newIn = null;
+            OutputStream newOut = null;
+            Socket newSocket = new Socket();
+            System.out.println("Socket accepted!");
+            try {
+                in = s.getInputStream();
+                out = s.getOutputStream();
+                String line = Util.readLine(in);
+                line = line.trim();
+                String connect = line.substring(0, "CONNECT".length());
+                InetSocketAddress addr = null;
+                if ("CONNECT".equalsIgnoreCase(connect)) {
+                    line = line.substring("CONNECT".length()).trim();
+                    line = line.substring(0, line.length() - "HTTP/1.1".length()).trim();
+                    HostPort hostPort = Util.toAddress(line, 443);
+                    addr = new InetSocketAddress(hostPort.host, hostPort.port);
+                    System.out.println("Attempting to proxy to: " + line);
+                } else {
+                    throw new IOException("not a proxy request: " + line);
+                }
+
+                int avail = in.available();
+                in.skip(avail);
+                Thread.yield();
+                avail = in.available();
+                while (avail != 0) {
+                    in.skip(avail);
+                    Thread.yield();
+                    avail = in.available();
+                }
+
+                InetSocketAddress local = new InetSocketAddress(0);
+                newSocket.setSoTimeout(10000);
+                newSocket.bind(local);
+                newSocket.connect(addr, 5000);
+                newIn = newSocket.getInputStream();
+                newOut = newSocket.getOutputStream();
+
+                out.write("HTTP/1.1 200 OKAY\r\n\r\n".getBytes());
+                out.flush();
+
+                final IOException[] e = new IOException[1];
+                final InputStream rIn = in;
+                final OutputStream rNewOut = newOut;
+                Runnable r = new Runnable() {
+                    public void run() {
+                        try {
+                            byte[] buf = new byte[4096];
+                            int read = rIn.read(buf);
+                            while (read >= 0) {
+                                if (read > 0) {
+                                    rNewOut.write(buf, 0, read);
+                                    rNewOut.flush();
+                                }
+                                read = rIn.read(buf);
+                            }
+                        }
+                        catch (IOException ioe) {
+                            e[0] = ioe;
+                        }
+                    }
+                };
+                new Thread(r).start();
+
+                byte[] buf = new byte[4096];
+                int read = newIn.read(buf);
+                while (read >= 0) {
+                    if (read > 0) {
+                        out.write(buf, 0, read);
+                        out.flush();
+                    }
+                    if (e[0] != null) {
+                        throw e[0];
+                    }
+                    read = newIn.read(buf);
+                }
+
+
+            }
+            catch (IOException ioe) {
+                try {
+                    if (out != null) {
+                        out.close();
+                    }
+                    if (in != null) {
+                        in.close();
+                    }
+                    s.close();
+                }
+                catch (Exception e) {
+                }
+
+                try {
+                    if (newOut != null) {
+                        newOut.close();
+                    }
+                    if (newIn != null) {
+                        newIn.close();
+                    }
+                    newSocket.close();
+                }
+                catch (Exception e) {
+                }
+
+
+                if (ioe instanceof InterruptedIOException) {
+                    System.out.println("Socket closed after 10 second timeout.");
+                } else {
+                    ioe.printStackTrace();
+                }
+
+            }
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLServer.java b/src/java/org/apache/commons/ssl/SSLServer.java
new file mode 100644
index 0000000..d110b8e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLServer.java
@@ -0,0 +1,295 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLServer.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocketFactory;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since May 1, 2006
+ */
+public class SSLServer extends SSLServerSocketFactory {
+    protected final SSL ssl;
+
+    public SSLServer()
+        throws GeneralSecurityException, IOException {
+        this.ssl = new SSL();
+        // client certs aren't usually tied down to a single host (and who knows
+        // if the DNS reverse-lookup will work!).
+        setCheckHostname(false);
+
+        // If "javax.net.ssl.keyStore" is set, then we won't bother with this
+        // silly SSLServer default behaviour.
+        if (!ssl.usingSystemProperties) {
+            // commons-ssl default KeyMaterial will be
+            //  ~/.keystore with a password of "changeit".
+            useDefaultKeyMaterial();
+        }
+    }
+
+    /**
+     * Tries to extract the TrustMaterial and KeyMaterial being used by a Tomcat
+     * SSL server (usually on 8443) by analyzing Tomcat's "server.xml" file.  If
+     * the extraction is successful, the TrustMaterial and KeyMaterial are
+     * applied to this SSLServer.
+     *
+     * @return true if the operation was successful.
+     * @throws GeneralSecurityException setKeyMaterial() failed
+     * @throws IOException              setKeyMaterial() failed
+     */
+    public boolean useTomcatSSLMaterial()
+        throws GeneralSecurityException, IOException {
+        // If running inside Tomcat, let's try to re-use Tomcat's SSL
+        // certificate for our own stuff (e.g. RMI-SSL).
+        Integer p8443 = new Integer(8443);
+        KeyMaterial km;
+        TrustMaterial tm;
+        km = (KeyMaterial) TomcatServerXML.KEY_MATERIAL_BY_PORT.get(p8443);
+        tm = (TrustMaterial) TomcatServerXML.TRUST_MATERIAL_BY_PORT.get(p8443);
+
+        // If 8443 isn't set, let's take lowest secure port.
+        km = km == null ? TomcatServerXML.KEY_MATERIAL : km;
+        tm = tm == null ? TomcatServerXML.TRUST_MATERIAL : tm;
+        boolean success = false;
+        if (km != null) {
+            setKeyMaterial(km);
+            success = true;
+            if (tm != null && !TrustMaterial.DEFAULT.equals(tm)) {
+                setTrustMaterial(tm);
+            }
+        }
+        return success;
+    }
+
+    private boolean useDefaultKeyMaterial()
+        throws GeneralSecurityException, IOException {
+        // If we're not able to re-use Tomcat's SSLServerSocket configuration,
+        // commons-ssl default KeyMaterial will be  ~/.keystore with a password
+        // of "changeit".
+        Properties props = System.getProperties();
+        boolean pwdSet = props.containsKey("javax.net.ssl.keyStorePassword");
+        String pwd = props.getProperty("javax.net.ssl.keyStorePassword");
+        pwd = pwdSet ? pwd : "changeit";
+
+        String userHome = System.getProperty("user.home");
+        String path = userHome + "/.keystore";
+        File f = new File(path);
+        boolean success = false;
+        if (f.exists()) {
+            KeyMaterial km = null;
+            try {
+                km = new KeyMaterial(path, pwd.toCharArray());
+            }
+            catch (Exception e) {
+                // Don't want to blowup just because this silly default
+                // behaviour didn't work out.
+                if (pwdSet) {
+                    // Buf if the user has specified a non-standard password for
+                    // "javax.net.ssl.keyStorePassword", then we will warn them
+                    // that things didn't work out.
+                    System.err.println("commons-ssl automatic loading of [" + path + "] failed. ");
+                    System.err.println(e);
+                }
+            }
+            if (km != null) {
+                setKeyMaterial(km);
+                success = true;
+            }
+        }
+        return success;
+    }
+
+    public void addTrustMaterial(TrustChain trustChain)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        ssl.addTrustMaterial(trustChain);
+    }
+
+    public void setTrustMaterial(TrustChain trustChain)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        ssl.setTrustMaterial(trustChain);
+    }
+
+    public void setKeyMaterial(KeyMaterial keyMaterial)
+        throws NoSuchAlgorithmException, KeyStoreException,
+        KeyManagementException, IOException, CertificateException {
+        ssl.setKeyMaterial(keyMaterial);
+    }
+
+    public void addAllowedName(String s) { ssl.addAllowedName(s); }
+
+    public void addAllowedNames(Collection c) { ssl.addAllowedNames(c); }
+
+    public void clearAllowedNames() { ssl.clearAllowedNames(); }
+
+    public void setCheckCRL(boolean b) { ssl.setCheckCRL(b); }
+
+    public void setCheckExpiry(boolean b) { ssl.setCheckExpiry(b); }
+
+    public void setCheckHostname(boolean b) { ssl.setCheckHostname(b); }
+
+    public void setConnectTimeout(int i) { ssl.setConnectTimeout(i); }
+
+    public void setDefaultProtocol(String s) { ssl.setDefaultProtocol(s); }
+
+    public void useDefaultJavaCiphers() { ssl.useDefaultJavaCiphers(); }
+
+    public void useStrongCiphers() { ssl.useStrongCiphers(); }
+
+    public void setEnabledCiphers(String[] ciphers) {
+        ssl.setEnabledCiphers(ciphers);
+    }
+
+    public void setEnabledProtocols(String[] protocols) {
+        ssl.setEnabledProtocols(protocols);
+    }
+
+    public void setHostnameVerifier(HostnameVerifier verifier) {
+        ssl.setHostnameVerifier(verifier);
+    }
+
+    public void setSoTimeout(int soTimeout) { ssl.setSoTimeout(soTimeout); }
+
+    public void setSSLWrapperFactory(SSLWrapperFactory wf) {
+        ssl.setSSLWrapperFactory(wf);
+    }
+
+    public void setNeedClientAuth(boolean b) { ssl.setNeedClientAuth(b); }
+
+    public void setWantClientAuth(boolean b) { ssl.setWantClientAuth(b); }
+
+    public void setUseClientMode(boolean b) { ssl.setUseClientMode(b); }
+
+    public List getAllowedNames() { return ssl.getAllowedNames(); }
+
+    public X509Certificate[] getAssociatedCertificateChain() {
+        return ssl.getAssociatedCertificateChain();
+    }
+
+    public boolean getCheckCRL() { return ssl.getCheckCRL(); }
+
+    public boolean getCheckExpiry() { return ssl.getCheckExpiry(); }
+
+    public boolean getCheckHostname() { return ssl.getCheckHostname(); }
+
+    public int getConnectTimeout() { return ssl.getConnectTimeout(); }
+
+    public String getDefaultProtocol() { return ssl.getDefaultProtocol(); }
+
+    public String[] getEnabledCiphers() { return ssl.getEnabledCiphers(); }
+
+    public String[] getEnabledProtocols() { return ssl.getEnabledProtocols(); }
+
+    public HostnameVerifier getHostnameVerifier() {
+        return ssl.getHostnameVerifier();
+    }
+
+    public int getSoTimeout() { return ssl.getSoTimeout(); }
+
+    public SSLWrapperFactory getSSLWrapperFactory() {
+        return ssl.getSSLWrapperFactory();
+    }
+
+    public boolean getNeedClientAuth() { return ssl.getNeedClientAuth(); }
+
+    public boolean getWantClientAuth() { return ssl.getWantClientAuth(); }
+
+    public boolean getUseClientMode() { /* SSLServer's default is false. */
+        return !ssl.getUseClientModeDefault() && ssl.getUseClientMode();
+    }
+
+    public SSLContext getSSLContext() throws GeneralSecurityException, IOException {
+        return ssl.getSSLContext();
+    }
+
+    public TrustChain getTrustChain() { return ssl.getTrustChain(); }
+
+    public X509Certificate[] getCurrentClientChain() {
+        return ssl.getCurrentClientChain();
+    }
+
+    public String[] getDefaultCipherSuites() {
+        return ssl.getDefaultCipherSuites();
+    }
+
+    public String[] getSupportedCipherSuites() {
+        return ssl.getSupportedCipherSuites();
+    }
+
+    public ServerSocket createServerSocket() throws IOException {
+        return ssl.createServerSocket();
+    }
+
+    public ServerSocket createServerSocket(int port)
+        throws IOException {
+        return createServerSocket(port, 50);
+    }
+
+    public ServerSocket createServerSocket(int port, int backlog)
+        throws IOException {
+        return createServerSocket(port, backlog, null);
+    }
+
+    /**
+     * Attempts to get a new socket connection to the given host within the
+     * given time limit.
+     *
+     * @param localHost the local host name/IP to bind against (null == ANY)
+     * @param port      the port to listen on
+     * @param backlog   number of connections allowed to queue up for accept().
+     * @return SSLServerSocket a new server socket
+     * @throws IOException if an I/O error occurs while creating thesocket
+     */
+    public ServerSocket createServerSocket(int port, int backlog,
+                                           InetAddress localHost)
+        throws IOException {
+        return ssl.createServerSocket(port, backlog, localHost);
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLServerSocketWrapper.java b/src/java/org/apache/commons/ssl/SSLServerSocketWrapper.java
new file mode 100644
index 0000000..f83e158
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLServerSocketWrapper.java
@@ -0,0 +1,182 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLServerSocketWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.channels.ServerSocketChannel;
+
+/**
+ * Wraps an SSLServerSocket - NOTE that the accept() method applies a number of
+ * important common-ssl settings before returning the SSLSocket!
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 20-Nov-2006
+ */
+public class SSLServerSocketWrapper extends SSLServerSocket {
+    protected SSLServerSocket s;
+    protected SSL ssl;
+    protected SSLWrapperFactory wf;
+
+    public SSLServerSocketWrapper(SSLServerSocket s, SSL ssl,
+                                  SSLWrapperFactory wf)
+        throws IOException {
+        super();
+        this.s = s;
+        this.ssl = ssl;
+        this.wf = wf;
+    }
+
+    /* javax.net.ssl.SSLServerSocket */
+
+    public Socket accept() throws IOException {
+        SSLSocket secureSocket = (SSLSocket) s.accept();
+
+        // Do the commons-ssl usual housekeeping for every socket:
+        ssl.doPreConnectSocketStuff(secureSocket);
+        InetAddress addr = secureSocket.getInetAddress();
+        String hostName = addr.getHostName();
+        ssl.doPostConnectSocketStuff(secureSocket, hostName);
+
+        return wf.wrap(secureSocket);
+    }
+
+    public String[] getEnabledCipherSuites() {
+        return s.getEnabledCipherSuites();
+    }
+
+    public String[] getEnabledProtocols() { return s.getEnabledProtocols(); }
+
+    public boolean getEnableSessionCreation() {
+        return s.getEnableSessionCreation();
+    }
+
+    public boolean getNeedClientAuth() { return s.getNeedClientAuth(); }
+
+    public String[] getSupportedCipherSuites() {
+        return s.getSupportedCipherSuites();
+    }
+
+    public String[] getSupportedProtocols() { return s.getSupportedProtocols(); }
+
+    public boolean getUseClientMode() { return s.getUseClientMode(); }
+
+    public boolean getWantClientAuth() { return s.getWantClientAuth(); }
+
+    public void setEnabledCipherSuites(String[] suites) {
+        s.setEnabledCipherSuites(suites);
+    }
+
+    public void setEnabledProtocols(String[] protocols) {
+        s.setEnabledProtocols(protocols);
+    }
+
+    public void setEnableSessionCreation(boolean flag) {
+        s.setEnableSessionCreation(flag);
+    }
+
+    public void setNeedClientAuth(boolean need) {
+        s.setNeedClientAuth(need);
+    }
+
+    public void setUseClientMode(boolean use) { s.setUseClientMode(use); }
+
+    public void setWantClientAuth(boolean want) {
+        s.setWantClientAuth(want);
+    }
+
+    /* java.net.Socket */
+
+    public void bind(SocketAddress endpoint) throws IOException {
+        s.bind(endpoint);
+    }
+
+    public void bind(SocketAddress ep, int bl) throws IOException {
+        s.bind(ep, bl);
+    }
+
+    public void close() throws IOException { s.close(); }
+
+    public ServerSocketChannel getChannel() { return s.getChannel(); }
+
+    public InetAddress getInetAddress() { return s.getInetAddress(); }
+
+    public int getLocalPort() { return s.getLocalPort(); }
+
+    public SocketAddress getLocalSocketAddress() {
+        return s.getLocalSocketAddress();
+    }
+
+    public int getReceiveBufferSize() throws SocketException {
+        return s.getReceiveBufferSize();
+    }
+
+    public boolean getReuseAddress() throws SocketException {
+        return s.getReuseAddress();
+    }
+
+    public int getSoTimeout() throws IOException { return s.getSoTimeout(); }
+
+    public boolean isBound() { return s.isBound(); }
+
+    public boolean isClosed() { return s.isClosed(); }
+
+    public void setReceiveBufferSize(int size) throws SocketException {
+        s.setReceiveBufferSize(size);
+    }
+
+    public void setReuseAddress(boolean on) throws SocketException {
+        s.setReuseAddress(on);
+    }
+
+    public void setSoTimeout(int timeout) throws SocketException {
+        s.setSoTimeout(timeout);
+    }
+
+    public String toString() { return s.toString(); }
+
+    /*  Java 1.5
+     public void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
+     {
+         s.setPerformancePreferences( connectionTime, latency, bandwidth );
+     }
+     */
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLSocketWrapper.java b/src/java/org/apache/commons/ssl/SSLSocketWrapper.java
new file mode 100644
index 0000000..20726d5
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLSocketWrapper.java
@@ -0,0 +1,251 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLSocketWrapper.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.channels.SocketChannel;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 16-Aug-2006
+ */
+public class SSLSocketWrapper extends SSLSocket {
+    protected SSLSocket s;
+
+    public SSLSocketWrapper(SSLSocket s) {
+        this.s = s;
+    }
+
+    /* javax.net.ssl.SSLSocket */
+
+    public void addHandshakeCompletedListener(HandshakeCompletedListener hcl) {
+        s.addHandshakeCompletedListener(hcl);
+    }
+
+    public void removeHandshakeCompletedListener(HandshakeCompletedListener hcl) {
+        s.removeHandshakeCompletedListener(hcl);
+    }
+
+    public String[] getSupportedCipherSuites() {
+        return s.getSupportedCipherSuites();
+    }
+
+    public boolean getEnableSessionCreation() {
+        return s.getEnableSessionCreation();
+    }
+
+    public String[] getEnabledCipherSuites() {
+        return s.getEnabledCipherSuites();
+    }
+
+    public String[] getSupportedProtocols() { return s.getSupportedProtocols(); }
+
+    public String[] getEnabledProtocols() { return s.getEnabledProtocols(); }
+
+    public SSLSession getSession() { return s.getSession(); }
+
+    public boolean getUseClientMode() { return s.getUseClientMode(); }
+
+    public boolean getNeedClientAuth() { return s.getNeedClientAuth(); }
+
+    public boolean getWantClientAuth() { return s.getWantClientAuth(); }
+
+    public void setEnabledCipherSuites(String[] cs) {
+        s.setEnabledCipherSuites(cs);
+    }
+
+    public void setEnabledProtocols(String[] ep) {
+        s.setEnabledProtocols(ep);
+    }
+
+    public void startHandshake() throws IOException { s.startHandshake(); }
+
+    public void setUseClientMode(boolean b) { s.setUseClientMode(b); }
+
+    public void setNeedClientAuth(boolean b) { s.setNeedClientAuth(b); }
+
+    public void setWantClientAuth(boolean b) { s.setWantClientAuth(b); }
+
+    public void setEnableSessionCreation(boolean b) {
+        s.setEnableSessionCreation(b);
+    }
+
+    /* java.net.Socket */
+
+    public SocketChannel getChannel() { return s.getChannel(); }
+
+    public InetAddress getInetAddress() { return s.getInetAddress(); }
+
+    public boolean getKeepAlive() throws SocketException {
+        return s.getKeepAlive();
+    }
+
+    public InetAddress getLocalAddress() { return s.getLocalAddress(); }
+
+    public int getLocalPort() { return s.getLocalPort(); }
+
+    public SocketAddress getLocalSocketAddress() {
+        return s.getLocalSocketAddress();
+    }
+
+    public boolean getOOBInline() throws SocketException {
+        return s.getOOBInline();
+    }
+
+    public int getPort() { return s.getPort(); }
+
+    public int getReceiveBufferSize() throws SocketException {
+        return s.getReceiveBufferSize();
+    }
+
+    public SocketAddress getRemoteSocketAddress() {
+        return s.getRemoteSocketAddress();
+    }
+
+    public boolean getReuseAddress() throws SocketException {
+        return s.getReuseAddress();
+    }
+
+    public int getSendBufferSize() throws SocketException {
+        return s.getSendBufferSize();
+    }
+
+    public int getSoLinger() throws SocketException { return s.getSoLinger(); }
+
+    public int getSoTimeout() throws SocketException { return s.getSoTimeout(); }
+
+    public boolean getTcpNoDelay() throws SocketException {
+        return s.getTcpNoDelay();
+    }
+
+    public int getTrafficClass() throws SocketException {
+        return s.getTrafficClass();
+    }
+
+    public boolean isBound() { return s.isBound(); }
+
+    public boolean isClosed() { return s.isClosed(); }
+
+    public boolean isConnected() { return s.isConnected(); }
+
+    public boolean isInputShutdown() { return s.isInputShutdown(); }
+
+    public boolean isOutputShutdown() { return s.isOutputShutdown(); }
+
+    public void sendUrgentData(int data) throws IOException {
+        s.sendUrgentData(data);
+    }
+
+    public void setKeepAlive(boolean on) throws SocketException {
+        s.setKeepAlive(on);
+    }
+
+    public void setOOBInline(boolean on) throws SocketException {
+        s.setOOBInline(on);
+    }
+
+    public void setReceiveBufferSize(int size) throws SocketException {
+        s.setReceiveBufferSize(size);
+    }
+
+    public void setReuseAddress(boolean on) throws SocketException {
+        s.setReuseAddress(on);
+    }
+
+    public void setSendBufferSize(int size) throws SocketException {
+        s.setSendBufferSize(size);
+    }
+
+    public void setSoLinger(boolean on, int l) throws SocketException {
+        s.setSoLinger(on, l);
+    }
+
+    public void setSoTimeout(int timeout) throws SocketException {
+        s.setSoTimeout(timeout);
+    }
+
+    public void setTcpNoDelay(boolean on) throws SocketException {
+        s.setTcpNoDelay(on);
+    }
+
+    public void setTrafficClass(int tc) throws SocketException {
+        s.setTrafficClass(tc);
+    }
+
+    public void shutdownInput() throws IOException { s.shutdownInput(); }
+
+    public void shutdownOutput() throws IOException { s.shutdownOutput(); }
+
+    public String toString() { return s.toString(); }
+
+    /*  Java 1.5
+     public void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
+     {
+         s.setPerformancePreferences( connectionTime, latency, bandwidth );
+     }
+     */
+
+    public void bind(SocketAddress bindpoint) throws IOException {
+        s.bind(bindpoint);
+    }
+
+    public void close() throws IOException {
+        s.close();
+    }
+
+    public void connect(SocketAddress endpoint) throws IOException {
+        s.connect(endpoint);
+    }
+
+    public void connect(SocketAddress endpoint, int timeout) throws IOException {
+        s.connect(endpoint, timeout);
+    }
+
+    public InputStream getInputStream() throws IOException {
+        return s.getInputStream();
+    }
+
+    public OutputStream getOutputStream() throws IOException {
+        return s.getOutputStream();
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/SSLWrapperFactory.java b/src/java/org/apache/commons/ssl/SSLWrapperFactory.java
new file mode 100644
index 0000000..3848259
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/SSLWrapperFactory.java
@@ -0,0 +1,109 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/SSLWrapperFactory.java $
+ * $Revision: 129 $
+ * $Date: 2007-11-14 19:21:33 -0800 (Wed, 14 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 19-Sep-2006
+ */
+public interface SSLWrapperFactory {
+
+    /**
+     * Wraps an SSLSSocket.
+     *
+     * @param s SSLSocket to wrap.
+     * @return The new wrapped SSLSocket.
+     * @throws IOException if wrapping failed
+     */
+    public SSLSocket wrap(SSLSocket s) throws IOException;
+
+    /**
+     * Wraps an SSLServerSocket.
+     *
+     * @param s   The SSLServerSocket to wrap.
+     * @param ssl The SSL object that created the SSLServerSocket.
+     *            This way some important commons-ssl config can be applied
+     *            to the returned socket.
+     * @return The new wrapped SSLServerSocket.
+     * @throws IOException if wrapping failed
+     */
+    public SSLServerSocket wrap(SSLServerSocket s, SSL ssl)
+        throws IOException;
+
+
+    /**
+     * NO_WRAP doesn't wrap the SSLSocket.  It does wrap the SSLServerSocket
+     * so that we can do the usual housekeeping after accept() that we like to
+     * do on every socket.  E.g. setSoTimeout, setEnabledProtocols,
+     * setEnabledCiphers, setUseClientMode, and the hostname verifier (which
+     * should be very rare on SSLServerSockets!).
+     */
+    public final static SSLWrapperFactory NO_WRAP = new SSLWrapperFactory() {
+        // Notice!  No wrapping!
+        public SSLSocket wrap(SSLSocket s) { return s; }
+
+        // We still wrap the ServerSocket, but we don't wrap the result of the
+        // the accept() call.
+        public SSLServerSocket wrap(SSLServerSocket s, SSL ssl)
+            throws IOException {
+            // Can't wrap with Java 1.3 because SSLServerSocket's constructor has
+            // default access instead of protected access in Java 1.3.
+            boolean java13 = JavaImpl.isJava13();
+            return java13 ? s : new SSLServerSocketWrapper(s, ssl, this);
+        }
+    };
+
+    /**
+     * DUMB_WRAP is useful to make sure that wrapping the sockets doesn't break
+     * anything.  It doesn't actually do anything interesting in its wrapped
+     * implementations.
+     */
+    public final static SSLWrapperFactory DUMB_WRAP = new SSLWrapperFactory() {
+        public SSLSocket wrap(SSLSocket s) { return new SSLSocketWrapper(s); }
+
+        public SSLServerSocket wrap(SSLServerSocket s, SSL ssl)
+            throws IOException {
+            // Can't wrap with Java 1.3 because SSLServerSocket's constructor has
+            // default access instead of protected access in Java 1.3.
+            boolean java13 = JavaImpl.isJava13();
+            return java13 ? s : new SSLServerSocketWrapper(s, ssl, this);
+        }
+    };
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/TomcatServerXML.java b/src/java/org/apache/commons/ssl/TomcatServerXML.java
new file mode 100644
index 0000000..e9ccc5c
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/TomcatServerXML.java
@@ -0,0 +1,231 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/TomcatServerXML.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class TomcatServerXML {
+    private final static LogWrapper log = LogWrapper.getLogger(TomcatServerXML.class);
+
+    /**
+     * KeyMaterial extracted from Tomcat's conf/server.xml.  There might be
+     * several KeyMaterials to extract if Tomcat has different SSL Certificates
+     * listening on different ports.  This particular KeyMaterial will come from
+     * the lowest secure port that Tomcat is properly configured to open.
+     */
+    public final static KeyMaterial KEY_MATERIAL;
+
+    /**
+     * TrustMaterial extracted from Tomcat's conf/server.xml.  There might be
+     * several TrustMaterials to extract if Tomcat has different SSL Certificates
+     * listening on different ports.  This particular TrustMaterial will come
+     * from the lowest secure port that Tomcat is properly configured to open.
+     * </p><p>
+     * There's a good chance this will be set to TrustMaterial.DEFAULT (which
+     * use's the JVM's '$JAVA_HOME/jre/lib/security/cacerts' file).
+     * </p><p>
+     * Note:  With SSLServerSockets, TrustMaterial only matters when the
+     * incoming client socket (SSLSocket) presents a client certificate.
+     * </p>
+     */
+    public final static TrustMaterial TRUST_MATERIAL;
+
+    /**
+     * new Integer( port ) --> KeyMaterial mapping of SSL Certificates found
+     * inside Tomcat's conf/server.xml file.
+     */
+    public final static SortedMap KEY_MATERIAL_BY_PORT;
+
+    /**
+     * new Integer( port ) --> TrustMaterial mapping of SSL configuration
+     * found inside Tomcat's conf/server.xml file.
+     * </p><p>
+     * Many of these will probably be TrustMaterial.DEFAULT (which uses the
+     * JVM's '$JAVA_HOME/jre/lib/security/cacerts' file).
+     * </p><p>
+     * Note:  With SSLServerSockets, TrustMaterial only matters when the
+     * incoming client socket (SSLSocket) presents a client certificate.
+     * </p>
+     */
+    public final static SortedMap TRUST_MATERIAL_BY_PORT;
+
+    static {
+        String tomcatHome = System.getProperty("catalina.home");
+        String serverXML = tomcatHome + "/conf/server.xml";
+        TreeMap keyMap = new TreeMap();
+        TreeMap trustMap = new TreeMap();
+        InputStream in = null;
+        Document doc = null;
+        try {
+            if (tomcatHome != null) {
+                File f = new File(serverXML);
+                if (f.exists()) {
+                    try {
+                        in = new FileInputStream(serverXML);
+                    }
+                    catch (IOException ioe) {
+                        // oh well, no soup for us.
+                        log.warn("Commons-SSL failed to load Tomcat's [" + serverXML + "] " + ioe);
+                    }
+                }
+            }
+            if (in != null) {
+                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+                try {
+                    DocumentBuilder db = dbf.newDocumentBuilder();
+                    doc = db.parse(in);
+                }
+                catch (Exception e) {
+                    log.warn("Commons-SSL failed to parse Tomcat's [" + serverXML + "] " + e);
+                }
+            }
+            if (doc != null) {
+                loadTomcatConfig(doc, keyMap, trustMap);
+            }
+        }
+        finally {
+            if (in != null) {
+                try { in.close(); } catch (Exception e) { /* . */ }
+            }
+        }
+        KEY_MATERIAL_BY_PORT = Collections.unmodifiableSortedMap(keyMap);
+        TRUST_MATERIAL_BY_PORT = Collections.unmodifiableSortedMap(trustMap);
+
+        KeyMaterial km = null;
+        TrustMaterial tm = null;
+        if (!keyMap.isEmpty()) {
+            km = (KeyMaterial) keyMap.get(keyMap.firstKey());
+        }
+        if (!trustMap.isEmpty()) {
+            tm = (TrustMaterial) trustMap.get(trustMap.firstKey());
+        }
+        KEY_MATERIAL = km;
+        TRUST_MATERIAL = tm;
+
+    }
+
+    private static void loadTomcatConfig(Document d, Map keyMap, Map trustMap) {
+        final String userHome = System.getProperty("user.home");
+        NodeList nl = d.getElementsByTagName("Connector");
+        for (int i = 0; i < nl.getLength(); i++) {
+            KeyMaterial km = null;
+            TrustMaterial tm = null;
+
+            Element element = (Element) nl.item(i);
+            String secure = element.getAttribute("secure");
+            String portString = element.getAttribute("port");
+            Integer port = null;
+            String pass;
+            try {
+                portString = portString != null ? portString.trim() : "";
+                port = new Integer(portString);
+            }
+            catch (NumberFormatException nfe) {
+                // oh well
+            }
+            if (port != null && Util.isYes(secure)) {
+                // Key Material
+                String keystoreFile = element.getAttribute("keystoreFile");
+                pass = element.getAttribute("keystorePass");
+                if (!element.hasAttribute("keystoreFile")) {
+                    keystoreFile = userHome + "/.keystore";
+                }
+                if (!element.hasAttribute("keystorePass")) {
+                    pass = "changeit";
+                }
+                char[] keystorePass = pass != null ? pass.toCharArray() : null;
+
+                // Trust Material
+                String truststoreFile = element.getAttribute("truststoreFile");
+                pass = element.getAttribute("truststorePass");
+                if (!element.hasAttribute("truststoreFile")) {
+                    truststoreFile = null;
+                }
+                if (!element.hasAttribute("truststorePass")) {
+                    pass = null;
+                }
+                char[] truststorePass = pass != null ? pass.toCharArray() : null;
+
+
+                if (keystoreFile == null) {
+                    km = null;
+                } else {
+                    try {
+                        km = new KeyMaterial(keystoreFile, keystorePass);
+                    }
+                    catch (Exception e) {
+                        log.warn("Commons-SSL failed to load [" + keystoreFile + "] " + e);
+                    }
+                }
+                if (truststoreFile == null) {
+                    tm = TrustMaterial.DEFAULT;
+                } else {
+                    try {
+                        tm = new TrustMaterial(truststoreFile, truststorePass);
+                    }
+                    catch (Exception e) {
+                        log.warn("Commons-SSL failed to load [" + truststoreFile + "] " + e);
+                    }
+                }
+
+                Object o = keyMap.put(port, km);
+                if (o != null) {
+                    log.debug("Commons-SSL TomcatServerXML keyMap clobbered port: " + port);
+                }
+                o = trustMap.put(port, tm);
+                if (o != null) {
+                    log.debug("Commons-SSL TomcatServerXML trustMap clobbered port: " + port);
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/TrustChain.java b/src/java/org/apache/commons/ssl/TrustChain.java
new file mode 100644
index 0000000..4ef8683
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/TrustChain.java
@@ -0,0 +1,206 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/TrustChain.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 27-Feb-2006
+ */
+public class TrustChain {
+    private final Set trustMaterial =
+        Collections.synchronizedSet(new HashSet());
+    private SortedSet x509Certificates = null;
+    private KeyStore unifiedKeyStore = null;
+
+    public TrustChain() {
+    }
+
+    public synchronized KeyStore getUnifiedKeyStore()
+        throws KeyStoreException, IOException, NoSuchAlgorithmException,
+        CertificateException {
+
+        // x509Certificates serves as our "cache available" indicator.
+        if (x509Certificates != null) {
+            return unifiedKeyStore;
+        }
+
+        // First, extract all the X509Certificates from this TrustChain.
+        this.x509Certificates = new TreeSet(Certificates.COMPARE_BY_EXPIRY);
+        Iterator it = trustMaterial.iterator();
+        while (it.hasNext()) {
+            TrustMaterial tm = (TrustMaterial) it.next();
+            KeyStore ks = tm.getKeyStore();
+            if (ks != null) {
+                Enumeration en = ks.aliases();
+                while (en.hasMoreElements()) {
+                    String alias = (String) en.nextElement();
+                    if (ks.isCertificateEntry(alias)) {
+                        X509Certificate cert;
+                        cert = (X509Certificate) ks.getCertificate(alias);
+                        if (!x509Certificates.contains(cert)) {
+                            x509Certificates.add(cert);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Now that the X509Certificates are extracted, create the unified
+        // keystore.
+        it = x509Certificates.iterator();
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        ks.load(null, null);
+        int count = 0;
+        while (it.hasNext()) {
+            X509Certificate cert = (X509Certificate) it.next();
+            // The "count" should keep the aliases unique (is that important?)
+            String alias = "commons-ssl-" + count;
+            ks.setCertificateEntry(alias, cert);
+            count++;
+        }
+        this.unifiedKeyStore = ks;
+        return unifiedKeyStore;
+    }
+
+    public synchronized void addTrustMaterial(TrustChain tc) {
+        this.x509Certificates = null;  // invalidate cache
+        if (tc instanceof TrustMaterial) {
+            trustMaterial.add(tc);
+        }
+        // If duplicates are added, the Set will remove them.
+        trustMaterial.addAll(tc.trustMaterial);
+    }
+
+    public boolean contains(TrustChain tc) {
+        if (tc instanceof TrustMaterial) {
+            return trustMaterial.contains(tc);
+        } else {
+            return trustMaterial.containsAll(tc.trustMaterial);
+        }
+    }
+
+    public boolean contains(X509Certificate cert)
+        throws KeyStoreException, IOException, NoSuchAlgorithmException,
+        CertificateException {
+        return getCertificates().contains(cert);
+    }
+
+    public Object getTrustManagerFactory()
+        throws NoSuchAlgorithmException, KeyStoreException, IOException,
+        CertificateException {
+        KeyStore uks = getUnifiedKeyStore();
+        if (uks != null) {
+            return JavaImpl.newTrustManagerFactory(uks);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return Array of TrustManager[] - presumably these will be dropped into
+     *         a call to SSLContext.init().  Note:  returns null if this
+     *         TrustChain doesn't contain anything to trust.
+     * @throws NoSuchAlgorithmException serious problems
+     * @throws KeyStoreException        serious problems
+     * @throws IOException              serious problems
+     * @throws CertificateException     serious problems
+     */
+    public Object[] getTrustManagers()
+        throws NoSuchAlgorithmException, KeyStoreException, IOException,
+        CertificateException {
+        Object tmf = getTrustManagerFactory();
+        return tmf != null ? JavaImpl.getTrustManagers(tmf) : null;
+    }
+
+    /**
+     * @return All X509Certificates contained in this TrustChain as a SortedSet.
+     *         The X509Certificates are sorted based on expiry date.
+     *         <p/>
+     *         See org.apache.commons.ssl.Certificates.COMPARE_BY_EXPIRY.
+     * @throws KeyStoreException        serious problems
+     * @throws IOException              serious problems
+     * @throws NoSuchAlgorithmException serious problems
+     * @throws CertificateException     serious problems
+     */
+    public synchronized SortedSet getCertificates()
+        throws KeyStoreException, IOException, NoSuchAlgorithmException,
+        CertificateException {
+        if (x509Certificates == null) {
+            getUnifiedKeyStore();
+        }
+        return Collections.unmodifiableSortedSet(x509Certificates);
+    }
+
+    /**
+     * @return Count of all X509Certificates contained in this TrustChain.
+     * @throws KeyStoreException
+     * @throws IOException
+     * @throws NoSuchAlgorithmException
+     * @throws CertificateException
+     */
+    public synchronized int getSize()
+        throws KeyStoreException, IOException, NoSuchAlgorithmException,
+        CertificateException {
+        return getCertificates().size();
+    }
+
+    /**
+     * @return Count of all X509Certificates contained in this TrustChain.
+     * @throws KeyStoreException
+     * @throws IOException
+     * @throws NoSuchAlgorithmException
+     * @throws CertificateException
+     */
+    public synchronized boolean isEmpty()
+        throws KeyStoreException, IOException, NoSuchAlgorithmException,
+        CertificateException {
+        return getCertificates().isEmpty();
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/TrustMaterial.java b/src/java/org/apache/commons/ssl/TrustMaterial.java
new file mode 100644
index 0000000..79caceb
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/TrustMaterial.java
@@ -0,0 +1,272 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/TrustMaterial.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 27-Feb-2006
+ */
+public class TrustMaterial extends TrustChain {
+    final static int SIMPLE_TRUST_TYPE_TRUST_ALL = 1;
+    final static int SIMPLE_TRUST_TYPE_TRUST_THIS_JVM = 2;
+
+    /** Might be null if "$JAVA_HOME/jre/lib/security/cacerts" doesn't exist. */
+    public final static TrustMaterial CACERTS;
+
+    /** Might be null if "$JAVA_HOME/jre/lib/security/jssecacerts" doesn't exist. */
+    public final static TrustMaterial JSSE_CACERTS;
+
+    /**
+     * Should never be null (unless both CACERTS and JSSE_CACERTS are not
+     * present???).  Is either CACERTS or JSSE_CACERTS.  Priority given to
+     * JSSE_CACERTS, but 99.9% of the time it's CACERTS, since JSSE_CACERTS
+     * is almost never present.
+     */
+    public final static TrustMaterial DEFAULT;
+
+    static {
+        JavaImpl.load();
+        String javaHome = System.getProperty("java.home");
+        String pathToCacerts = javaHome + "/lib/security/cacerts";
+        String pathToJSSECacerts = javaHome + "/lib/security/jssecacerts";
+        TrustMaterial cacerts = null;
+        TrustMaterial jssecacerts = null;
+        try {
+            File f = new File(pathToCacerts);
+            if (f.exists()) {
+                cacerts = new TrustMaterial(pathToCacerts);
+            }
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+        try {
+            File f = new File(pathToJSSECacerts);
+            if (f.exists()) {
+                jssecacerts = new TrustMaterial(pathToJSSECacerts);
+            }
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        CACERTS = cacerts;
+        JSSE_CACERTS = jssecacerts;
+        if (JSSE_CACERTS != null) {
+            DEFAULT = JSSE_CACERTS;
+        } else {
+            DEFAULT = CACERTS;
+        }
+    }
+
+    public final static TrustMaterial TRUST_ALL =
+        new TrustMaterial(SIMPLE_TRUST_TYPE_TRUST_ALL);
+
+    public final static TrustMaterial TRUST_THIS_JVM =
+        new TrustMaterial(SIMPLE_TRUST_TYPE_TRUST_THIS_JVM);
+
+    public final int simpleTrustType;
+    private final KeyStore jks;
+
+    private TrustMaterial(int simpleTrustType) {
+        this(null, simpleTrustType);
+    }
+
+    TrustMaterial(KeyStore jks, int simpleTrustType) {
+        if (jks == null && simpleTrustType != 0) {
+            // Just use CACERTS as a place holder, since Java 5 and 6 seem to get
+            // upset when we hand SSLContext null TrustManagers.  See
+            // Java14.initSSL(), which despite its name, is also used
+            // with Java5 and Java6.
+            this.jks = CACERTS != null ? CACERTS.jks : JSSE_CACERTS.jks;
+        } else {
+            this.jks = jks;
+        }
+        addTrustMaterial(this);
+        this.simpleTrustType = simpleTrustType;
+    }
+
+    public TrustMaterial(Collection x509Certs)
+        throws GeneralSecurityException, IOException {
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        ks.load(null, null);
+        loadCerts(ks, x509Certs);
+        this.jks = ks;
+        addTrustMaterial(this);
+
+        // We're not a simple trust type, so set value to 0.
+        // Only TRUST_ALL and TRUST_THIS_JVM are simple trust types.
+        this.simpleTrustType = 0;
+    }
+
+    public TrustMaterial(X509Certificate x509Cert)
+        throws GeneralSecurityException, IOException {
+        this(Collections.singleton(x509Cert));
+    }
+
+    public TrustMaterial(X509Certificate[] x509Certs)
+        throws GeneralSecurityException, IOException {
+        this(Arrays.asList(x509Certs));
+    }
+
+    public TrustMaterial(byte[] pemBase64)
+        throws GeneralSecurityException, IOException {
+        this(pemBase64, null);
+    }
+
+    public TrustMaterial(InputStream pemBase64)
+        throws GeneralSecurityException, IOException {
+        this(Util.streamToBytes(pemBase64));
+    }
+
+    public TrustMaterial(String pathToPemFile)
+        throws GeneralSecurityException, IOException {
+        this(new FileInputStream(pathToPemFile));
+    }
+
+    public TrustMaterial(File pemFile)
+        throws GeneralSecurityException, IOException {
+        this(new FileInputStream(pemFile));
+    }
+
+    public TrustMaterial(URL urlToPemFile)
+        throws GeneralSecurityException, IOException {
+        this(urlToPemFile.openStream());
+    }
+
+    public TrustMaterial(String pathToJksFile, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(new File(pathToJksFile), password);
+    }
+
+    public TrustMaterial(File jksFile, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(new FileInputStream(jksFile), password);
+    }
+
+    public TrustMaterial(URL urlToJKS, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(urlToJKS.openStream(), password);
+    }
+
+    public TrustMaterial(InputStream jks, char[] password)
+        throws GeneralSecurityException, IOException {
+        this(Util.streamToBytes(jks), password);
+    }
+
+
+    public TrustMaterial(byte[] jks, char[] password)
+        throws GeneralSecurityException, IOException {
+
+        KeyStoreBuilder.BuildResult br = KeyStoreBuilder.parse(jks, password);
+        if (br.jks != null) {
+            // If we've been given a keystore, just use that.
+            this.jks = br.jks;
+        } else {
+            // Otherwise we need to build a keystore from what we were given.
+            KeyStore ks = KeyStore.getInstance("jks");
+            if (br.chain != null && br.chain.length > 0) {
+                ks.load(null, password);
+                loadCerts(ks, Arrays.asList(br.chain));
+            }
+            this.jks = ks;
+        }
+
+        // Should validate our keystore to make sure it has at least ONE
+        // certificate entry:
+        KeyStore ks = this.jks;
+        boolean hasCertificates = false;
+        Enumeration en = ks.aliases();
+        while (en.hasMoreElements()) {
+            String alias = (String) en.nextElement();
+            if (ks.isCertificateEntry(alias)) {
+                hasCertificates = true;
+                break;
+            }
+        }
+        if (!hasCertificates) {
+            throw new KeyStoreException("TrustMaterial couldn't load any certificates to trust!");
+        }
+
+        // overwrite password
+        if (password != null && !(this instanceof KeyMaterial)) {
+            for (int i = 0; i < password.length; i++) {
+                password[i] = '*';
+            }
+        }
+        addTrustMaterial(this);
+
+        // We're not a simple trust type, so set value to 0.
+        // Only TRUST_ALL and TRUST_THIS_JVM are simple trust types.
+        this.simpleTrustType = 0;
+    }
+
+    public KeyStore getKeyStore() {
+        return jks;
+    }
+
+    private static void loadCerts(KeyStore ks, Collection certs)
+        throws KeyStoreException {
+        Iterator it = certs.iterator();
+        int count = 0;
+        while (it.hasNext()) {
+            X509Certificate cert = (X509Certificate) it.next();
+
+            // I could be fancy and parse out the CN field from the
+            // certificate's subject, but these names don't actually matter
+            // at all - I think they just have to be unique.
+            String cn = Certificates.getCN(cert);
+            String alias = cn + "_" + count;
+            ks.setCertificateEntry(alias, cert);
+            count++;
+        }
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/Util.java b/src/java/org/apache/commons/ssl/Util.java
new file mode 100644
index 0000000..d16cde8
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Util.java
@@ -0,0 +1,403 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Util.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 28-Feb-2006
+ */
+public class Util {
+    public final static int SIZE_KEY = 0;
+    public final static int LAST_READ_KEY = 1;
+
+    public static boolean isYes(String yesString) {
+        if (yesString == null) {
+            return false;
+        }
+        String s = yesString.trim().toUpperCase();
+        return "1".equals(s) || "YES".equals(s) || "TRUE".equals(s) ||
+               "ENABLE".equals(s) || "ENABLED".equals(s) || "Y".equals(s) ||
+               "ON".equals(s);
+    }
+
+    public static String trim(final String s) {
+        if (s == null || "".equals(s)) {
+            return s;
+        }
+        int i = 0;
+        int j = s.length() - 1;
+        while (isWhiteSpace(s.charAt(i))) {
+            i++;
+        }
+        while (isWhiteSpace(s.charAt(j))) {
+            j--;
+        }
+        return j >= i ? s.substring(i, j + 1) : "";
+    }
+
+    public static boolean isWhiteSpace(final char c) {
+        switch (c) {
+            case 0:
+            case ' ':
+            case '\t':
+            case '\n':
+            case '\r':
+            case '\f':
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static void pipeStream(InputStream in, OutputStream out)
+        throws IOException {
+        pipeStream(in, out, true);
+    }
+
+    public static void pipeStream(InputStream in, OutputStream out,
+                                  boolean autoClose)
+        throws IOException {
+        byte[] buf = new byte[4096];
+        IOException ioe = null;
+        try {
+            int bytesRead = in.read(buf);
+            while (bytesRead >= 0) {
+                if (bytesRead > 0) {
+                    out.write(buf, 0, bytesRead);
+                }
+                bytesRead = in.read(buf);
+            }
+        }
+        finally {
+            // Probably it's best to let consumer call "close", but I'm usually
+            // the consumer, and I want to be lazy.  [Julius, November 20th, 2006]
+            try { in.close(); } catch (IOException e) { ioe = e; }
+            if (autoClose) {
+                try { out.close(); } catch (IOException e) { ioe = e; }
+            }
+        }
+        if (ioe != null) {
+            throw ioe;
+        }
+    }
+
+    public static byte[] streamToBytes(final ByteArrayInputStream in,
+                                       int maxLength) {
+        byte[] buf = new byte[maxLength];
+        int[] status = fill(buf, 0, in);
+        int size = status[SIZE_KEY];
+        if (buf.length != size) {
+            byte[] smallerBuf = new byte[size];
+            System.arraycopy(buf, 0, smallerBuf, 0, size);
+            buf = smallerBuf;
+        }
+        return buf;
+    }
+
+    public static byte[] streamToBytes(final InputStream in, int maxLength)
+        throws IOException {
+        byte[] buf = new byte[maxLength];
+        int[] status = fill(buf, 0, in);
+        int size = status[SIZE_KEY];
+        if (buf.length != size) {
+            byte[] smallerBuf = new byte[size];
+            System.arraycopy(buf, 0, smallerBuf, 0, size);
+            buf = smallerBuf;
+        }
+        return buf;
+    }
+
+    public static byte[] streamToBytes(final InputStream in) throws IOException {
+        byte[] buf = new byte[4096];
+        try {
+            int[] status = fill(buf, 0, in);
+            int size = status[SIZE_KEY];
+            int lastRead = status[LAST_READ_KEY];
+            while (lastRead != -1) {
+                buf = resizeArray(buf);
+                status = fill(buf, size, in);
+                size = status[SIZE_KEY];
+                lastRead = status[LAST_READ_KEY];
+            }
+            if (buf.length != size) {
+                byte[] smallerBuf = new byte[size];
+                System.arraycopy(buf, 0, smallerBuf, 0, size);
+                buf = smallerBuf;
+            }
+        }
+        finally {
+            in.close();
+        }
+        return buf;
+    }
+
+    public static byte[] streamToBytes(final ByteArrayInputStream in) {
+        byte[] buf = new byte[4096];
+        int[] status = fill(buf, 0, in);
+        int size = status[SIZE_KEY];
+        int lastRead = status[LAST_READ_KEY];
+        while (lastRead != -1) {
+            buf = resizeArray(buf);
+            status = fill(buf, size, in);
+            size = status[SIZE_KEY];
+            lastRead = status[LAST_READ_KEY];
+        }
+        if (buf.length != size) {
+            byte[] smallerBuf = new byte[size];
+            System.arraycopy(buf, 0, smallerBuf, 0, size);
+            buf = smallerBuf;
+        }
+        // in.close();  <-- this is a no-op on ByteArrayInputStream.
+        return buf;
+    }
+
+    public static int[] fill(final byte[] buf, final int offset,
+                             final InputStream in)
+        throws IOException {
+        int read = in.read(buf, offset, buf.length - offset);
+        int lastRead = read;
+        if (read == -1) {
+            read = 0;
+        }
+        while (lastRead != -1 && read + offset < buf.length) {
+            lastRead = in.read(buf, offset + read, buf.length - read - offset);
+            if (lastRead != -1) {
+                read += lastRead;
+            }
+        }
+        return new int[]{offset + read, lastRead};
+    }
+
+    public static int[] fill(final byte[] buf, final int offset,
+                             final ByteArrayInputStream in) {
+        int read = in.read(buf, offset, buf.length - offset);
+        int lastRead = read;
+        if (read == -1) {
+            read = 0;
+        }
+        while (lastRead != -1 && read + offset < buf.length) {
+            lastRead = in.read(buf, offset + read, buf.length - read - offset);
+            if (lastRead != -1) {
+                read += lastRead;
+            }
+        }
+        return new int[]{offset + read, lastRead};
+    }
+
+    public static byte[] resizeArray(final byte[] bytes) {
+        byte[] biggerBytes = new byte[bytes.length * 2];
+        System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
+        return biggerBytes;
+    }
+
+    public static String pad(String s, final int length, final boolean left) {
+        if (s == null) {
+            s = "";
+        }
+        int diff = length - s.length();
+        if (diff == 0) {
+            return s;
+        } else if (diff > 0) {
+            StringBuffer sb = new StringBuffer();
+            if (left) {
+                for (int i = 0; i < diff; i++) {
+                    sb.append(' ');
+                }
+            }
+            sb.append(s);
+            if (!left) {
+                for (int i = 0; i < diff; i++) {
+                    sb.append(' ');
+                }
+            }
+            return sb.toString();
+        } else {
+            return s;
+        }
+    }
+
+    public static Map parseArgs(final String[] cargs) {
+        Map args = new TreeMap();
+        Map ARGS_MATCH = Ping.ARGS_MATCH;
+
+        int l = cargs.length;
+        final String[] EMPTY_VALUES = {""};
+        for (int i = 0; i < l; i++) {
+            String k = cargs[i];
+            Ping.Arg a = (Ping.Arg) ARGS_MATCH.get(k);
+            if (l > i + 1) {
+                String v = cargs[++i];
+                while (ARGS_MATCH.containsKey(v)) {
+                    args.put(a, EMPTY_VALUES);
+                    a = (Ping.Arg) ARGS_MATCH.get(v);
+                    v = "";
+                    if (l > i + 1) {
+                        v = cargs[++i];
+                    }
+                }
+                String[] values = new String[1];
+                values[0] = v;
+                args.put(a, values);
+                if (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
+                    LinkedList list = new LinkedList();
+                    list.add(v);
+                    while (l > i + 1 && !ARGS_MATCH.containsKey(cargs[i + 1])) {
+                        v = cargs[++i];
+                        list.add(v);
+                    }
+                    args.put(a, list.toArray(new String[list.size()]));
+                }
+            } else {
+                args.put(a, EMPTY_VALUES);
+            }
+        }
+        return args;
+    }
+
+    public static String readLine(final InputStream in) throws IOException {
+        StringBuffer buf = new StringBuffer(64);
+        int b = in.read();
+        while (b != -1) {
+            char c = (char) b;
+            if (c == '\n' || c == '\r') {
+                if (buf.length() >= 1) {
+                    return buf.toString();
+                }
+            } else {
+                buf.append(c);
+            }
+            b = in.read();
+        }
+        return buf.length() >= 1 ? buf.toString() : null;
+    }
+
+    public static String readLine(final ByteArrayInputStream in) {
+        StringBuffer buf = new StringBuffer(64);
+        int b = in.read();
+        while (b != -1) {
+            char c = (char) b;
+            if (c == '\n' || c == '\r') {
+                if (buf.length() >= 1) {
+                    return buf.toString();
+                }
+            } else {
+                buf.append(c);
+            }
+            b = in.read();
+        }
+        return buf.length() >= 1 ? buf.toString() : null;
+    }
+
+    public static HostPort toAddress(final String target,
+                                     final int defaultPort)
+        throws UnknownHostException {
+        String host = target;
+        int port = defaultPort;
+        StringTokenizer st = new StringTokenizer(target, ":");
+        if (st.hasMoreTokens()) {
+            host = st.nextToken().trim();
+        }
+        if (st.hasMoreTokens()) {
+            port = Integer.parseInt(st.nextToken().trim());
+        }
+        if (st.hasMoreTokens()) {
+            throw new IllegalArgumentException("Invalid host: " + target);
+        }
+        return new HostPort(host, port);
+    }
+
+    public static String cipherToAuthType(String cipher) {
+        if (cipher == null) {
+            return null;
+        }
+
+        // SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA  ==> "DHE_DSS_EXPORT"
+        // SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA      ==> "DHE_DSS"
+        // SSL_RSA_WITH_3DES_EDE_CBC_SHA          ==> "RSA"
+
+        StringTokenizer st = new StringTokenizer(cipher.trim(), "_");
+        if (st.hasMoreTokens()) {
+            st.nextToken();  // always skip first token
+        }
+        if (st.hasMoreTokens()) {
+            String tok = st.nextToken();
+            StringBuffer buf = new StringBuffer();
+            buf.append(tok);
+            if (st.hasMoreTokens()) {
+                tok = st.nextToken();
+                while (!"WITH".equalsIgnoreCase(tok)) {
+                    buf.append('_');
+                    buf.append(tok);
+                    tok = st.nextToken();
+                }
+            }
+            return buf.toString();
+        }
+        throw new IllegalArgumentException("not a valid cipher: " + cipher);
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        String s = "line1\n\rline2\n\rline3";
+        InputStream in = new ByteArrayInputStream(s.getBytes());
+        String line = readLine(in);
+        while (line != null) {
+            System.out.println(line);
+            line = readLine(in);
+        }
+
+        System.out.println("--------- test 2 ----------");
+
+        s = "line1\n\rline2\n\rline3\n\r\n\r";
+        in = new ByteArrayInputStream(s.getBytes());
+        line = readLine(in);
+        while (line != null) {
+            System.out.println(line);
+            line = readLine(in);
+        }
+
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/Version.java b/src/java/org/apache/commons/ssl/Version.java
new file mode 100644
index 0000000..0cb3d2e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/Version.java
@@ -0,0 +1,197 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Version.java $
+ * $Revision: 130 $
+ * $Date: 2007-11-14 19:24:15 -0800 (Wed, 14 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Extracts tagged version from a subversion $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Version.java $ property, and prints it
+ * out nicely on standard out.
+ * <p/>
+ * e.g. If this version came from /tags/commons-ssl-0_3_9/, then Version.java
+ * will print:  "Version: 0.3.9" on standard out.
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 14-Nov-2007
+ */
+public class Version {
+    public static final String HEAD_URL = "$HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/Version.java $";
+    public static final String VERSION;
+    public static final String COMPILE_TIME;
+
+    static {
+        // Try to extract a clean version number from svn's HeadURL property:
+        String v = "UNKNOWN";
+        boolean fromBranch = false;
+        int x = HEAD_URL.lastIndexOf("/tags/");
+        if (x >= 0) {
+            int y = HEAD_URL.indexOf("/", x + "/tags/".length());
+            if (y >= 0) {
+                v = HEAD_URL.substring(x + "/tags/".length(), y);
+            }
+            v = v.replace('_', '.');
+            v = v.replace('-', '.');
+        } else if (HEAD_URL.indexOf("/trunk/") >= 0) {
+            v = "trunk";
+        } else if (HEAD_URL.indexOf("/branches/") >= 0) {
+            fromBranch = true;
+            x = HEAD_URL.indexOf("/branches/");
+            int y = HEAD_URL.indexOf("/", x + "/branches/".length());
+            if (y >= 0) {
+                v = HEAD_URL.substring(x + "/branches/".length(), y);
+            }
+            v = v.replace('_', '.');
+            v = v.replace('-', '.');
+        }
+
+        String V = v.toUpperCase();
+        x = V.indexOf("COMMONS.SSL.");
+        if (x >= 0) {
+            v = v.substring(x + "commons.ssl.".length());
+        }
+        VERSION = fromBranch ? "***Branch*** " + v : v;
+
+        // Try to calculate when jar file was compiled:
+        String s;
+        try {
+            s = CompileTime.getCompileTimeString(Version.class);
+        }
+        catch (NoClassDefFoundError e) {
+            s = null;
+        }
+        COMPILE_TIME = s;
+    }
+
+    public static String versionString() {
+        String v;
+        if (COMPILE_TIME != null) {
+            v = CompileTime.formatVersion(VERSION, COMPILE_TIME);
+        } else {
+            v = VERSION;
+        }
+        return "Version: " + v;
+    }
+
+    public static void main(String[] args) {
+        System.out.println(versionString());
+    }
+
+    public String toString() {
+        return versionString();
+    }
+
+
+    /**
+     * Searches through a jar file to the find the most recent timestamp of
+     * all the class files.
+     */
+    private static class CompileTime {
+        private final static String PATTERN = ".jar!";
+        private final static String PREFIX = "file:";
+        private final static String DF_FORMAT = "zzz:yyyy-MM-dd/HH:mm:ss.SSS";
+        private final static DateFormat DF = new SimpleDateFormat(DF_FORMAT);
+
+        public static String getCompileTimeString(Class clazz) {
+            String s = clazz.getName();
+            s = "/" + s.replace('.', '/') + ".class";
+            return getCompileTimeString(s);
+        }
+
+        private static String getCompileTimeString(String resource) {
+            try {
+                Date d = getCompileTime(resource);
+                return d != null ? DF.format(d) : "[unknown]";
+            }
+            catch (IOException ioe) {
+                return ioe.toString();
+            }
+        }
+
+        public static Date getCompileTime(String resource) throws IOException {
+            URL url = CompileTime.class.getResource(resource);
+            if (url != null) {
+                String urlString = url.getFile();
+                String fileLocation;
+                int i = urlString.indexOf(PATTERN);
+                if (i > 0) {
+                    int x = i + PATTERN.length() - 1;
+                    fileLocation = urlString.substring(0, x);
+                    if (fileLocation.startsWith(PREFIX)) {
+                        fileLocation = fileLocation.substring(PREFIX.length());
+                    }
+                    JarFile jf = new JarFile(fileLocation);
+                    long newestTime = 0;
+                    Enumeration entries = jf.entries();
+                    while (entries.hasMoreElements()) {
+                        JarEntry entry = (JarEntry) entries.nextElement();
+                        if (entry.getName().endsWith(".class")) {
+                            newestTime = Math.max(newestTime, entry.getTime());
+                        }
+                    }
+                    if (newestTime > 0) {
+                        return new Date(newestTime);
+                    }
+                } else {
+                    File f = new File(urlString);
+                    try {
+                        return new Date(f.lastModified());
+                    }
+                    catch (Exception e) {
+                        return null;
+                    }
+                }
+            }
+            return null;
+        }
+
+        public static String formatVersion(String version, String compileTime) {
+            StringBuffer buf = new StringBuffer();
+            buf.append(version);
+            buf.append("   Compiled: [");
+            buf.append(compileTime);
+            buf.append("]");
+            return buf.toString();
+        }
+
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/X509CertificateChainBuilder.java b/src/java/org/apache/commons/ssl/X509CertificateChainBuilder.java
new file mode 100644
index 0000000..204bf3a
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/X509CertificateChainBuilder.java
@@ -0,0 +1,181 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/X509CertificateChainBuilder.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl;
+
+import java.io.FileInputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * Utility for building X509 certificate chains.
+ *
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 16-Nov-2005
+ */
+public class X509CertificateChainBuilder {
+    /**
+     * Builds the ordered certificate chain upwards from the startingPoint.
+     * Uses the supplied X509Certificate[] array to search for the parent,
+     * grandparent, and higher ancestor certificates.  Stops at self-signed
+     * certificates, or when no ancestor can be found.
+     * <p/>
+     * Thanks to Joe Whitney for helping me put together a Big-O( m * n )
+     * implementation where m = the length of the final certificate chain.
+     * For a while I was using a Big-O( n ^ 2 ) implementation!
+     *
+     * @param startingPoint the X509Certificate for which we want to find
+     *                      ancestors
+     * @param certificates  A pool of certificates in which we expect to find
+     *                      the startingPoint's ancestors.
+     * @return Array of X509Certificates, starting with the "startingPoint" and
+     *         ending with highest level ancestor we could find in the supplied
+     *         collection.
+     * @throws java.security.NoSuchAlgorithmException
+     *          on unsupported signature
+     *          algorithms.
+     * @throws java.security.InvalidKeyException
+     *          on incorrect key.
+     * @throws java.security.NoSuchProviderException
+     *          if there's no default provider.
+     * @throws java.security.cert.CertificateException
+     *          on encoding errors.
+     */
+    public static X509Certificate[] buildPath(X509Certificate startingPoint,
+                                              Certificate[] certificates)
+        throws NoSuchAlgorithmException, InvalidKeyException,
+        NoSuchProviderException, CertificateException {
+        // Use a LinkedList, because we do lots of random it.remove() operations.
+        return buildPath(startingPoint,
+            new LinkedList(Arrays.asList(certificates)));
+    }
+
+    /**
+     * Builds the ordered certificate chain upwards from the startingPoint.
+     * Uses the supplied collection to search for the parent, grandparent,
+     * and higher ancestor certificates.  Stops at self-signed certificates,
+     * or when no ancestor can be found.
+     * <p/>
+     * Thanks to Joe Whitney for helping me put together a Big-O( m * n )
+     * implementation where m = the length of the final certificate chain.
+     * For a while I was using a Big-O( n ^ 2 ) implementation!
+     *
+     * @param startingPoint the X509Certificate for which we want to find
+     *                      ancestors
+     * @param certificates  A pool of certificates in which we expect to find
+     *                      the startingPoint's ancestors.
+     * @return Array of X509Certificates, starting with the "startingPoint" and
+     *         ending with highest level ancestor we could find in the supplied
+     *         collection.
+     * @throws java.security.NoSuchAlgorithmException
+     *          on unsupported signature
+     *          algorithms.
+     * @throws java.security.InvalidKeyException
+     *          on incorrect key.
+     * @throws java.security.NoSuchProviderException
+     *          if there's no default provider.
+     * @throws java.security.cert.CertificateException
+     *          on encoding errors.
+     */
+    public static X509Certificate[] buildPath(X509Certificate startingPoint,
+                                              Collection certificates)
+        throws NoSuchAlgorithmException, InvalidKeyException,
+        NoSuchProviderException, CertificateException {
+        LinkedList path = new LinkedList();
+        path.add(startingPoint);
+        boolean nodeAdded = true;
+        // Keep looping until an iteration happens where we don't add any nodes
+        // to our path.
+        while (nodeAdded) {
+            // We'll start out by assuming nothing gets added.  If something
+            // gets added, then nodeAdded will be changed to "true".
+            nodeAdded = false;
+            X509Certificate top = (X509Certificate) path.getLast();
+            try {
+                top.verify(top.getPublicKey());
+                // We're self-signed, so we're done!
+                break;
+            }
+            catch (SignatureException se) {
+                // Not self-signed.  Let's see if we're signed by anyone in the
+                // collection.
+                Iterator it = certificates.iterator();
+                while (it.hasNext()) {
+                    X509Certificate x509 = (X509Certificate) it.next();
+                    try {
+                        top.verify(x509.getPublicKey());
+                        // No exception thrown, so we're signed by this guy!
+                        path.add(x509);
+                        nodeAdded = true;
+                        it.remove(); // Not interested in this guy anymore!
+                        break;
+                    }
+                    catch (SignatureException se2) {
+                        // Not signed by this guy, let's try the next guy.
+                    }
+                }
+            }
+        }
+
+        X509Certificate[] results = new X509Certificate[path.size()];
+        path.toArray(results);
+        return results;
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (args.length < 2) {
+            System.out.println("Usage: [special-one] [file-with-certs]");
+            System.exit(1);
+        }
+        FileInputStream f1 = new FileInputStream(args[0]);
+        FileInputStream f2 = new FileInputStream(args[1]);
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        X509Certificate theOne = (X509Certificate) cf.generateCertificate(f1);
+        Collection c = cf.generateCertificates(f2);
+
+        X509Certificate[] path = buildPath(theOne, c);
+        for (int i = 0; i < path.length; i++) {
+            System.out.println(Certificates.getCN(path[i]));
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Choice.java b/src/java/org/apache/commons/ssl/asn1/ASN1Choice.java
new file mode 100644
index 0000000..c08485e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Choice.java
@@ -0,0 +1,13 @@
+package org.apache.commons.ssl.asn1;
+
+/**
+ * Marker interface for CHOICE objects - if you implement this in a role your
+ * own object any attempt to tag the object implicitly will convert the tag to
+ * an explicit one as the encoding rules require.
+ * <p/>
+ * If you use this interface your class should also implement the getInstance
+ * pattern which takes a tag object and the tagging mode used.
+ */
+public interface ASN1Choice {
+    // marker interface
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Encodable.java b/src/java/org/apache/commons/ssl/asn1/ASN1Encodable.java
new file mode 100644
index 0000000..99900cb
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Encodable.java
@@ -0,0 +1,74 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public abstract class ASN1Encodable
+    implements DEREncodable {
+    public static final String DER = "DER";
+    public static final String BER = "BER";
+
+    public byte[] getEncoded()
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+        aOut.writeObject(this);
+
+        return bOut.toByteArray();
+    }
+
+    public byte[] getEncoded(
+        String encoding)
+        throws IOException {
+        if (encoding.equals(DER)) {
+            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+            DEROutputStream dOut = new DEROutputStream(bOut);
+
+            dOut.writeObject(this);
+
+            return bOut.toByteArray();
+        }
+
+        return this.getEncoded();
+    }
+
+    /**
+     * Return the DER encoding of the object, null if the DER encoding can not be made.
+     *
+     * @return a DER byte array, null otherwise.
+     */
+    public byte[] getDEREncoded() {
+        try {
+            return this.getEncoded(DER);
+        }
+        catch (IOException e) {
+            return null;
+        }
+    }
+
+    public int hashCode() {
+        return this.toASN1Object().hashCode();
+    }
+
+    public boolean equals(
+        Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof DEREncodable)) {
+            return false;
+        }
+
+        DEREncodable other = (DEREncodable) o;
+
+        return this.toASN1Object().equals(other.getDERObject());
+    }
+
+    public DERObject getDERObject() {
+        return this.toASN1Object();
+    }
+
+    public abstract DERObject toASN1Object();
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1EncodableVector.java b/src/java/org/apache/commons/ssl/asn1/ASN1EncodableVector.java
new file mode 100644
index 0000000..b769758
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1EncodableVector.java
@@ -0,0 +1,10 @@
+package org.apache.commons.ssl.asn1;
+
+/** the parent class for this will eventually disappear. Use this one! */
+public class ASN1EncodableVector
+    extends DEREncodableVector {
+    // migrating from DEREncodeableVector
+    public ASN1EncodableVector() {
+
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Generator.java b/src/java/org/apache/commons/ssl/asn1/ASN1Generator.java
new file mode 100644
index 0000000..b39d994
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Generator.java
@@ -0,0 +1,13 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.OutputStream;
+
+public abstract class ASN1Generator {
+    protected OutputStream _out;
+
+    public ASN1Generator(OutputStream out) {
+        _out = out;
+    }
+
+    public abstract OutputStream getRawOutputStream();
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1InputStream.java b/src/java/org/apache/commons/ssl/asn1/ASN1InputStream.java
new file mode 100644
index 0000000..e68c231
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1InputStream.java
@@ -0,0 +1,420 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Vector;
+
+/**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
+ * returned.
+ */
+public class ASN1InputStream
+    extends FilterInputStream
+    implements DERTags {
+    private static final DERObject END_OF_STREAM = new DERObject() {
+        void encode(
+            DEROutputStream out)
+            throws IOException {
+            throw new IOException("Eeek!");
+        }
+        public int hashCode() {
+            return 0;
+        }
+        public boolean equals(
+            Object o) {
+            return o == this;
+        }
+    };
+
+    boolean eofFound = false;
+    int limit = Integer.MAX_VALUE;
+
+    public ASN1InputStream(
+        InputStream is) {
+        super(is);
+    }
+
+    /**
+     * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+     * the stream is automatically limited to the length of the input array.
+     *
+     * @param input array containing ASN.1 encoded data.
+     */
+    public ASN1InputStream(
+        byte[] input) {
+        this(new ByteArrayInputStream(input), input.length);
+    }
+
+    /**
+     * Create an ASN1InputStream where no DER object will be longer than limit.
+     *
+     * @param input stream containing ASN.1 encoded data.
+     * @param limit maximum size of a DER encoded object.
+     */
+    public ASN1InputStream(
+        InputStream input,
+        int limit) {
+        super(input);
+        this.limit = limit;
+    }
+
+    protected int readLength()
+        throws IOException {
+        int length = read();
+        if (length < 0) {
+            throw new IOException("EOF found when length expected");
+        }
+
+        if (length == 0x80) {
+            return -1;      // indefinite-length encoding
+        }
+
+        if (length > 127) {
+            int size = length & 0x7f;
+
+            if (size > 4) {
+                throw new IOException("DER length more than 4 bytes");
+            }
+
+            length = 0;
+            for (int i = 0; i < size; i++) {
+                int next = read();
+
+                if (next < 0) {
+                    throw new IOException("EOF found reading length");
+                }
+
+                length = (length << 8) + next;
+            }
+
+            if (length < 0) {
+                throw new IOException("corrupted stream - negative length found");
+            }
+
+            if (length >= limit)   // after all we must have read at least 1 byte
+            {
+                throw new IOException("corrupted stream - out of bounds length found");
+            }
+        }
+
+        return length;
+    }
+
+    protected void readFully(
+        byte[] bytes)
+        throws IOException {
+        int left = bytes.length;
+        int len;
+
+        if (left == 0) {
+            return;
+        }
+
+        while ((len = read(bytes, bytes.length - left, left)) > 0) {
+            if ((left -= len) == 0) {
+                return;
+            }
+        }
+
+        if (left != 0) {
+            throw new EOFException("EOF encountered in middle of object");
+        }
+    }
+
+    /** build an object given its tag and the number of bytes to construct it from. */
+    protected DERObject buildObject(
+        int tag,
+        int tagNo,
+        int length)
+        throws IOException {
+        if ((tag & APPLICATION) != 0) {
+            return new DERApplicationSpecific(tagNo, readDefiniteLengthFully(length));
+        }
+
+        boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+        if (isConstructed) {
+            switch (tag) {
+                case SEQUENCE | CONSTRUCTED:
+                    return new DERSequence(buildDerEncodableVector(length));
+                case SET | CONSTRUCTED:
+                    return new DERSet(buildDerEncodableVector(length), false);
+                case OCTET_STRING | CONSTRUCTED:
+                    return buildDerConstructedOctetString(length);
+                default: {
+                    //
+                    // with tagged object tag number is bottom 5 bits
+                    //
+                    if ((tag & TAGGED) != 0) {
+                        if (length == 0)     // empty tag!
+                        {
+                            return new DERTaggedObject(false, tagNo, new DERSequence());
+                        }
+
+                        ASN1EncodableVector v = buildDerEncodableVector(length);
+
+                        if (v.size() == 1) {
+                            //
+                            // explicitly tagged (probably!) - if it isn't we'd have to
+                            // tell from the context
+                            //
+                            return new DERTaggedObject(tagNo, v.get(0));
+                        }
+
+                        return new DERTaggedObject(false, tagNo, new DERSequence(v));
+                    }
+
+                    return new DERUnknownTag(tag, readDefiniteLengthFully(length));
+                }
+            }
+        }
+
+        byte[] bytes = readDefiniteLengthFully(length);
+
+        switch (tag) {
+            case NULL:
+                return DERNull.INSTANCE;
+            case BOOLEAN:
+                return new DERBoolean(bytes);
+            case INTEGER:
+                return new DERInteger(bytes);
+            case ENUMERATED:
+                return new DEREnumerated(bytes);
+            case OBJECT_IDENTIFIER:
+                return new DERObjectIdentifier(bytes);
+            case BIT_STRING: {
+                int padBits = bytes[0];
+                byte[] data = new byte[bytes.length - 1];
+
+                System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+
+                return new DERBitString(data, padBits);
+            }
+            case NUMERIC_STRING:
+                return new DERNumericString(bytes);
+            case UTF8_STRING:
+                return new DERUTF8String(bytes);
+            case PRINTABLE_STRING:
+                return new DERPrintableString(bytes);
+            case IA5_STRING:
+                return new DERIA5String(bytes);
+            case T61_STRING:
+                return new DERT61String(bytes);
+            case VISIBLE_STRING:
+                return new DERVisibleString(bytes);
+            case GENERAL_STRING:
+                return new DERGeneralString(bytes);
+            case UNIVERSAL_STRING:
+                return new DERUniversalString(bytes);
+            case BMP_STRING:
+                return new DERBMPString(bytes);
+            case OCTET_STRING:
+                return new DEROctetString(bytes);
+            case UTC_TIME:
+                return new DERUTCTime(bytes);
+            case GENERALIZED_TIME:
+                return new DERGeneralizedTime(bytes);
+            default: {
+                //
+                // with tagged object tag number is bottom 5 bits
+                //
+                if ((tag & TAGGED) != 0) {
+                    if (bytes.length == 0)     // empty tag!
+                    {
+                        return new DERTaggedObject(false, tagNo, DERNull.INSTANCE);
+                    }
+
+                    //
+                    // simple type - implicit... return an octet string
+                    //
+                    return new DERTaggedObject(false, tagNo, new DEROctetString(bytes));
+                }
+
+                return new DERUnknownTag(tag, bytes);
+            }
+        }
+    }
+
+    private byte[] readDefiniteLengthFully(int length)
+        throws IOException {
+        byte[] bytes = new byte[length];
+        readFully(bytes);
+        return bytes;
+    }
+
+    /** read a string of bytes representing an indefinite length object. */
+    private byte[] readIndefiniteLengthFully()
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        int b, b1;
+
+        b1 = read();
+
+        while ((b = read()) >= 0) {
+            if (b1 == 0 && b == 0) {
+                break;
+            }
+
+            bOut.write(b1);
+            b1 = b;
+        }
+
+        return bOut.toByteArray();
+    }
+
+    private BERConstructedOctetString buildConstructedOctetString(DERObject sentinel)
+        throws IOException {
+        Vector octs = new Vector();
+        DERObject o;
+
+        while ((o = readObject()) != sentinel) {
+            octs.addElement(o);
+        }
+
+        return new BERConstructedOctetString(octs);
+    }
+
+    //
+    // yes, people actually do this...
+    //
+    private BERConstructedOctetString buildDerConstructedOctetString(int length)
+        throws IOException {
+        DefiniteLengthInputStream dIn = new DefiniteLengthInputStream(this, length);
+        ASN1InputStream aIn = new ASN1InputStream(dIn, length);
+
+        return aIn.buildConstructedOctetString(null);
+    }
+
+    private ASN1EncodableVector buildEncodableVector(DERObject sentinel)
+        throws IOException {
+        ASN1EncodableVector v = new ASN1EncodableVector();
+        DERObject o;
+
+        while ((o = readObject()) != sentinel) {
+            v.add(o);
+        }
+
+        return v;
+    }
+
+    private ASN1EncodableVector buildDerEncodableVector(int length)
+        throws IOException {
+        DefiniteLengthInputStream dIn = new DefiniteLengthInputStream(this, length);
+        ASN1InputStream aIn = new ASN1InputStream(dIn, length);
+
+        return aIn.buildEncodableVector(null);
+    }
+
+    public DERObject readObject()
+        throws IOException {
+        int tag = read();
+        if (tag == -1) {
+            if (eofFound) {
+                throw new EOFException("attempt to read past end of file.");
+            }
+
+            eofFound = true;
+
+            return null;
+        }
+
+        int tagNo = 0;
+
+        if ((tag & TAGGED) != 0 || (tag & APPLICATION) != 0) {
+            tagNo = readTagNumber(tag);
+        }
+
+        int length = readLength();
+
+        if (length < 0)    // indefinite length method
+        {
+            switch (tag) {
+                case NULL:
+                    return BERNull.INSTANCE;
+                case SEQUENCE | CONSTRUCTED:
+                    return new BERSequence(buildEncodableVector(END_OF_STREAM));
+                case SET | CONSTRUCTED:
+                    return new BERSet(buildEncodableVector(END_OF_STREAM), false);
+                case OCTET_STRING | CONSTRUCTED:
+                    return buildConstructedOctetString(END_OF_STREAM);
+                default: {
+                    //
+                    // with tagged object tag number is bottom 5 bits
+                    //
+                    if ((tag & TAGGED) != 0) {
+                        //
+                        // simple type - implicit... return an octet string
+                        //
+                        if ((tag & CONSTRUCTED) == 0) {
+                            byte[] bytes = readIndefiniteLengthFully();
+
+                            return new BERTaggedObject(false, tagNo, new DEROctetString(bytes));
+                        }
+
+                        //
+                        // either constructed or explicitly tagged
+                        //
+                        ASN1EncodableVector v = buildEncodableVector(END_OF_STREAM);
+
+                        if (v.size() == 0)     // empty tag!
+                        {
+                            return new DERTaggedObject(tagNo);
+                        }
+
+                        if (v.size() == 1) {
+                            //
+                            // explicitly tagged (probably!) - if it isn't we'd have to
+                            // tell from the context
+                            //
+                            return new BERTaggedObject(tagNo, v.get(0));
+                        }
+
+                        return new BERTaggedObject(false, tagNo, new BERSequence(v));
+                    }
+
+                    throw new IOException("unknown BER object encountered");
+                }
+            }
+        } else {
+            if (tag == 0 && length == 0)    // end of contents marker.
+            {
+                return END_OF_STREAM;
+            }
+
+            return buildObject(tag, tagNo, length);
+        }
+    }
+
+    private int readTagNumber(int tag)
+        throws IOException {
+        int tagNo = tag & 0x1f;
+
+        if (tagNo == 0x1f) {
+            int b = read();
+
+            tagNo = 0;
+
+            while ((b >= 0) && ((b & 0x80) != 0)) {
+                tagNo |= (b & 0x7f);
+                tagNo <<= 7;
+                b = read();
+            }
+
+            if (b < 0) {
+                eofFound = true;
+                throw new EOFException("EOF found inside tag value.");
+            }
+
+            tagNo |= (b & 0x7f);
+        }
+
+        return tagNo;
+    }
+}
+
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Null.java b/src/java/org/apache/commons/ssl/asn1/ASN1Null.java
new file mode 100644
index 0000000..7f56bbd
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Null.java
@@ -0,0 +1,30 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** A NULL object. */
+public abstract class ASN1Null
+    extends ASN1Object {
+    public ASN1Null() {
+    }
+
+    public int hashCode() {
+        return 0;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof ASN1Null)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    abstract void encode(DEROutputStream out)
+        throws IOException;
+
+    public String toString() {
+        return "NULL";
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Object.java b/src/java/org/apache/commons/ssl/asn1/ASN1Object.java
new file mode 100644
index 0000000..02a3930
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Object.java
@@ -0,0 +1,34 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public abstract class ASN1Object
+    extends DERObject {
+    /**
+     * Create a base ASN.1 object from a byte stream.
+     *
+     * @param data the byte stream to parse.
+     * @return the base ASN.1 object represented by the byte stream.
+     * @throws IOException if there is a problem parsing the data.
+     */
+    public static ASN1Object fromByteArray(byte[] data)
+        throws IOException {
+        ASN1InputStream aIn = new ASN1InputStream(data);
+
+        return (ASN1Object) aIn.readObject();
+    }
+
+    public final boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        return (o instanceof DEREncodable) && asn1Equals(((DEREncodable) o).getDERObject());
+    }
+
+    public abstract int hashCode();
+
+    abstract void encode(DEROutputStream out) throws IOException;
+
+    abstract boolean asn1Equals(DERObject o);
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1ObjectParser.java b/src/java/org/apache/commons/ssl/asn1/ASN1ObjectParser.java
new file mode 100644
index 0000000..ca2a576
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1ObjectParser.java
@@ -0,0 +1,55 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ASN1ObjectParser {
+    private int _baseTag;
+    private int _tagNumber;
+
+    private ASN1StreamParser _aIn;
+
+    protected ASN1ObjectParser(
+        int baseTag,
+        int tagNumber,
+        InputStream contentStream) {
+        _baseTag = baseTag;
+        _tagNumber = tagNumber;
+        _aIn = new ASN1StreamParser(contentStream);
+    }
+
+    /**
+     * Return the tag number for this object.
+     *
+     * @return the tag number.
+     */
+    int getTagNumber() {
+        return _tagNumber;
+    }
+
+    int getBaseTag() {
+        return _baseTag;
+    }
+
+    DEREncodable readObject()
+        throws IOException {
+        return _aIn.readObject();
+    }
+
+    ASN1EncodableVector readVector()
+        throws IllegalStateException {
+        ASN1EncodableVector v = new ASN1EncodableVector();
+        DEREncodable obj;
+
+        try {
+            while ((obj = readObject()) != null) {
+                v.add(obj.getDERObject());
+            }
+        }
+        catch (IOException e) {
+            throw new IllegalStateException(e.getMessage());
+        }
+
+        return v;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1OctetString.java b/src/java/org/apache/commons/ssl/asn1/ASN1OctetString.java
new file mode 100644
index 0000000..10ab72e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1OctetString.java
@@ -0,0 +1,137 @@
+package org.apache.commons.ssl.asn1;
+
+import org.apache.commons.ssl.util.Hex;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class ASN1OctetString
+    extends ASN1Object
+    implements ASN1OctetStringParser {
+    byte[] string;
+
+    /**
+     * return an Octet String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want.
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static ASN1OctetString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /**
+     * return an Octet String from the given object.
+     *
+     * @param obj the object we want converted.
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static ASN1OctetString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof ASN1OctetString) {
+            return (ASN1OctetString) obj;
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        if (obj instanceof ASN1Sequence) {
+            Vector v = new Vector();
+            Enumeration e = ((ASN1Sequence) obj).getObjects();
+
+            while (e.hasMoreElements()) {
+                v.addElement(e.nextElement());
+            }
+
+            return new BERConstructedOctetString(v);
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /** @param string the octets making up the octet string. */
+    public ASN1OctetString(
+        byte[] string) {
+        this.string = string;
+    }
+
+    public ASN1OctetString(
+        DEREncodable obj) {
+        try {
+            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+            DEROutputStream dOut = new DEROutputStream(bOut);
+
+            dOut.writeObject(obj);
+            dOut.close();
+
+            this.string = bOut.toByteArray();
+        }
+        catch (IOException e) {
+            throw new IllegalArgumentException("Error processing object : " + e.toString());
+        }
+    }
+
+    public InputStream getOctetStream() {
+        return new ByteArrayInputStream(string);
+    }
+
+    public ASN1OctetStringParser parser() {
+        return this;
+    }
+
+    public byte[] getOctets() {
+        return string;
+    }
+
+    public int hashCode() {
+        byte[] b = this.getOctets();
+        int value = 0;
+
+        for (int i = 0; i != b.length; i++) {
+            value ^= (b[i] & 0xff) << (i % 4);
+        }
+
+        return value;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof ASN1OctetString)) {
+            return false;
+        }
+
+        ASN1OctetString other = (ASN1OctetString) o;
+
+        byte[] b1 = other.string;
+        byte[] b2 = this.string;
+
+        if (b1.length != b2.length) {
+            return false;
+        }
+
+        for (int i = 0; i != b1.length; i++) {
+            if (b1[i] != b2[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    abstract void encode(DEROutputStream out)
+        throws IOException;
+
+    public String toString() {
+        return "#" + Hex.encode(string);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1OctetStringParser.java b/src/java/org/apache/commons/ssl/asn1/ASN1OctetStringParser.java
new file mode 100644
index 0000000..b958534
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1OctetStringParser.java
@@ -0,0 +1,8 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.InputStream;
+
+public interface ASN1OctetStringParser
+    extends DEREncodable {
+    public InputStream getOctetStream();
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1OutputStream.java b/src/java/org/apache/commons/ssl/asn1/ASN1OutputStream.java
new file mode 100644
index 0000000..2cac08d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1OutputStream.java
@@ -0,0 +1,26 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class ASN1OutputStream
+    extends DEROutputStream {
+    public ASN1OutputStream(
+        OutputStream os) {
+        super(os);
+    }
+
+    public void writeObject(
+        Object obj)
+        throws IOException {
+        if (obj == null) {
+            writeNull();
+        } else if (obj instanceof DERObject) {
+            ((DERObject) obj).encode(this);
+        } else if (obj instanceof DEREncodable) {
+            ((DEREncodable) obj).getDERObject().encode(this);
+        } else {
+            throw new IOException("object not ASN1Encodable");
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Sequence.java b/src/java/org/apache/commons/ssl/asn1/ASN1Sequence.java
new file mode 100644
index 0000000..699edd1
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Sequence.java
@@ -0,0 +1,183 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class ASN1Sequence
+    extends ASN1Object {
+    private Vector seq = new Vector();
+
+    /**
+     * return an ASN1Sequence from the given object.
+     *
+     * @param obj the object we want converted.
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static ASN1Sequence getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof ASN1Sequence) {
+            return (ASN1Sequence) obj;
+        }
+
+        throw new IllegalArgumentException("unknown object in getInstance");
+    }
+
+    /**
+     * Return an ASN1 sequence from a tagged object. There is a special
+     * case here, if an object appears to have been explicitly tagged on
+     * reading but we were expecting it to be implictly tagged in the
+     * normal course of events it indicates that we lost the surrounding
+     * sequence - so we need to add it back (this will happen if the tagged
+     * object is a sequence that contains other sequences). If you are
+     * dealing with implicitly tagged sequences you really <b>should</b>
+     * be using this method.
+     *
+     * @param obj      the tagged object.
+     * @param explicit true if the object is meant to be explicitly tagged,
+     *                 false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static ASN1Sequence getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        if (explicit) {
+            if (!obj.isExplicit()) {
+                throw new IllegalArgumentException("object implicit - explicit expected.");
+            }
+
+            return (ASN1Sequence) obj.getObject();
+        } else {
+            //
+            // constructed object which appears to be explicitly tagged
+            // when it should be implicit means we have to add the
+            // surrounding sequence.
+            //
+            if (obj.isExplicit()) {
+                if (obj instanceof BERTaggedObject) {
+                    return new BERSequence(obj.getObject());
+                } else {
+                    return new DERSequence(obj.getObject());
+                }
+            } else {
+                if (obj.getObject() instanceof ASN1Sequence) {
+                    return (ASN1Sequence) obj.getObject();
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(
+            "unknown object in getInstanceFromTagged");
+    }
+
+    public Enumeration getObjects() {
+        return seq.elements();
+    }
+
+    public ASN1SequenceParser parser() {
+        final ASN1Sequence outer = this;
+
+        return new ASN1SequenceParser() {
+            private final int max = size();
+
+            private int index;
+
+            public DEREncodable readObject() throws IOException {
+                if (index == max) {
+                    return null;
+                }
+
+                DEREncodable obj = getObjectAt(index++);
+                if (obj instanceof ASN1Sequence) {
+                    return ((ASN1Sequence) obj).parser();
+                }
+                if (obj instanceof ASN1Set) {
+                    return ((ASN1Set) obj).parser();
+                }
+
+                return obj;
+            }
+
+            public DERObject getDERObject() {
+                return outer;
+            }
+        };
+    }
+
+    /**
+     * return the object at the sequence postion indicated by index.
+     *
+     * @param index the sequence number (starting at zero) of the object
+     * @return the object at the sequence postion indicated by index.
+     */
+    public DEREncodable getObjectAt(
+        int index) {
+        return (DEREncodable) seq.elementAt(index);
+    }
+
+    /**
+     * return the number of objects in this sequence.
+     *
+     * @return the number of objects in this sequence.
+     */
+    public int size() {
+        return seq.size();
+    }
+
+    public int hashCode() {
+        Enumeration e = this.getObjects();
+        int hashCode = 0;
+
+        while (e.hasMoreElements()) {
+            Object o = e.nextElement();
+
+            if (o != null) {
+                hashCode ^= o.hashCode();
+            }
+        }
+
+        return hashCode;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof ASN1Sequence)) {
+            return false;
+        }
+
+        ASN1Sequence other = (ASN1Sequence) o;
+
+        if (this.size() != other.size()) {
+            return false;
+        }
+
+        Enumeration s1 = this.getObjects();
+        Enumeration s2 = other.getObjects();
+
+        while (s1.hasMoreElements()) {
+            DERObject o1 = ((DEREncodable) s1.nextElement()).getDERObject();
+            DERObject o2 = ((DEREncodable) s2.nextElement()).getDERObject();
+
+            if (o1 == o2 || (o1 != null && o1.equals(o2))) {
+                continue;
+            }
+
+            return false;
+        }
+
+        return true;
+    }
+
+    protected void addObject(
+        DEREncodable obj) {
+        seq.addElement(obj);
+    }
+
+    abstract void encode(DEROutputStream out)
+        throws IOException;
+
+    public String toString() {
+        return seq.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1SequenceParser.java b/src/java/org/apache/commons/ssl/asn1/ASN1SequenceParser.java
new file mode 100644
index 0000000..c64c93e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1SequenceParser.java
@@ -0,0 +1,9 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public interface ASN1SequenceParser
+    extends DEREncodable {
+    DEREncodable readObject()
+        throws IOException;
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1Set.java b/src/java/org/apache/commons/ssl/asn1/ASN1Set.java
new file mode 100644
index 0000000..549fc57
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1Set.java
@@ -0,0 +1,281 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+abstract public class ASN1Set
+    extends ASN1Object {
+    protected Vector set = new Vector();
+
+    /**
+     * return an ASN1Set from the given object.
+     *
+     * @param obj the object we want converted.
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static ASN1Set getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof ASN1Set) {
+            return (ASN1Set) obj;
+        }
+
+        throw new IllegalArgumentException("unknown object in getInstance");
+    }
+
+    /**
+     * Return an ASN1 set from a tagged object. There is a special
+     * case here, if an object appears to have been explicitly tagged on
+     * reading but we were expecting it to be implictly tagged in the
+     * normal course of events it indicates that we lost the surrounding
+     * set - so we need to add it back (this will happen if the tagged
+     * object is a sequence that contains other sequences). If you are
+     * dealing with implicitly tagged sets you really <b>should</b>
+     * be using this method.
+     *
+     * @param obj      the tagged object.
+     * @param explicit true if the object is meant to be explicitly tagged
+     *                 false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static ASN1Set getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        if (explicit) {
+            if (!obj.isExplicit()) {
+                throw new IllegalArgumentException("object implicit - explicit expected.");
+            }
+
+            return (ASN1Set) obj.getObject();
+        } else {
+            //
+            // constructed object which appears to be explicitly tagged
+            // and it's really implicit means we have to add the
+            // surrounding sequence.
+            //
+            if (obj.isExplicit()) {
+                ASN1Set set = new DERSet(obj.getObject());
+
+                return set;
+            } else {
+                if (obj.getObject() instanceof ASN1Set) {
+                    return (ASN1Set) obj.getObject();
+                }
+
+                //
+                // in this case the parser returns a sequence, convert it
+                // into a set.
+                //
+                ASN1EncodableVector v = new ASN1EncodableVector();
+
+                if (obj.getObject() instanceof ASN1Sequence) {
+                    ASN1Sequence s = (ASN1Sequence) obj.getObject();
+                    Enumeration e = s.getObjects();
+
+                    while (e.hasMoreElements()) {
+                        v.add((DEREncodable) e.nextElement());
+                    }
+
+                    return new DERSet(v, false);
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(
+            "unknown object in getInstanceFromTagged");
+    }
+
+    public ASN1Set() {
+    }
+
+    public Enumeration getObjects() {
+        return set.elements();
+    }
+
+    /**
+     * return the object at the set postion indicated by index.
+     *
+     * @param index the set number (starting at zero) of the object
+     * @return the object at the set postion indicated by index.
+     */
+    public DEREncodable getObjectAt(
+        int index) {
+        return (DEREncodable) set.elementAt(index);
+    }
+
+    /**
+     * return the number of objects in this set.
+     *
+     * @return the number of objects in this set.
+     */
+    public int size() {
+        return set.size();
+    }
+
+    public ASN1SetParser parser() {
+        final ASN1Set outer = this;
+
+        return new ASN1SetParser() {
+            private final int max = size();
+
+            private int index;
+
+            public DEREncodable readObject() throws IOException {
+                if (index == max) {
+                    return null;
+                }
+
+                DEREncodable obj = getObjectAt(index++);
+                if (obj instanceof ASN1Sequence) {
+                    return ((ASN1Sequence) obj).parser();
+                }
+                if (obj instanceof ASN1Set) {
+                    return ((ASN1Set) obj).parser();
+                }
+
+                return obj;
+            }
+
+            public DERObject getDERObject() {
+                return outer;
+            }
+        };
+    }
+
+    public int hashCode() {
+        Enumeration e = this.getObjects();
+        int hashCode = 0;
+
+        while (e.hasMoreElements()) {
+            hashCode ^= e.nextElement().hashCode();
+        }
+
+        return hashCode;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof ASN1Set)) {
+            return false;
+        }
+
+        ASN1Set other = (ASN1Set) o;
+
+        if (this.size() != other.size()) {
+            return false;
+        }
+
+        Enumeration s1 = this.getObjects();
+        Enumeration s2 = other.getObjects();
+
+        while (s1.hasMoreElements()) {
+            DERObject o1 = ((DEREncodable) s1.nextElement()).getDERObject();
+            DERObject o2 = ((DEREncodable) s2.nextElement()).getDERObject();
+
+            if (o1 == o2 || (o1 != null && o1.equals(o2))) {
+                continue;
+            }
+
+            return false;
+        }
+
+        return true;
+    }
+
+    /** return true if a <= b (arrays are assumed padded with zeros). */
+    private boolean lessThanOrEqual(
+        byte[] a,
+        byte[] b) {
+        if (a.length <= b.length) {
+            for (int i = 0; i != a.length; i++) {
+                int l = a[i] & 0xff;
+                int r = b[i] & 0xff;
+
+                if (r > l) {
+                    return true;
+                } else if (l > r) {
+                    return false;
+                }
+            }
+
+            return true;
+        } else {
+            for (int i = 0; i != b.length; i++) {
+                int l = a[i] & 0xff;
+                int r = b[i] & 0xff;
+
+                if (r > l) {
+                    return true;
+                } else if (l > r) {
+                    return false;
+                }
+            }
+
+            return false;
+        }
+    }
+
+    private byte[] getEncoded(
+        DEREncodable obj) {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+        try {
+            aOut.writeObject(obj);
+        }
+        catch (IOException e) {
+            throw new IllegalArgumentException("cannot encode object added to SET");
+        }
+
+        return bOut.toByteArray();
+    }
+
+    protected void sort() {
+        if (set.size() > 1) {
+            boolean swapped = true;
+            int lastSwap = set.size() - 1;
+
+            while (swapped) {
+                int index = 0;
+                int swapIndex = 0;
+                byte[] a = getEncoded((DEREncodable) set.elementAt(0));
+
+                swapped = false;
+
+                while (index != lastSwap) {
+                    byte[] b = getEncoded((DEREncodable) set.elementAt(index + 1));
+
+                    if (lessThanOrEqual(a, b)) {
+                        a = b;
+                    } else {
+                        Object o = set.elementAt(index);
+
+                        set.setElementAt(set.elementAt(index + 1), index);
+                        set.setElementAt(o, index + 1);
+
+                        swapped = true;
+                        swapIndex = index;
+                    }
+
+                    index++;
+                }
+
+                lastSwap = swapIndex;
+            }
+        }
+    }
+
+    protected void addObject(
+        DEREncodable obj) {
+        set.addElement(obj);
+    }
+
+    abstract void encode(DEROutputStream out)
+        throws IOException;
+
+    public String toString() {
+        return set.toString();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1SetParser.java b/src/java/org/apache/commons/ssl/asn1/ASN1SetParser.java
new file mode 100644
index 0000000..00ffbd0
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1SetParser.java
@@ -0,0 +1,9 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public interface ASN1SetParser
+    extends DEREncodable {
+    public DEREncodable readObject()
+        throws IOException;
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1StreamParser.java b/src/java/org/apache/commons/ssl/asn1/ASN1StreamParser.java
new file mode 100644
index 0000000..b1cd940
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1StreamParser.java
@@ -0,0 +1,193 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ASN1StreamParser {
+    InputStream _in;
+
+    private int _limit;
+    private boolean _eofFound;
+
+    public ASN1StreamParser(
+        InputStream in) {
+        this(in, Integer.MAX_VALUE);
+    }
+
+    public ASN1StreamParser(
+        InputStream in,
+        int limit) {
+        this._in = in;
+        this._limit = limit;
+    }
+
+    public ASN1StreamParser(
+        byte[] encoding) {
+        this(new ByteArrayInputStream(encoding), encoding.length);
+    }
+
+    InputStream getParentStream() {
+        return _in;
+    }
+
+    private int readLength()
+        throws IOException {
+        int length = _in.read();
+        if (length < 0) {
+            throw new EOFException("EOF found when length expected");
+        }
+
+        if (length == 0x80) {
+            return -1;      // indefinite-length encoding
+        }
+
+        if (length > 127) {
+            int size = length & 0x7f;
+
+            if (size > 4) {
+                throw new IOException("DER length more than 4 bytes");
+            }
+
+            length = 0;
+            for (int i = 0; i < size; i++) {
+                int next = _in.read();
+
+                if (next < 0) {
+                    throw new EOFException("EOF found reading length");
+                }
+
+                length = (length << 8) + next;
+            }
+
+            if (length < 0) {
+                throw new IOException("corrupted stream - negative length found");
+            }
+
+            if (length >= _limit)   // after all we must have read at least 1 byte
+            {
+                throw new IOException("corrupted stream - out of bounds length found");
+            }
+        }
+
+        return length;
+    }
+
+    public DEREncodable readObject()
+        throws IOException {
+        int tag = _in.read();
+        if (tag == -1) {
+            if (_eofFound) {
+                throw new EOFException("attempt to read past end of file.");
+            }
+
+            _eofFound = true;
+
+            return null;
+        }
+
+        //
+        // turn of looking for "00" while we resolve the tag
+        //
+        set00Check(false);
+
+        //
+        // calculate tag number
+        //
+        int baseTagNo = tag & ~DERTags.CONSTRUCTED;
+        int tagNo = baseTagNo;
+
+        if ((tag & DERTags.TAGGED) != 0) {
+            tagNo = tag & 0x1f;
+
+            //
+            // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+            //
+            if (tagNo == 0x1f) {
+                tagNo = 0;
+
+                int b = _in.read();
+
+                while ((b >= 0) && ((b & 0x80) != 0)) {
+                    tagNo |= (b & 0x7f);
+                    tagNo <<= 7;
+                    b = _in.read();
+                }
+
+                if (b < 0) {
+                    _eofFound = true;
+
+                    throw new EOFException("EOF encountered inside tag value.");
+                }
+
+                tagNo |= (b & 0x7f);
+            }
+        }
+
+        //
+        // calculate length
+        //
+        int length = readLength();
+
+        if (length < 0)  // indefinite length
+        {
+            IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
+
+            switch (baseTagNo) {
+                case DERTags.NULL:
+                    while (indIn.read() >= 0) {
+                        // make sure we skip to end of object
+                    }
+                    return BERNull.INSTANCE;
+                case DERTags.OCTET_STRING:
+                    return new BEROctetStringParser(new ASN1ObjectParser(tag, tagNo, indIn));
+                case DERTags.SEQUENCE:
+                    return new BERSequenceParser(new ASN1ObjectParser(tag, tagNo, indIn));
+                case DERTags.SET:
+                    return new BERSetParser(new ASN1ObjectParser(tag, tagNo, indIn));
+                default:
+                    return new BERTaggedObjectParser(tag, tagNo, indIn);
+            }
+        } else {
+            DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+            switch (baseTagNo) {
+                case DERTags.INTEGER:
+                    return new DERInteger(defIn.toByteArray());
+                case DERTags.NULL:
+                    defIn.toByteArray(); // make sure we read to end of object bytes.
+                    return DERNull.INSTANCE;
+                case DERTags.OBJECT_IDENTIFIER:
+                    return new DERObjectIdentifier(defIn.toByteArray());
+                case DERTags.OCTET_STRING:
+                    return new DEROctetString(defIn.toByteArray());
+                case DERTags.SEQUENCE:
+                    return new DERSequence(loadVector(defIn, length)).parser();
+                case DERTags.SET:
+                    return new DERSet(loadVector(defIn, length)).parser();
+                default:
+                    return new BERTaggedObjectParser(tag, tagNo, defIn);
+            }
+        }
+    }
+
+    private void set00Check(boolean enabled) {
+        if (_in instanceof IndefiniteLengthInputStream) {
+            ((IndefiniteLengthInputStream) _in).setEofOn00(enabled);
+        }
+    }
+
+    private ASN1EncodableVector loadVector(InputStream in, int length)
+        throws IOException {
+        ASN1InputStream aIn = new ASN1InputStream(in, length);
+        ASN1EncodableVector v = new ASN1EncodableVector();
+
+        DERObject obj;
+        while ((obj = aIn.readObject()) != null) {
+            v.add(obj);
+        }
+
+        return v;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1TaggedObject.java b/src/java/org/apache/commons/ssl/asn1/ASN1TaggedObject.java
new file mode 100644
index 0000000..063569b
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1TaggedObject.java
@@ -0,0 +1,177 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/**
+ * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by
+ * a [n] where n is some number - these are assume to follow the construction
+ * rules (as with sequences).
+ */
+public abstract class ASN1TaggedObject
+    extends ASN1Object
+    implements ASN1TaggedObjectParser {
+    int tagNo;
+    boolean empty = false;
+    boolean explicit = true;
+    DEREncodable obj = null;
+
+    static public ASN1TaggedObject getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        if (explicit) {
+            return (ASN1TaggedObject) obj.getObject();
+        }
+
+        throw new IllegalArgumentException("implicitly tagged tagged object");
+    }
+
+    static public ASN1TaggedObject getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof ASN1TaggedObject) {
+            return (ASN1TaggedObject) obj;
+        }
+
+        throw new IllegalArgumentException("unknown object in getInstance");
+    }
+
+    /**
+     * Create a tagged object in the explicit style.
+     *
+     * @param tagNo the tag number for this object.
+     * @param obj   the tagged object.
+     */
+    public ASN1TaggedObject(
+        int tagNo,
+        DEREncodable obj) {
+        this.explicit = true;
+        this.tagNo = tagNo;
+        this.obj = obj;
+    }
+
+    /**
+     * Create a tagged object with the style given by the value of explicit.
+     * <p>
+     * If the object implements ASN1Choice the tag style will always be changed
+     * to explicit in accordance with the ASN.1 encoding rules.
+     * </p>
+     *
+     * @param explicit true if the object is explicitly tagged.
+     * @param tagNo    the tag number for this object.
+     * @param obj      the tagged object.
+     */
+    public ASN1TaggedObject(
+        boolean explicit,
+        int tagNo,
+        DEREncodable obj) {
+        if (obj instanceof ASN1Choice) {
+            this.explicit = true;
+        } else {
+            this.explicit = explicit;
+        }
+
+        this.tagNo = tagNo;
+        this.obj = obj;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof ASN1TaggedObject)) {
+            return false;
+        }
+
+        ASN1TaggedObject other = (ASN1TaggedObject) o;
+
+        if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit) {
+            return false;
+        }
+
+        if (obj == null) {
+            if (other.obj != null) {
+                return false;
+            }
+        } else {
+            if (!(obj.getDERObject().equals(other.obj.getDERObject()))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public int hashCode() {
+        int code = tagNo;
+
+        if (obj != null) {
+            code ^= obj.hashCode();
+        }
+
+        return code;
+    }
+
+    public int getTagNo() {
+        return tagNo;
+    }
+
+    /**
+     * return whether or not the object may be explicitly tagged.
+     * <p/>
+     * Note: if the object has been read from an input stream, the only
+     * time you can be sure if isExplicit is returning the true state of
+     * affairs is if it returns false. An implicitly tagged object may appear
+     * to be explicitly tagged, so you need to understand the context under
+     * which the reading was done as well, see getObject below.
+     */
+    public boolean isExplicit() {
+        return explicit;
+    }
+
+    public boolean isEmpty() {
+        return empty;
+    }
+
+    /**
+     * return whatever was following the tag.
+     * <p/>
+     * Note: tagged objects are generally context dependent if you're
+     * trying to extract a tagged object you should be going via the
+     * appropriate getInstance method.
+     */
+    public DERObject getObject() {
+        if (obj != null) {
+            return obj.getDERObject();
+        }
+
+        return null;
+    }
+
+    /**
+     * Return the object held in this tagged object as a parser assuming it has
+     * the type of the passed in tag. If the object doesn't have a parser
+     * associated with it, the base object is returned.
+     */
+    public DEREncodable getObjectParser(
+        int tag,
+        boolean isExplicit) {
+        switch (tag) {
+            case DERTags.SET:
+                return ASN1Set.getInstance(this, isExplicit).parser();
+            case DERTags.SEQUENCE:
+                return ASN1Sequence.getInstance(this, isExplicit).parser();
+            case DERTags.OCTET_STRING:
+                return ASN1OctetString.getInstance(this, isExplicit).parser();
+        }
+
+        if (isExplicit) {
+            return getObject();
+        }
+
+        throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
+    }
+
+    abstract void encode(DEROutputStream out)
+        throws IOException;
+
+    public String toString() {
+        return "[" + tagNo + "]" + obj;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ASN1TaggedObjectParser.java b/src/java/org/apache/commons/ssl/asn1/ASN1TaggedObjectParser.java
new file mode 100644
index 0000000..7d24c6d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ASN1TaggedObjectParser.java
@@ -0,0 +1,11 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public interface ASN1TaggedObjectParser
+    extends DEREncodable {
+    public int getTagNo();
+
+    public DEREncodable getObjectParser(int tag, boolean isExplicit)
+        throws IOException;
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERConstructedOctetString.java b/src/java/org/apache/commons/ssl/asn1/BERConstructedOctetString.java
new file mode 100644
index 0000000..750de3b
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERConstructedOctetString.java
@@ -0,0 +1,137 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class BERConstructedOctetString
+    extends DEROctetString {
+    private static final int MAX_LENGTH = 1000;
+
+    /** convert a vector of octet strings into a single byte string */
+    static private byte[] toBytes(
+        Vector octs) {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+        for (int i = 0; i != octs.size(); i++) {
+            try {
+                DEROctetString o = (DEROctetString) octs.elementAt(i);
+
+                bOut.write(o.getOctets());
+            }
+            catch (ClassCastException e) {
+                throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
+            }
+            catch (IOException e) {
+                throw new IllegalArgumentException("exception converting octets " + e.toString());
+            }
+        }
+
+        return bOut.toByteArray();
+    }
+
+    private Vector octs;
+
+    /** @param string the octets making up the octet string. */
+    public BERConstructedOctetString(
+        byte[] string) {
+        super(string);
+    }
+
+    public BERConstructedOctetString(
+        Vector octs) {
+        super(toBytes(octs));
+
+        this.octs = octs;
+    }
+
+    public BERConstructedOctetString(
+        DERObject obj) {
+        super(obj);
+    }
+
+    public BERConstructedOctetString(
+        DEREncodable obj) {
+        super(obj.getDERObject());
+    }
+
+    public byte[] getOctets() {
+        return string;
+    }
+
+    /** return the DER octets that make up this string. */
+    public Enumeration getObjects() {
+        if (octs == null) {
+            return generateOcts().elements();
+        }
+
+        return octs.elements();
+    }
+
+    private Vector generateOcts() {
+        int start = 0;
+        int end = 0;
+        Vector vec = new Vector();
+
+        while ((end + 1) < string.length) {
+            if (string[end] == 0 && string[end + 1] == 0) {
+                byte[] nStr = new byte[end - start + 1];
+
+                System.arraycopy(string, start, nStr, 0, nStr.length);
+
+                vec.addElement(new DEROctetString(nStr));
+                start = end + 1;
+            }
+            end++;
+        }
+
+        byte[] nStr = new byte[string.length - start];
+
+        System.arraycopy(string, start, nStr, 0, nStr.length);
+
+        vec.addElement(new DEROctetString(nStr));
+
+        return vec;
+    }
+
+    public void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
+            out.write(CONSTRUCTED | OCTET_STRING);
+
+            out.write(0x80);
+
+            //
+            // write out the octet array
+            //
+            if (octs != null) {
+                for (int i = 0; i != octs.size(); i++) {
+                    out.writeObject(octs.elementAt(i));
+                }
+            } else {
+                for (int i = 0; i < string.length; i += MAX_LENGTH) {
+                    int end;
+
+                    if (i + MAX_LENGTH > string.length) {
+                        end = string.length;
+                    } else {
+                        end = i + MAX_LENGTH;
+                    }
+
+                    byte[] nStr = new byte[end - i];
+
+                    System.arraycopy(string, i, nStr, 0, nStr.length);
+
+                    out.writeObject(new DEROctetString(nStr));
+                }
+            }
+
+            out.write(0x00);
+            out.write(0x00);
+        } else {
+            super.encode(out);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERConstructedSequence.java b/src/java/org/apache/commons/ssl/asn1/BERConstructedSequence.java
new file mode 100644
index 0000000..5cccfb6
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERConstructedSequence.java
@@ -0,0 +1,29 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/** @deprecated use BERSequence */
+public class BERConstructedSequence
+    extends DERConstructedSequence {
+    /*
+     */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
+            out.write(SEQUENCE | CONSTRUCTED);
+            out.write(0x80);
+
+            Enumeration e = getObjects();
+            while (e.hasMoreElements()) {
+                out.writeObject(e.nextElement());
+            }
+
+            out.write(0x00);
+            out.write(0x00);
+        } else {
+            super.encode(out);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERGenerator.java b/src/java/org/apache/commons/ssl/asn1/BERGenerator.java
new file mode 100644
index 0000000..a81859b
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERGenerator.java
@@ -0,0 +1,82 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class BERGenerator
+    extends ASN1Generator {
+    private boolean _tagged = false;
+    private boolean _isExplicit;
+    private int _tagNo;
+
+    protected BERGenerator(
+        OutputStream out) {
+        super(out);
+    }
+
+    public BERGenerator(
+        OutputStream out,
+        int tagNo,
+        boolean isExplicit) {
+        super(out);
+
+        _tagged = true;
+        _isExplicit = isExplicit;
+        _tagNo = tagNo;
+    }
+
+    public OutputStream getRawOutputStream() {
+        return _out;
+    }
+
+    private void writeHdr(
+        int tag)
+        throws IOException {
+        _out.write(tag);
+        _out.write(0x80);
+    }
+
+    protected void writeBERHeader(
+        int tag)
+        throws IOException {
+        if (_tagged) {
+            int tagNum = _tagNo | DERTags.TAGGED;
+
+            if (_isExplicit) {
+                writeHdr(tagNum | DERTags.CONSTRUCTED);
+                writeHdr(tag);
+            } else {
+                if ((tag & DERTags.CONSTRUCTED) != 0) {
+                    writeHdr(tagNum | DERTags.CONSTRUCTED);
+                } else {
+                    writeHdr(tagNum);
+                }
+            }
+        } else {
+            writeHdr(tag);
+        }
+    }
+
+    protected void writeBERBody(
+        InputStream contentStream)
+        throws IOException {
+        int ch;
+
+        while ((ch = contentStream.read()) >= 0) {
+            _out.write(ch);
+        }
+    }
+
+    protected void writeBEREnd()
+        throws IOException {
+        _out.write(0x00);
+        _out.write(0x00);
+
+        if (_tagged && _isExplicit)  // write extra end for tag header
+        {
+            _out.write(0x00);
+            _out.write(0x00);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERInputStream.java b/src/java/org/apache/commons/ssl/asn1/BERInputStream.java
new file mode 100644
index 0000000..403b2ce
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERInputStream.java
@@ -0,0 +1,179 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Vector;
+
+/** @deprecated use ASN1InputStream */
+public class BERInputStream
+    extends DERInputStream {
+    private static final DERObject END_OF_STREAM = new DERObject() {
+        void encode(
+            DEROutputStream out)
+            throws IOException {
+            throw new IOException("Eeek!");
+        }
+        public int hashCode() {
+            return 0;
+        }
+        public boolean equals(
+            Object o) {
+            return o == this;
+        }
+    };
+    public BERInputStream(
+        InputStream is) {
+        super(is);
+    }
+
+    /** read a string of bytes representing an indefinite length object. */
+    private byte[] readIndefiniteLengthFully()
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        int b, b1;
+
+        b1 = read();
+
+        while ((b = read()) >= 0) {
+            if (b1 == 0 && b == 0) {
+                break;
+            }
+
+            bOut.write(b1);
+            b1 = b;
+        }
+
+        return bOut.toByteArray();
+    }
+
+    private BERConstructedOctetString buildConstructedOctetString()
+        throws IOException {
+        Vector octs = new Vector();
+
+        for (; ;) {
+            DERObject o = readObject();
+
+            if (o == END_OF_STREAM) {
+                break;
+            }
+
+            octs.addElement(o);
+        }
+
+        return new BERConstructedOctetString(octs);
+    }
+
+    public DERObject readObject()
+        throws IOException {
+        int tag = read();
+        if (tag == -1) {
+            throw new EOFException();
+        }
+
+        int length = readLength();
+
+        if (length < 0)    // indefinite length method
+        {
+            switch (tag) {
+                case NULL:
+                    return null;
+                case SEQUENCE | CONSTRUCTED:
+                    BERConstructedSequence seq = new BERConstructedSequence();
+
+                    for (; ;) {
+                        DERObject obj = readObject();
+
+                        if (obj == END_OF_STREAM) {
+                            break;
+                        }
+
+                        seq.addObject(obj);
+                    }
+                    return seq;
+                case OCTET_STRING | CONSTRUCTED:
+                    return buildConstructedOctetString();
+                case SET | CONSTRUCTED:
+                    ASN1EncodableVector v = new ASN1EncodableVector();
+
+                    for (; ;) {
+                        DERObject obj = readObject();
+
+                        if (obj == END_OF_STREAM) {
+                            break;
+                        }
+
+                        v.add(obj);
+                    }
+                    return new BERSet(v);
+                default:
+                    //
+                    // with tagged object tag number is bottom 5 bits
+                    //
+                    if ((tag & TAGGED) != 0) {
+                        if ((tag & 0x1f) == 0x1f) {
+                            throw new IOException("unsupported high tag encountered");
+                        }
+
+                        //
+                        // simple type - implicit... return an octet string
+                        //
+                        if ((tag & CONSTRUCTED) == 0) {
+                            byte[] bytes = readIndefiniteLengthFully();
+
+                            return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
+                        }
+
+                        //
+                        // either constructed or explicitly tagged
+                        //
+                        DERObject dObj = readObject();
+
+                        if (dObj == END_OF_STREAM)     // empty tag!
+                        {
+                            return new DERTaggedObject(tag & 0x1f);
+                        }
+
+                        DERObject next = readObject();
+
+                        //
+                        // explicitly tagged (probably!) - if it isn't we'd have to
+                        // tell from the context
+                        //
+                        if (next == END_OF_STREAM) {
+                            return new BERTaggedObject(tag & 0x1f, dObj);
+                        }
+
+                        //
+                        // another implicit object, we'll create a sequence...
+                        //
+                        seq = new BERConstructedSequence();
+
+                        seq.addObject(dObj);
+
+                        do {
+                            seq.addObject(next);
+                            next = readObject();
+                        }
+                        while (next != END_OF_STREAM);
+
+                        return new BERTaggedObject(false, tag & 0x1f, seq);
+                    }
+
+                    throw new IOException("unknown BER object encountered");
+            }
+        } else {
+            if (tag == 0 && length == 0)    // end of contents marker.
+            {
+                return END_OF_STREAM;
+            }
+
+            byte[] bytes = new byte[length];
+
+            readFully(bytes);
+
+            return buildObject(tag, bytes);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERNull.java b/src/java/org/apache/commons/ssl/asn1/BERNull.java
new file mode 100644
index 0000000..e5c1626
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERNull.java
@@ -0,0 +1,22 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** A BER NULL object. */
+public class BERNull
+    extends DERNull {
+    public static final BERNull INSTANCE = new BERNull();
+
+    public BERNull() {
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
+            out.write(NULL);
+        } else {
+            super.encode(out);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BEROctetStringGenerator.java b/src/java/org/apache/commons/ssl/asn1/BEROctetStringGenerator.java
new file mode 100644
index 0000000..b21fade
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BEROctetStringGenerator.java
@@ -0,0 +1,86 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROctetStringGenerator
+    extends BERGenerator {
+    public BEROctetStringGenerator(OutputStream out)
+        throws IOException {
+        super(out);
+
+        writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
+    }
+
+    public BEROctetStringGenerator(
+        OutputStream out,
+        int tagNo,
+        boolean isExplicit)
+        throws IOException {
+        super(out, tagNo, isExplicit);
+
+        writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
+    }
+
+    public OutputStream getOctetOutputStream() {
+        return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
+    }
+
+    public OutputStream getOctetOutputStream(
+        byte[] buf) {
+        return new BufferedBEROctetStream(buf);
+    }
+
+    private class BufferedBEROctetStream
+        extends OutputStream {
+        private byte[] _buf;
+        private int _off;
+
+        BufferedBEROctetStream(
+            byte[] buf) {
+            _buf = buf;
+            _off = 0;
+        }
+
+        public void write(
+            int b)
+            throws IOException {
+            _buf[_off++] = (byte) b;
+
+            if (_off == _buf.length) {
+                _out.write(new DEROctetString(_buf).getEncoded());
+                _off = 0;
+            }
+        }
+
+        public void write(byte[] b, int off, int len) throws IOException {
+            while (len > 0) {
+                int numToCopy = Math.min(len, _buf.length - _off);
+                System.arraycopy(b, off, _buf, _off, numToCopy);
+
+                _off += numToCopy;
+                if (_off < _buf.length) {
+                    break;
+                }
+
+                _out.write(new DEROctetString(_buf).getEncoded());
+                _off = 0;
+
+                off += numToCopy;
+                len -= numToCopy;
+            }
+        }
+
+        public void close()
+            throws IOException {
+            if (_off != 0) {
+                byte[] bytes = new byte[_off];
+                System.arraycopy(_buf, 0, bytes, 0, _off);
+
+                _out.write(new DEROctetString(bytes).getEncoded());
+            }
+
+            writeBEREnd();
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BEROctetStringParser.java b/src/java/org/apache/commons/ssl/asn1/BEROctetStringParser.java
new file mode 100644
index 0000000..2123c2b
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BEROctetStringParser.java
@@ -0,0 +1,36 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BEROctetStringParser
+    implements ASN1OctetStringParser {
+    private ASN1ObjectParser _parser;
+
+    protected BEROctetStringParser(
+        ASN1ObjectParser parser) {
+        _parser = parser;
+    }
+
+    public InputStream getOctetStream() {
+        return new ConstructedOctetStream(_parser);
+    }
+
+    public DERObject getDERObject() {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        InputStream in = this.getOctetStream();
+        int ch;
+
+        try {
+            while ((ch = in.read()) >= 0) {
+                bOut.write(ch);
+            }
+        }
+        catch (IOException e) {
+            throw new IllegalStateException("IOException converting stream to byte array: " + e.getMessage());
+        }
+
+        return new BERConstructedOctetString(bOut.toByteArray());
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BEROutputStream.java b/src/java/org/apache/commons/ssl/asn1/BEROutputStream.java
new file mode 100644
index 0000000..36f99ee
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BEROutputStream.java
@@ -0,0 +1,26 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROutputStream
+    extends DEROutputStream {
+    public BEROutputStream(
+        OutputStream os) {
+        super(os);
+    }
+
+    public void writeObject(
+        Object obj)
+        throws IOException {
+        if (obj == null) {
+            writeNull();
+        } else if (obj instanceof DERObject) {
+            ((DERObject) obj).encode(this);
+        } else if (obj instanceof DEREncodable) {
+            ((DEREncodable) obj).getDERObject().encode(this);
+        } else {
+            throw new IOException("object not BEREncodable");
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERSequence.java b/src/java/org/apache/commons/ssl/asn1/BERSequence.java
new file mode 100644
index 0000000..cc7667e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERSequence.java
@@ -0,0 +1,44 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class BERSequence
+    extends DERSequence {
+    /** create an empty sequence */
+    public BERSequence() {
+    }
+
+    /** create a sequence containing one object */
+    public BERSequence(
+        DEREncodable obj) {
+        super(obj);
+    }
+
+    /** create a sequence containing a vector of objects. */
+    public BERSequence(
+        DEREncodableVector v) {
+        super(v);
+    }
+
+    /*
+     */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
+            out.write(SEQUENCE | CONSTRUCTED);
+            out.write(0x80);
+
+            Enumeration e = getObjects();
+            while (e.hasMoreElements()) {
+                out.writeObject(e.nextElement());
+            }
+
+            out.write(0x00);
+            out.write(0x00);
+        } else {
+            super.encode(out);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERSequenceGenerator.java b/src/java/org/apache/commons/ssl/asn1/BERSequenceGenerator.java
new file mode 100644
index 0000000..0e821ce
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERSequenceGenerator.java
@@ -0,0 +1,36 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BERSequenceGenerator
+    extends BERGenerator {
+    public BERSequenceGenerator(
+        OutputStream out)
+        throws IOException {
+        super(out);
+
+        writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
+    }
+
+    public BERSequenceGenerator(
+        OutputStream out,
+        int tagNo,
+        boolean isExplicit)
+        throws IOException {
+        super(out, tagNo, isExplicit);
+
+        writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
+    }
+
+    public void addObject(
+        DEREncodable object)
+        throws IOException {
+        object.getDERObject().encode(new DEROutputStream(_out));
+    }
+
+    public void close()
+        throws IOException {
+        writeBEREnd();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERSequenceParser.java b/src/java/org/apache/commons/ssl/asn1/BERSequenceParser.java
new file mode 100644
index 0000000..fb7dad3
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERSequenceParser.java
@@ -0,0 +1,21 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public class BERSequenceParser
+    implements ASN1SequenceParser {
+    private ASN1ObjectParser _parser;
+
+    BERSequenceParser(ASN1ObjectParser parser) {
+        this._parser = parser;
+    }
+
+    public DEREncodable readObject()
+        throws IOException {
+        return _parser.readObject();
+    }
+
+    public DERObject getDERObject() {
+        return new BERSequence(_parser.readVector());
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERSet.java b/src/java/org/apache/commons/ssl/asn1/BERSet.java
new file mode 100644
index 0000000..db80cf4
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERSet.java
@@ -0,0 +1,51 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class BERSet
+    extends DERSet {
+    /** create an empty sequence */
+    public BERSet() {
+    }
+
+    /** create a set containing one object */
+    public BERSet(
+        DEREncodable obj) {
+        super(obj);
+    }
+
+    /** @param v - a vector of objects making up the set. */
+    public BERSet(
+        DEREncodableVector v) {
+        super(v, false);
+    }
+
+    /** @param v - a vector of objects making up the set. */
+    BERSet(
+        DEREncodableVector v,
+        boolean needsSorting) {
+        super(v, needsSorting);
+    }
+
+    /*
+     */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
+            out.write(SET | CONSTRUCTED);
+            out.write(0x80);
+
+            Enumeration e = getObjects();
+            while (e.hasMoreElements()) {
+                out.writeObject(e.nextElement());
+            }
+
+            out.write(0x00);
+            out.write(0x00);
+        } else {
+            super.encode(out);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERSetParser.java b/src/java/org/apache/commons/ssl/asn1/BERSetParser.java
new file mode 100644
index 0000000..7f88189
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERSetParser.java
@@ -0,0 +1,21 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public class BERSetParser
+    implements ASN1SetParser {
+    private ASN1ObjectParser _parser;
+
+    BERSetParser(ASN1ObjectParser parser) {
+        this._parser = parser;
+    }
+
+    public DEREncodable readObject()
+        throws IOException {
+        return _parser.readObject();
+    }
+
+    public DERObject getDERObject() {
+        return new BERSet(_parser.readVector());
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERTaggedObject.java b/src/java/org/apache/commons/ssl/asn1/BERTaggedObject.java
new file mode 100644
index 0000000..c0be868
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERTaggedObject.java
@@ -0,0 +1,94 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * BER TaggedObject - in ASN.1 nottation this is any object proceeded by
+ * a [n] where n is some number - these are assume to follow the construction
+ * rules (as with sequences).
+ */
+public class BERTaggedObject
+    extends DERTaggedObject {
+    /**
+     * @param tagNo the tag number for this object.
+     * @param obj   the tagged object.
+     */
+    public BERTaggedObject(
+        int tagNo,
+        DEREncodable obj) {
+        super(tagNo, obj);
+    }
+
+    /**
+     * @param explicit true if an explicitly tagged object.
+     * @param tagNo    the tag number for this object.
+     * @param obj      the tagged object.
+     */
+    public BERTaggedObject(
+        boolean explicit,
+        int tagNo,
+        DEREncodable obj) {
+        super(explicit, tagNo, obj);
+    }
+
+    /**
+     * create an implicitly tagged object that contains a zero
+     * length sequence.
+     */
+    public BERTaggedObject(
+        int tagNo) {
+        super(false, tagNo, new BERSequence());
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
+            out.write(CONSTRUCTED | TAGGED | tagNo);
+            out.write(0x80);
+
+            if (!empty) {
+                if (!explicit) {
+                    if (obj instanceof ASN1OctetString) {
+                        Enumeration e;
+
+                        if (obj instanceof BERConstructedOctetString) {
+                            e = ((BERConstructedOctetString) obj).getObjects();
+                        } else {
+                            ASN1OctetString octs = (ASN1OctetString) obj;
+                            BERConstructedOctetString berO = new BERConstructedOctetString(octs.getOctets());
+
+                            e = berO.getObjects();
+                        }
+
+                        while (e.hasMoreElements()) {
+                            out.writeObject(e.nextElement());
+                        }
+                    } else if (obj instanceof ASN1Sequence) {
+                        Enumeration e = ((ASN1Sequence) obj).getObjects();
+
+                        while (e.hasMoreElements()) {
+                            out.writeObject(e.nextElement());
+                        }
+                    } else if (obj instanceof ASN1Set) {
+                        Enumeration e = ((ASN1Set) obj).getObjects();
+
+                        while (e.hasMoreElements()) {
+                            out.writeObject(e.nextElement());
+                        }
+                    } else {
+                        throw new RuntimeException("not implemented: " + obj.getClass().getName());
+                    }
+                } else {
+                    out.writeObject(obj);
+                }
+            }
+
+            out.write(0x00);
+            out.write(0x00);
+        } else {
+            super.encode(out);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/BERTaggedObjectParser.java b/src/java/org/apache/commons/ssl/asn1/BERTaggedObjectParser.java
new file mode 100644
index 0000000..0f45cdb
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/BERTaggedObjectParser.java
@@ -0,0 +1,118 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BERTaggedObjectParser
+    implements ASN1TaggedObjectParser {
+    private int _baseTag;
+    private int _tagNumber;
+    private InputStream _contentStream;
+
+    private boolean _indefiniteLength;
+
+    protected BERTaggedObjectParser(
+        int baseTag,
+        int tagNumber,
+        InputStream contentStream) {
+        _baseTag = baseTag;
+        _tagNumber = tagNumber;
+        _contentStream = contentStream;
+        _indefiniteLength = contentStream instanceof IndefiniteLengthInputStream;
+    }
+
+    public boolean isConstructed() {
+        return (_baseTag & DERTags.CONSTRUCTED) != 0;
+    }
+
+    public int getTagNo() {
+        return _tagNumber;
+    }
+
+    public DEREncodable getObjectParser(
+        int tag,
+        boolean isExplicit)
+        throws IOException {
+        if (isExplicit) {
+            return new ASN1StreamParser(_contentStream).readObject();
+        } else {
+            switch (tag) {
+                case DERTags.SET:
+                    if (_indefiniteLength) {
+                        return new BERSetParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
+                    } else {
+                        return new DERSet(loadVector(_contentStream)).parser();
+                    }
+                case DERTags.SEQUENCE:
+                    if (_indefiniteLength) {
+                        return new BERSequenceParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
+                    } else {
+                        return new DERSequence(loadVector(_contentStream)).parser();
+                    }
+                case DERTags.OCTET_STRING:
+                    if (_indefiniteLength || this.isConstructed()) {
+                        return new BEROctetStringParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
+                    } else {
+                        return new DEROctetString(((DefiniteLengthInputStream) _contentStream).toByteArray()).parser();
+                    }
+            }
+        }
+
+        throw new RuntimeException("implicit tagging not implemented");
+    }
+
+    private ASN1EncodableVector loadVector(InputStream in)
+        throws IOException {
+        ASN1StreamParser aIn = new ASN1StreamParser(in);
+        ASN1EncodableVector v = new ASN1EncodableVector();
+        DEREncodable obj = aIn.readObject();
+
+        while (obj != null) {
+            v.add(obj.getDERObject());
+            obj = aIn.readObject();
+        }
+
+        return v;
+    }
+
+    private ASN1EncodableVector rLoadVector(InputStream in) {
+        try {
+            return loadVector(in);
+        }
+        catch (IOException e) {
+            throw new IllegalStateException(e.getMessage());
+        }
+    }
+
+    public DERObject getDERObject() {
+        if (_indefiniteLength) {
+            ASN1EncodableVector v = rLoadVector(_contentStream);
+
+            if (v.size() > 1) {
+                return new BERTaggedObject(false, _tagNumber, new BERSequence(v));
+            } else if (v.size() == 1) {
+                return new BERTaggedObject(true, _tagNumber, v.get(0));
+            } else {
+                return new BERTaggedObject(false, _tagNumber, new BERSequence());
+            }
+        } else {
+            if (this.isConstructed()) {
+                ASN1EncodableVector v = rLoadVector(_contentStream);
+
+                if (v.size() == 1) {
+                    return new DERTaggedObject(true, _tagNumber, v.get(0));
+                }
+
+                return new DERTaggedObject(false, _tagNumber, new DERSequence(v));
+            }
+
+            try {
+                return new DERTaggedObject(false, _tagNumber, new DEROctetString(((DefiniteLengthInputStream) _contentStream).toByteArray()));
+            }
+            catch (IOException e) {
+                throw new IllegalStateException(e.getMessage());
+            }
+        }
+
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/ConstructedOctetStream.java b/src/java/org/apache/commons/ssl/asn1/ConstructedOctetStream.java
new file mode 100644
index 0000000..18565bb
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/ConstructedOctetStream.java
@@ -0,0 +1,92 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+class ConstructedOctetStream
+    extends InputStream {
+    private final ASN1ObjectParser _parser;
+
+    private boolean _first = true;
+    private InputStream _currentStream;
+
+    ConstructedOctetStream(
+        ASN1ObjectParser parser) {
+        _parser = parser;
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (_currentStream == null) {
+            if (!_first) {
+                return -1;
+            }
+
+            ASN1OctetStringParser s = (ASN1OctetStringParser) _parser.readObject();
+
+            if (s == null) {
+                return -1;
+            }
+
+            _first = false;
+            _currentStream = s.getOctetStream();
+        }
+
+        int totalRead = 0;
+
+        for (; ;) {
+            int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
+
+            if (numRead >= 0) {
+                totalRead += numRead;
+
+                if (totalRead == len) {
+                    return totalRead;
+                }
+            } else {
+                ASN1OctetStringParser aos = (ASN1OctetStringParser) _parser.readObject();
+
+                if (aos == null) {
+                    _currentStream = null;
+                    return totalRead < 1 ? -1 : totalRead;
+                }
+
+                _currentStream = aos.getOctetStream();
+            }
+        }
+    }
+
+    public int read()
+        throws IOException {
+        if (_currentStream == null) {
+            if (!_first) {
+                return -1;
+            }
+
+            ASN1OctetStringParser s = (ASN1OctetStringParser) _parser.readObject();
+
+            if (s == null) {
+                return -1;
+            }
+
+            _first = false;
+            _currentStream = s.getOctetStream();
+        }
+
+        for (; ;) {
+            int b = _currentStream.read();
+
+            if (b >= 0) {
+                return b;
+            }
+
+            ASN1OctetStringParser s = (ASN1OctetStringParser) _parser.readObject();
+
+            if (s == null) {
+                _currentStream = null;
+                return -1;
+            }
+
+            _currentStream = s.getOctetStream();
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERApplicationSpecific.java b/src/java/org/apache/commons/ssl/asn1/DERApplicationSpecific.java
new file mode 100644
index 0000000..be1b192
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERApplicationSpecific.java
@@ -0,0 +1,143 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/** Base class for an application specific object */
+public class DERApplicationSpecific
+    extends ASN1Object {
+    private int tag;
+    private byte[] octets;
+
+    public DERApplicationSpecific(
+        int tag,
+        byte[] octets) {
+        this.tag = tag;
+        this.octets = octets;
+    }
+
+    public DERApplicationSpecific(
+        int tag,
+        DEREncodable object)
+        throws IOException {
+        this(true, tag, object);
+    }
+
+    public DERApplicationSpecific(
+        boolean explicit,
+        int tag,
+        DEREncodable object)
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        DEROutputStream dos = new DEROutputStream(bOut);
+
+        dos.writeObject(object);
+
+        byte[] data = bOut.toByteArray();
+
+        if (tag >= 0x1f) {
+            throw new IOException("unsupported tag number");
+        }
+
+        if (explicit) {
+            this.tag = tag | DERTags.CONSTRUCTED;
+            this.octets = data;
+        } else {
+            this.tag = tag;
+            int lenBytes = getLengthOfLength(data);
+            byte[] tmp = new byte[data.length - lenBytes];
+            System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+            this.octets = tmp;
+        }
+    }
+
+    private int getLengthOfLength(byte[] data) {
+        int count = 2;               // TODO: assumes only a 1 byte tag number
+
+        while ((data[count - 1] & 0x80) != 0) {
+            count++;
+        }
+
+        return count;
+    }
+
+    public boolean isConstructed() {
+        return (tag & DERTags.CONSTRUCTED) != 0;
+    }
+
+    public byte[] getContents() {
+        return octets;
+    }
+
+    public int getApplicationTag() {
+        return tag;
+    }
+
+    public DERObject getObject()
+        throws IOException {
+        return new ASN1InputStream(getContents()).readObject();
+    }
+
+    /**
+     * Return the enclosed object assuming implicit tagging.
+     *
+     * @param derTagNo the type tag that should be applied to the object's contents.
+     * @return the resulting object
+     * @throws IOException if reconstruction fails.
+     */
+    public DERObject getObject(int derTagNo)
+        throws IOException {
+        if (tag >= 0x1f) {
+            throw new IOException("unsupported tag number");
+        }
+
+        byte[] tmp = this.getEncoded();
+
+        tmp[0] = (byte) derTagNo;
+
+        return new ASN1InputStream(tmp).readObject();
+    }
+
+    /* (non-Javadoc)
+    * @see org.apache.commons.ssl.asn1.DERObject#encode(org.apache.commons.ssl.asn1.DEROutputStream)
+    */
+    void encode(DEROutputStream out) throws IOException {
+        out.writeEncoded(DERTags.APPLICATION | tag, octets);
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERApplicationSpecific)) {
+            return false;
+        }
+
+        DERApplicationSpecific other = (DERApplicationSpecific) o;
+
+        if (tag != other.tag) {
+            return false;
+        }
+
+        if (octets.length != other.octets.length) {
+            return false;
+        }
+
+        for (int i = 0; i < octets.length; i++) {
+            if (octets[i] != other.octets[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public int hashCode() {
+        byte[] b = this.getContents();
+        int value = 0;
+
+        for (int i = 0; i != b.length; i++) {
+            value ^= (b[i] & 0xff) << (i % 4);
+        }
+
+        return value ^ this.getApplicationTag();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERBMPString.java b/src/java/org/apache/commons/ssl/asn1/DERBMPString.java
new file mode 100644
index 0000000..e093582
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERBMPString.java
@@ -0,0 +1,104 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER BMPString object. */
+public class DERBMPString
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return a BMP String from the given object.
+     *
+     * @param obj the object we want converted.
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERBMPString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERBMPString) {
+            return (DERBMPString) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERBMPString(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return a BMP String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERBMPString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+
+    /** basic constructor - byte encoded string. */
+    public DERBMPString(
+        byte[] string) {
+        char[] cs = new char[string.length / 2];
+
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) ((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
+        }
+
+        this.string = new String(cs);
+    }
+
+    /** basic constructor */
+    public DERBMPString(
+        String string) {
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+
+    protected boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERBMPString)) {
+            return false;
+        }
+
+        DERBMPString s = (DERBMPString) o;
+
+        return this.getString().equals(s.getString());
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        char[] c = string.toCharArray();
+        byte[] b = new byte[c.length * 2];
+
+        for (int i = 0; i != c.length; i++) {
+            b[2 * i] = (byte) (c[i] >> 8);
+            b[2 * i + 1] = (byte) c[i];
+        }
+
+        out.writeEncoded(BMP_STRING, b);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERBitString.java b/src/java/org/apache/commons/ssl/asn1/DERBitString.java
new file mode 100644
index 0000000..2cb649c
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERBitString.java
@@ -0,0 +1,245 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class DERBitString
+    extends ASN1Object
+    implements DERString {
+    private static final char[] table = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+    protected byte[] data;
+    protected int padBits;
+
+    /**
+     * return the correct number of pad bits for a bit string defined in
+     * a 32 bit constant
+     */
+    static protected int getPadBits(
+        int bitString) {
+        int val = 0;
+        for (int i = 3; i >= 0; i--) {
+            //
+            // this may look a little odd, but if it isn't done like this pre jdk1.2
+            // JVM's break!
+            //
+            if (i != 0) {
+                if ((bitString >> (i * 8)) != 0) {
+                    val = (bitString >> (i * 8)) & 0xFF;
+                    break;
+                }
+            } else {
+                if (bitString != 0) {
+                    val = bitString & 0xFF;
+                    break;
+                }
+            }
+        }
+
+        if (val == 0) {
+            return 7;
+        }
+
+
+        int bits = 1;
+
+        while (((val <<= 1) & 0xFF) != 0) {
+            bits++;
+        }
+
+        return 8 - bits;
+    }
+
+    /**
+     * return the correct number of bytes for a bit string defined in
+     * a 32 bit constant
+     */
+    static protected byte[] getBytes(int bitString) {
+        int bytes = 4;
+        for (int i = 3; i >= 1; i--) {
+            if ((bitString & (0xFF << (i * 8))) != 0) {
+                break;
+            }
+            bytes--;
+        }
+
+        byte[] result = new byte[bytes];
+        for (int i = 0; i < bytes; i++) {
+            result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
+        }
+
+        return result;
+    }
+
+    /**
+     * return a Bit String from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERBitString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERBitString) {
+            return (DERBitString) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            byte[] bytes = ((ASN1OctetString) obj).getOctets();
+            int padBits = bytes[0];
+            byte[] data = new byte[bytes.length - 1];
+
+            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+
+            return new DERBitString(data, padBits);
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return a Bit String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERBitString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    protected DERBitString(
+        byte data,
+        int padBits) {
+        this.data = new byte[1];
+        this.data[0] = data;
+        this.padBits = padBits;
+    }
+
+    /**
+     * @param data    the octets making up the bit string.
+     * @param padBits the number of extra bits at the end of the string.
+     */
+    public DERBitString(
+        byte[] data,
+        int padBits) {
+        this.data = data;
+        this.padBits = padBits;
+    }
+
+    public DERBitString(
+        byte[] data) {
+        this(data, 0);
+    }
+
+    public DERBitString(
+        DEREncodable obj) {
+        try {
+            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+            DEROutputStream dOut = new DEROutputStream(bOut);
+
+            dOut.writeObject(obj);
+            dOut.close();
+
+            this.data = bOut.toByteArray();
+            this.padBits = 0;
+        }
+        catch (IOException e) {
+            throw new IllegalArgumentException("Error processing object : " + e.toString());
+        }
+    }
+
+    public byte[] getBytes() {
+        return data;
+    }
+
+    public int getPadBits() {
+        return padBits;
+    }
+
+
+    /** @return the value of the bit string as an int (truncating if necessary) */
+    public int intValue() {
+        int value = 0;
+
+        for (int i = 0; i != data.length && i != 4; i++) {
+            value |= (data[i] & 0xff) << (8 * i);
+        }
+
+        return value;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        byte[] bytes = new byte[getBytes().length + 1];
+
+        bytes[0] = (byte) getPadBits();
+        System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
+
+        out.writeEncoded(BIT_STRING, bytes);
+    }
+
+    public int hashCode() {
+        int value = 0;
+
+        for (int i = 0; i != data.length; i++) {
+            value ^= (data[i] & 0xff) << (i % 4);
+        }
+
+        return value;
+    }
+
+    protected boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERBitString)) {
+            return false;
+        }
+
+        DERBitString other = (DERBitString) o;
+
+        if (data.length != other.data.length) {
+            return false;
+        }
+
+        for (int i = 0; i != data.length; i++) {
+            if (data[i] != other.data[i]) {
+                return false;
+            }
+        }
+
+        return (padBits == other.padBits);
+    }
+
+    public String getString() {
+        StringBuffer buf = new StringBuffer("#");
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+        try {
+            aOut.writeObject(this);
+        }
+        catch (IOException e) {
+            throw new RuntimeException("internal error encoding BitString");
+        }
+
+        byte[] string = bOut.toByteArray();
+
+        for (int i = 0; i != string.length; i++) {
+            buf.append(table[(string[i] >>> 4) & 0xf]);
+            buf.append(table[string[i] & 0xf]);
+        }
+
+        return buf.toString();
+    }
+
+    public String toString() {
+        return getString();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERBoolean.java b/src/java/org/apache/commons/ssl/asn1/DERBoolean.java
new file mode 100644
index 0000000..e49ec6c
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERBoolean.java
@@ -0,0 +1,96 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public class DERBoolean
+    extends ASN1Object {
+    byte value;
+
+    public static final DERBoolean FALSE = new DERBoolean(false);
+    public static final DERBoolean TRUE = new DERBoolean(true);
+
+    /**
+     * return a boolean from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERBoolean getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERBoolean) {
+            return (DERBoolean) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERBoolean(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /** return a DERBoolean from the passed in boolean. */
+    public static DERBoolean getInstance(
+        boolean value) {
+        return (value ? TRUE : FALSE);
+    }
+
+    /**
+     * return a Boolean from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERBoolean getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    public DERBoolean(
+        byte[] value) {
+        this.value = value[0];
+    }
+
+    public DERBoolean(
+        boolean value) {
+        this.value = (value) ? (byte) 0xff : (byte) 0;
+    }
+
+    public boolean isTrue() {
+        return (value != 0);
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        byte[] bytes = new byte[1];
+
+        bytes[0] = value;
+
+        out.writeEncoded(BOOLEAN, bytes);
+    }
+
+    protected boolean asn1Equals(
+        DERObject o) {
+        if ((o == null) || !(o instanceof DERBoolean)) {
+            return false;
+        }
+
+        return (value == ((DERBoolean) o).value);
+    }
+
+    public int hashCode() {
+        return value;
+    }
+
+
+    public String toString() {
+        return (value != 0) ? "TRUE" : "FALSE";
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERConstructedSequence.java b/src/java/org/apache/commons/ssl/asn1/DERConstructedSequence.java
new file mode 100644
index 0000000..f7cad53
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERConstructedSequence.java
@@ -0,0 +1,46 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+/** @deprecated use DERSequence. */
+public class DERConstructedSequence
+    extends ASN1Sequence {
+    public void addObject(
+        DEREncodable obj) {
+        super.addObject(obj);
+    }
+
+    public int getSize() {
+        return size();
+    }
+
+    /*
+     * A note on the implementation:
+     * <p>
+     * As DER requires the constructed, definite-length model to
+     * be used for structured types, this varies slightly from the
+     * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
+     * we also have to specify CONSTRUCTED, and the objects length.
+     */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        DEROutputStream dOut = new DEROutputStream(bOut);
+        Enumeration e = this.getObjects();
+
+        while (e.hasMoreElements()) {
+            Object obj = e.nextElement();
+
+            dOut.writeObject(obj);
+        }
+
+        dOut.close();
+
+        byte[] bytes = bOut.toByteArray();
+
+        out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERConstructedSet.java b/src/java/org/apache/commons/ssl/asn1/DERConstructedSet.java
new file mode 100644
index 0000000..50adf8e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERConstructedSet.java
@@ -0,0 +1,63 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+/** @deprecated use DERSet */
+public class DERConstructedSet
+    extends ASN1Set {
+    public DERConstructedSet() {
+    }
+
+    /** @param obj - a single object that makes up the set. */
+    public DERConstructedSet(
+        DEREncodable obj) {
+        this.addObject(obj);
+    }
+
+    /** @param v - a vector of objects making up the set. */
+    public DERConstructedSet(
+        DEREncodableVector v) {
+        for (int i = 0; i != v.size(); i++) {
+            this.addObject(v.get(i));
+        }
+    }
+
+    public void addObject(
+        DEREncodable obj) {
+        super.addObject(obj);
+    }
+
+    public int getSize() {
+        return size();
+    }
+
+    /*
+     * A note on the implementation:
+     * <p>
+     * As DER requires the constructed, definite-length model to
+     * be used for structured types, this varies slightly from the
+     * ASN.1 descriptions given. Rather than just outputing SET,
+     * we also have to specify CONSTRUCTED, and the objects length.
+     */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        DEROutputStream dOut = new DEROutputStream(bOut);
+        Enumeration e = this.getObjects();
+
+        while (e.hasMoreElements()) {
+            Object obj = e.nextElement();
+
+            dOut.writeObject(obj);
+        }
+
+        dOut.close();
+
+        byte[] bytes = bOut.toByteArray();
+
+        out.writeEncoded(SET | CONSTRUCTED, bytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DEREncodable.java b/src/java/org/apache/commons/ssl/asn1/DEREncodable.java
new file mode 100644
index 0000000..cbaebf9
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DEREncodable.java
@@ -0,0 +1,5 @@
+package org.apache.commons.ssl.asn1;
+
+public interface DEREncodable {
+    public DERObject getDERObject();
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DEREncodableVector.java b/src/java/org/apache/commons/ssl/asn1/DEREncodableVector.java
new file mode 100644
index 0000000..d441a44
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DEREncodableVector.java
@@ -0,0 +1,31 @@
+package org.apache.commons.ssl.asn1;
+
+import java.util.Vector;
+
+/**
+ * a general class for building up a vector of DER encodable objects -
+ * this will eventually be superceded by ASN1EncodableVector so you should
+ * use that class in preference.
+ */
+public class DEREncodableVector {
+    private Vector v = new Vector();
+
+    /** @deprecated use ASN1EncodableVector instead. */
+    public DEREncodableVector() {
+
+    }
+
+    public void add(
+        DEREncodable obj) {
+        v.addElement(obj);
+    }
+
+    public DEREncodable get(
+        int i) {
+        return (DEREncodable) v.elementAt(i);
+    }
+
+    public int size() {
+        return v.size();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DEREnumerated.java b/src/java/org/apache/commons/ssl/asn1/DEREnumerated.java
new file mode 100644
index 0000000..faacf13
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DEREnumerated.java
@@ -0,0 +1,96 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class DEREnumerated
+    extends ASN1Object {
+    byte[] bytes;
+
+    /**
+     * return an integer from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DEREnumerated getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DEREnumerated) {
+            return (DEREnumerated) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DEREnumerated(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an Enumerated from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DEREnumerated getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    public DEREnumerated(
+        int value) {
+        bytes = BigInteger.valueOf(value).toByteArray();
+    }
+
+    public DEREnumerated(
+        BigInteger value) {
+        bytes = value.toByteArray();
+    }
+
+    public DEREnumerated(
+        byte[] bytes) {
+        this.bytes = bytes;
+    }
+
+    public BigInteger getValue() {
+        return new BigInteger(bytes);
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(ENUMERATED, bytes);
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DEREnumerated)) {
+            return false;
+        }
+
+        DEREnumerated other = (DEREnumerated) o;
+
+        if (bytes.length != other.bytes.length) {
+            return false;
+        }
+
+        for (int i = 0; i != bytes.length; i++) {
+            if (bytes[i] != other.bytes[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public int hashCode() {
+        return this.getValue().hashCode();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERGeneralString.java b/src/java/org/apache/commons/ssl/asn1/DERGeneralString.java
new file mode 100644
index 0000000..d571a1d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERGeneralString.java
@@ -0,0 +1,75 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public class DERGeneralString
+    extends ASN1Object implements DERString {
+    private String string;
+
+    public static DERGeneralString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERGeneralString) {
+            return (DERGeneralString) obj;
+        }
+        if (obj instanceof ASN1OctetString) {
+            return new DERGeneralString(((ASN1OctetString) obj).getOctets());
+        }
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+        throw new IllegalArgumentException("illegal object in getInstance: "
+                                           + obj.getClass().getName());
+    }
+
+    public static DERGeneralString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    public DERGeneralString(byte[] string) {
+        char[] cs = new char[string.length];
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) (string[i] & 0xff);
+        }
+        this.string = new String(cs);
+    }
+
+    public DERGeneralString(String string) {
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    public byte[] getOctets() {
+        char[] cs = string.toCharArray();
+        byte[] bs = new byte[cs.length];
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+        return bs;
+    }
+
+    void encode(DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(GENERAL_STRING, this.getOctets());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+
+    boolean asn1Equals(DERObject o) {
+        if (!(o instanceof DERGeneralString)) {
+            return false;
+        }
+        DERGeneralString s = (DERGeneralString) o;
+        return this.getString().equals(s.getString());
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERGeneralizedTime.java b/src/java/org/apache/commons/ssl/asn1/DERGeneralizedTime.java
new file mode 100644
index 0000000..0e2de28
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERGeneralizedTime.java
@@ -0,0 +1,242 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+/** Generalized time object. */
+public class DERGeneralizedTime
+    extends ASN1Object {
+    String time;
+
+    /**
+     * return a generalized time from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERGeneralizedTime getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERGeneralizedTime) {
+            return (DERGeneralizedTime) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERGeneralizedTime(((ASN1OctetString) obj).getOctets());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return a Generalized Time object from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERGeneralizedTime getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /**
+     * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+     * for local time, or Z+-HHMM on the end, for difference between local
+     * time and UTC time. The fractional second amount f must consist of at
+     * least one number with trailing zeroes removed.
+     *
+     * @param time the time string.
+     * @throws IllegalArgumentException if String is an illegal format.
+     */
+    public DERGeneralizedTime(
+        String time) {
+        this.time = time;
+        try {
+            this.getDate();
+        }
+        catch (ParseException e) {
+            throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+        }
+    }
+
+    /** base constructer from a java.util.date object */
+    public DERGeneralizedTime(
+        Date time) {
+        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+        dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+        this.time = dateF.format(time);
+    }
+
+    DERGeneralizedTime(
+        byte[] bytes) {
+        //
+        // explicitly convert to characters
+        //
+        char[] dateC = new char[bytes.length];
+
+        for (int i = 0; i != dateC.length; i++) {
+            dateC[i] = (char) (bytes[i] & 0xff);
+        }
+
+        this.time = new String(dateC);
+    }
+
+    /**
+     * Return the time.
+     *
+     * @return The time string as it appeared in the encoded object.
+     */
+    public String getTimeString() {
+        return time;
+    }
+
+    /**
+     * return the time - always in the form of
+     * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+     * <p/>
+     * Normally in a certificate we would expect "Z" rather than "GMT",
+     * however adding the "GMT" means we can just use:
+     * <pre>
+     *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+     * </pre>
+     * To read in the time and get a date which is compatible with our local
+     * time zone.
+     */
+    public String getTime() {
+        //
+        // standardise the format.
+        //             
+        if (time.charAt(time.length() - 1) == 'Z') {
+            return time.substring(0, time.length() - 1) + "GMT+00:00";
+        } else {
+            int signPos = time.length() - 5;
+            char sign = time.charAt(signPos);
+            if (sign == '-' || sign == '+') {
+                return time.substring(0, signPos)
+                       + "GMT"
+                       + time.substring(signPos, signPos + 3)
+                       + ":"
+                       + time.substring(signPos + 3);
+            } else {
+                signPos = time.length() - 3;
+                sign = time.charAt(signPos);
+                if (sign == '-' || sign == '+') {
+                    return time.substring(0, signPos)
+                           + "GMT"
+                           + time.substring(signPos)
+                           + ":00";
+                }
+            }
+        }
+        return time + calculateGMTOffset();
+    }
+
+    private String calculateGMTOffset() {
+        String sign = "+";
+        TimeZone timeZone = TimeZone.getDefault();
+        int offset = timeZone.getRawOffset();
+        if (offset < 0) {
+            sign = "-";
+            offset = -offset;
+        }
+        int hours = offset / (60 * 60 * 1000);
+        int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+        try {
+            if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate())) {
+                hours += sign.equals("+") ? 1 : -1;
+            }
+        }
+        catch (ParseException e) {
+            // we'll do our best and ignore daylight savings
+        }
+
+        return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+    }
+
+    private String convert(int time) {
+        if (time < 10) {
+            return "0" + time;
+        }
+
+        return Integer.toString(time);
+    }
+
+    public Date getDate()
+        throws ParseException {
+        SimpleDateFormat dateF;
+        String d = time;
+
+        if (time.endsWith("Z")) {
+            if (hasFractionalSeconds()) {
+                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSS'Z'");
+            } else {
+                dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+            }
+
+            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+        } else if (time.indexOf('-') > 0 || time.indexOf('+') > 0) {
+            d = this.getTime();
+            if (hasFractionalSeconds()) {
+                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSSz");
+            } else {
+                dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+            }
+
+            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+        } else {
+            if (hasFractionalSeconds()) {
+                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSS");
+            } else {
+                dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+            }
+
+            dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+        }
+
+        return dateF.parse(d);
+    }
+
+    private boolean hasFractionalSeconds() {
+        return time.indexOf('.') == 14;
+    }
+
+    private byte[] getOctets() {
+        char[] cs = time.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(GENERALIZED_TIME, this.getOctets());
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERGeneralizedTime)) {
+            return false;
+        }
+
+        return time.equals(((DERGeneralizedTime) o).time);
+    }
+
+    public int hashCode() {
+        return time.hashCode();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERGenerator.java b/src/java/org/apache/commons/ssl/asn1/DERGenerator.java
new file mode 100644
index 0000000..359d931
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERGenerator.java
@@ -0,0 +1,108 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public abstract class DERGenerator
+    extends ASN1Generator {
+    private boolean _tagged = false;
+    private boolean _isExplicit;
+    private int _tagNo;
+
+    protected DERGenerator(
+        OutputStream out) {
+        super(out);
+    }
+
+    public DERGenerator(
+        OutputStream out,
+        int tagNo,
+        boolean isExplicit) {
+        super(out);
+
+        _tagged = true;
+        _isExplicit = isExplicit;
+        _tagNo = tagNo;
+    }
+
+    private void writeLength(
+        OutputStream out,
+        int length)
+        throws IOException {
+        if (length > 127) {
+            int size = 1;
+            int val = length;
+
+            while ((val >>>= 8) != 0) {
+                size++;
+            }
+
+            out.write((byte) (size | 0x80));
+
+            for (int i = (size - 1) * 8; i >= 0; i -= 8) {
+                out.write((byte) (length >> i));
+            }
+        } else {
+            out.write((byte) length);
+        }
+    }
+
+    void writeDEREncoded(
+        OutputStream out,
+        int tag,
+        byte[] bytes)
+        throws IOException {
+        out.write(tag);
+        writeLength(out, bytes.length);
+        out.write(bytes);
+    }
+
+    void writeDEREncoded(
+        int tag,
+        byte[] bytes)
+        throws IOException {
+        if (_tagged) {
+            int tagNum = _tagNo | DERTags.TAGGED;
+
+            if (_isExplicit) {
+                int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED;
+
+                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+                writeDEREncoded(bOut, tag, bytes);
+
+                writeDEREncoded(_out, newTag, bOut.toByteArray());
+            } else {
+                if ((tag & DERTags.CONSTRUCTED) != 0) {
+                    writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes);
+                } else {
+                    writeDEREncoded(_out, tagNum, bytes);
+                }
+            }
+        } else {
+            writeDEREncoded(_out, tag, bytes);
+        }
+    }
+
+    void writeDEREncoded(
+        OutputStream out,
+        int tag,
+        InputStream in)
+        throws IOException {
+        out.write(tag);
+
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+        int b = 0;
+        while ((b = in.read()) >= 0) {
+            bOut.write(b);
+        }
+
+        byte[] bytes = bOut.toByteArray();
+
+        writeLength(out, bytes.length);
+        out.write(bytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERIA5String.java b/src/java/org/apache/commons/ssl/asn1/DERIA5String.java
new file mode 100644
index 0000000..53d1abf
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERIA5String.java
@@ -0,0 +1,142 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER IA5String object - this is an ascii string. */
+public class DERIA5String
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return a IA5 string from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERIA5String getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERIA5String) {
+            return (DERIA5String) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERIA5String(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an IA5 String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERIA5String getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - with bytes. */
+    public DERIA5String(
+        byte[] string) {
+        char[] cs = new char[string.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) (string[i] & 0xff);
+        }
+
+        this.string = new String(cs);
+    }
+
+    /** basic constructor - without validation. */
+    public DERIA5String(
+        String string) {
+        this(string, false);
+    }
+
+    /**
+     * Constructor with optional validation.
+     *
+     * @param string   the base string to wrap.
+     * @param validate whether or not to check the string.
+     * @throws IllegalArgumentException if validate is true and the string
+     *                                  contains characters that should not be in an IA5String.
+     */
+    public DERIA5String(
+        String string,
+        boolean validate) {
+        if (validate && !isIA5String(string)) {
+            throw new IllegalArgumentException("string contains illegal characters");
+        }
+
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    public byte[] getOctets() {
+        char[] cs = string.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(IA5_STRING, this.getOctets());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERIA5String)) {
+            return false;
+        }
+
+        DERIA5String s = (DERIA5String) o;
+
+        return this.getString().equals(s.getString());
+    }
+
+    /**
+     * return true if the passed in String can be represented without
+     * loss as an IA5String, false otherwise.
+     *
+     * @return true if in printable set, false otherwise.
+     */
+    public static boolean isIA5String(
+        String str) {
+        for (int i = str.length() - 1; i >= 0; i--) {
+            char ch = str.charAt(i);
+
+            if (ch > 0x007f) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERInputStream.java b/src/java/org/apache/commons/ssl/asn1/DERInputStream.java
new file mode 100644
index 0000000..5d35bd3
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERInputStream.java
@@ -0,0 +1,237 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Don't use this class. It will eventually disappear, use ASN1InputStream.
+ * <br>
+ * This class is scheduled for removal.
+ *
+ * @deprecated use ASN1InputStream
+ */
+public class DERInputStream
+    extends FilterInputStream implements DERTags {
+    /** @deprecated use ASN1InputStream */
+    public DERInputStream(
+        InputStream is) {
+        super(is);
+    }
+
+    protected int readLength()
+        throws IOException {
+        int length = read();
+        if (length < 0) {
+            throw new IOException("EOF found when length expected");
+        }
+
+        if (length == 0x80) {
+            return -1;      // indefinite-length encoding
+        }
+
+        if (length > 127) {
+            int size = length & 0x7f;
+
+            if (size > 4) {
+                throw new IOException("DER length more than 4 bytes");
+            }
+
+            length = 0;
+            for (int i = 0; i < size; i++) {
+                int next = read();
+
+                if (next < 0) {
+                    throw new IOException("EOF found reading length");
+                }
+
+                length = (length << 8) + next;
+            }
+
+            if (length < 0) {
+                throw new IOException("corrupted stream - negative length found");
+            }
+        }
+
+        return length;
+    }
+
+    protected void readFully(
+        byte[] bytes)
+        throws IOException {
+        int left = bytes.length;
+
+        if (left == 0) {
+            return;
+        }
+
+        while (left > 0) {
+            int l = read(bytes, bytes.length - left, left);
+
+            if (l < 0) {
+                throw new EOFException("unexpected end of stream");
+            }
+
+            left -= l;
+        }
+    }
+
+    /**
+     * build an object given its tag and a byte stream to construct it
+     * from.
+     */
+    protected DERObject buildObject(
+        int tag,
+        byte[] bytes)
+        throws IOException {
+        switch (tag) {
+            case NULL:
+                return null;
+            case SEQUENCE | CONSTRUCTED:
+                ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
+                BERInputStream dIn = new BERInputStream(bIn);
+                DERConstructedSequence seq = new DERConstructedSequence();
+
+                try {
+                    for (; ;) {
+                        DERObject obj = dIn.readObject();
+
+                        seq.addObject(obj);
+                    }
+                }
+                catch (EOFException ex) {
+                    return seq;
+                }
+            case SET | CONSTRUCTED:
+                bIn = new ByteArrayInputStream(bytes);
+                dIn = new BERInputStream(bIn);
+
+                ASN1EncodableVector v = new ASN1EncodableVector();
+
+                try {
+                    for (; ;) {
+                        DERObject obj = dIn.readObject();
+
+                        v.add(obj);
+                    }
+                }
+                catch (EOFException ex) {
+                    return new DERConstructedSet(v);
+                }
+            case BOOLEAN:
+                return new DERBoolean(bytes);
+            case INTEGER:
+                return new DERInteger(bytes);
+            case ENUMERATED:
+                return new DEREnumerated(bytes);
+            case OBJECT_IDENTIFIER:
+                return new DERObjectIdentifier(bytes);
+            case BIT_STRING:
+                int padBits = bytes[0];
+                byte[] data = new byte[bytes.length - 1];
+
+                System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+
+                return new DERBitString(data, padBits);
+            case UTF8_STRING:
+                return new DERUTF8String(bytes);
+            case PRINTABLE_STRING:
+                return new DERPrintableString(bytes);
+            case IA5_STRING:
+                return new DERIA5String(bytes);
+            case T61_STRING:
+                return new DERT61String(bytes);
+            case VISIBLE_STRING:
+                return new DERVisibleString(bytes);
+            case UNIVERSAL_STRING:
+                return new DERUniversalString(bytes);
+            case GENERAL_STRING:
+                return new DERGeneralString(bytes);
+            case BMP_STRING:
+                return new DERBMPString(bytes);
+            case OCTET_STRING:
+                return new DEROctetString(bytes);
+            case UTC_TIME:
+                return new DERUTCTime(bytes);
+            case GENERALIZED_TIME:
+                return new DERGeneralizedTime(bytes);
+            default:
+                //
+                // with tagged object tag number is bottom 5 bits
+                //
+                if ((tag & TAGGED) != 0) {
+                    if ((tag & 0x1f) == 0x1f) {
+                        throw new IOException("unsupported high tag encountered");
+                    }
+
+                    if (bytes.length == 0)        // empty tag!
+                    {
+                        if ((tag & CONSTRUCTED) == 0) {
+                            return new DERTaggedObject(false, tag & 0x1f, new DERNull());
+                        } else {
+                            return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
+                        }
+                    }
+
+                    //
+                    // simple type - implicit... return an octet string
+                    //
+                    if ((tag & CONSTRUCTED) == 0) {
+                        return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
+                    }
+
+                    bIn = new ByteArrayInputStream(bytes);
+                    dIn = new BERInputStream(bIn);
+
+                    DEREncodable dObj = dIn.readObject();
+
+                    //
+                    // explicitly tagged (probably!) - if it isn't we'd have to
+                    // tell from the context
+                    //
+                    if (dIn.available() == 0) {
+                        return new DERTaggedObject(tag & 0x1f, dObj);
+                    }
+
+                    //
+                    // another implicit object, we'll create a sequence...
+                    //
+                    seq = new DERConstructedSequence();
+
+                    seq.addObject(dObj);
+
+                    try {
+                        for (; ;) {
+                            dObj = dIn.readObject();
+
+                            seq.addObject(dObj);
+                        }
+                    }
+                    catch (EOFException ex) {
+                        // ignore --
+                    }
+
+                    return new DERTaggedObject(false, tag & 0x1f, seq);
+                }
+
+                return new DERUnknownTag(tag, bytes);
+        }
+    }
+
+    public DERObject readObject()
+        throws IOException {
+        int tag = read();
+        if (tag == -1) {
+            throw new EOFException();
+        }
+
+        int length = readLength();
+        byte[] bytes = new byte[length];
+
+        readFully(bytes);
+
+        return buildObject(tag, bytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERInteger.java b/src/java/org/apache/commons/ssl/asn1/DERInteger.java
new file mode 100644
index 0000000..4265efe
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERInteger.java
@@ -0,0 +1,114 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class DERInteger
+    extends ASN1Object {
+    byte[] bytes;
+
+    /**
+     * return an integer from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERInteger getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERInteger) {
+            return (DERInteger) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERInteger(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an Integer from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERInteger getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    public DERInteger(
+        int value) {
+        bytes = BigInteger.valueOf(value).toByteArray();
+    }
+
+    public DERInteger(
+        BigInteger value) {
+        bytes = value.toByteArray();
+    }
+
+    public DERInteger(
+        byte[] bytes) {
+        this.bytes = bytes;
+    }
+
+    public BigInteger getValue() {
+        return new BigInteger(bytes);
+    }
+
+    /**
+     * in some cases positive values get crammed into a space,
+     * that's not quite big enough...
+     */
+    public BigInteger getPositiveValue() {
+        return new BigInteger(1, bytes);
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(INTEGER, bytes);
+    }
+
+    public int hashCode() {
+        int value = 0;
+
+        for (int i = 0; i != bytes.length; i++) {
+            value ^= (bytes[i] & 0xff) << (i % 4);
+        }
+
+        return value;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERInteger)) {
+            return false;
+        }
+
+        DERInteger other = (DERInteger) o;
+
+        if (bytes.length != other.bytes.length) {
+            return false;
+        }
+
+        for (int i = 0; i != bytes.length; i++) {
+            if (bytes[i] != other.bytes[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public String toString() {
+        return getValue().toString();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERNull.java b/src/java/org/apache/commons/ssl/asn1/DERNull.java
new file mode 100644
index 0000000..774cb6e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERNull.java
@@ -0,0 +1,20 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** A NULL object. */
+public class DERNull
+    extends ASN1Null {
+    public static final DERNull INSTANCE = new DERNull();
+
+    byte[] zeroBytes = new byte[0];
+
+    public DERNull() {
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(NULL, zeroBytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERNumericString.java b/src/java/org/apache/commons/ssl/asn1/DERNumericString.java
new file mode 100644
index 0000000..9b72196
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERNumericString.java
@@ -0,0 +1,148 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }. */
+public class DERNumericString
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return a Numeric string from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERNumericString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERNumericString) {
+            return (DERNumericString) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERNumericString(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an Numeric String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERNumericString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - with bytes. */
+    public DERNumericString(
+        byte[] string) {
+        char[] cs = new char[string.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) (string[i] & 0xff);
+        }
+
+        this.string = new String(cs);
+    }
+
+    /** basic constructor -  without validation.. */
+    public DERNumericString(
+        String string) {
+        this(string, false);
+    }
+
+    /**
+     * Constructor with optional validation.
+     *
+     * @param string   the base string to wrap.
+     * @param validate whether or not to check the string.
+     * @throws IllegalArgumentException if validate is true and the string
+     *                                  contains characters that should not be in a NumericString.
+     */
+    public DERNumericString(
+        String string,
+        boolean validate) {
+        if (validate && !isNumericString(string)) {
+            throw new IllegalArgumentException("string contains illegal characters");
+        }
+
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    public byte[] getOctets() {
+        char[] cs = string.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(NUMERIC_STRING, this.getOctets());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERNumericString)) {
+            return false;
+        }
+
+        DERNumericString s = (DERNumericString) o;
+
+        return this.getString().equals(s.getString());
+    }
+
+    /**
+     * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+     *
+     * @param str string to validate.
+     * @return true if numeric, fale otherwise.
+     */
+    public static boolean isNumericString(
+        String str) {
+        for (int i = str.length() - 1; i >= 0; i--) {
+            char ch = str.charAt(i);
+
+            if (ch > 0x007f) {
+                return false;
+            }
+
+            if (('0' <= ch && ch <= '9') || ch == ' ') {
+                continue;
+            }
+
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERObject.java b/src/java/org/apache/commons/ssl/asn1/DERObject.java
new file mode 100644
index 0000000..df6dd86
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERObject.java
@@ -0,0 +1,18 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public abstract class DERObject
+    extends ASN1Encodable
+    implements DERTags {
+    public DERObject toASN1Object() {
+        return this;
+    }
+
+    public abstract int hashCode();
+
+    public abstract boolean equals(Object o);
+
+    abstract void encode(DEROutputStream out)
+        throws IOException;
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERObjectIdentifier.java b/src/java/org/apache/commons/ssl/asn1/DERObjectIdentifier.java
new file mode 100644
index 0000000..f53153f
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERObjectIdentifier.java
@@ -0,0 +1,245 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+public class DERObjectIdentifier
+    extends ASN1Object {
+    String identifier;
+
+    /**
+     * return an OID from the passed in object
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERObjectIdentifier getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERObjectIdentifier) {
+            return (DERObjectIdentifier) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERObjectIdentifier(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an Object Identifier from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERObjectIdentifier getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+
+    DERObjectIdentifier(
+        byte[] bytes) {
+        StringBuffer objId = new StringBuffer();
+        long value = 0;
+        BigInteger bigValue = null;
+        boolean first = true;
+
+        for (int i = 0; i != bytes.length; i++) {
+            int b = bytes[i] & 0xff;
+
+            if (value < 0x80000000000000L) {
+                value = value * 128 + (b & 0x7f);
+                if ((b & 0x80) == 0)             // end of number reached
+                {
+                    if (first) {
+                        switch ((int) value / 40) {
+                            case 0:
+                                objId.append('0');
+                                break;
+                            case 1:
+                                objId.append('1');
+                                value -= 40;
+                                break;
+                            default:
+                                objId.append('2');
+                                value -= 80;
+                        }
+                        first = false;
+                    }
+
+                    objId.append('.');
+                    objId.append(value);
+                    value = 0;
+                }
+            } else {
+                if (bigValue == null) {
+                    bigValue = BigInteger.valueOf(value);
+                }
+                bigValue = bigValue.shiftLeft(7);
+                bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
+                if ((b & 0x80) == 0) {
+                    objId.append('.');
+                    objId.append(bigValue);
+                    bigValue = null;
+                    value = 0;
+                }
+            }
+        }
+
+        this.identifier = objId.toString();
+    }
+
+    public DERObjectIdentifier(
+        String identifier) {
+        if (!isValidIdentifier(identifier)) {
+            throw new IllegalArgumentException("string " + identifier + " not an OID");
+        }
+
+        this.identifier = identifier;
+    }
+
+    public String getId() {
+        return identifier;
+    }
+
+    private void writeField(
+        OutputStream out,
+        long fieldValue)
+        throws IOException {
+        if (fieldValue >= (1L << 7)) {
+            if (fieldValue >= (1L << 14)) {
+                if (fieldValue >= (1L << 21)) {
+                    if (fieldValue >= (1L << 28)) {
+                        if (fieldValue >= (1L << 35)) {
+                            if (fieldValue >= (1L << 42)) {
+                                if (fieldValue >= (1L << 49)) {
+                                    if (fieldValue >= (1L << 56)) {
+                                        out.write((int) (fieldValue >> 56) | 0x80);
+                                    }
+                                    out.write((int) (fieldValue >> 49) | 0x80);
+                                }
+                                out.write((int) (fieldValue >> 42) | 0x80);
+                            }
+                            out.write((int) (fieldValue >> 35) | 0x80);
+                        }
+                        out.write((int) (fieldValue >> 28) | 0x80);
+                    }
+                    out.write((int) (fieldValue >> 21) | 0x80);
+                }
+                out.write((int) (fieldValue >> 14) | 0x80);
+            }
+            out.write((int) (fieldValue >> 7) | 0x80);
+        }
+        out.write((int) fieldValue & 0x7f);
+    }
+
+    private void writeField(
+        OutputStream out,
+        BigInteger fieldValue)
+        throws IOException {
+        int byteCount = (fieldValue.bitLength() + 6) / 7;
+        if (byteCount == 0) {
+            out.write(0);
+        } else {
+            BigInteger tmpValue = fieldValue;
+            byte[] tmp = new byte[byteCount];
+            for (int i = byteCount - 1; i >= 0; i--) {
+                tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
+                tmpValue = tmpValue.shiftRight(7);
+            }
+            tmp[byteCount - 1] &= 0x7f;
+            out.write(tmp);
+        }
+
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        OIDTokenizer tok = new OIDTokenizer(identifier);
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        DEROutputStream dOut = new DEROutputStream(bOut);
+
+        writeField(bOut,
+            Integer.parseInt(tok.nextToken()) * 40
+            + Integer.parseInt(tok.nextToken()));
+
+        while (tok.hasMoreTokens()) {
+            String token = tok.nextToken();
+            if (token.length() < 18) {
+                writeField(bOut, Long.parseLong(token));
+            } else {
+                writeField(bOut, new BigInteger(token));
+            }
+        }
+
+        dOut.close();
+
+        byte[] bytes = bOut.toByteArray();
+
+        out.writeEncoded(OBJECT_IDENTIFIER, bytes);
+    }
+
+    public int hashCode() {
+        return identifier.hashCode();
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERObjectIdentifier)) {
+            return false;
+        }
+
+        return identifier.equals(((DERObjectIdentifier) o).identifier);
+    }
+
+    public String toString() {
+        return getId();
+    }
+
+    private static boolean isValidIdentifier(
+        String identifier) {
+        if (identifier.length() < 3
+            || identifier.charAt(1) != '.') {
+            return false;
+        }
+
+        char first = identifier.charAt(0);
+        if (first < '0' || first > '2') {
+            return false;
+        }
+
+        boolean periodAllowed = false;
+        for (int i = identifier.length() - 1; i >= 2; i--) {
+            char ch = identifier.charAt(i);
+
+            if ('0' <= ch && ch <= '9') {
+                periodAllowed = true;
+                continue;
+            }
+
+            if (ch == '.') {
+                if (!periodAllowed) {
+                    return false;
+                }
+
+                periodAllowed = false;
+                continue;
+            }
+
+            return false;
+        }
+
+        return periodAllowed;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DEROctetString.java b/src/java/org/apache/commons/ssl/asn1/DEROctetString.java
new file mode 100644
index 0000000..113a99c
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DEROctetString.java
@@ -0,0 +1,23 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+public class DEROctetString
+    extends ASN1OctetString {
+    /** @param string the octets making up the octet string. */
+    public DEROctetString(
+        byte[] string) {
+        super(string);
+    }
+
+    public DEROctetString(
+        DEREncodable obj) {
+        super(obj);
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(OCTET_STRING, string);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DEROutputStream.java b/src/java/org/apache/commons/ssl/asn1/DEROutputStream.java
new file mode 100644
index 0000000..4a85500
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DEROutputStream.java
@@ -0,0 +1,73 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class DEROutputStream
+    extends FilterOutputStream implements DERTags {
+    public DEROutputStream(
+        OutputStream os) {
+        super(os);
+    }
+
+    private void writeLength(
+        int length)
+        throws IOException {
+        if (length > 127) {
+            int size = 1;
+            int val = length;
+
+            while ((val >>>= 8) != 0) {
+                size++;
+            }
+
+            write((byte) (size | 0x80));
+
+            for (int i = (size - 1) * 8; i >= 0; i -= 8) {
+                write((byte) (length >> i));
+            }
+        } else {
+            write((byte) length);
+        }
+    }
+
+    void writeEncoded(
+        int tag,
+        byte[] bytes)
+        throws IOException {
+        write(tag);
+        writeLength(bytes.length);
+        write(bytes);
+    }
+
+    protected void writeNull()
+        throws IOException {
+        write(NULL);
+        write(0x00);
+    }
+
+    public void write(byte[] buf)
+        throws IOException {
+        out.write(buf, 0, buf.length);
+    }
+
+    public void write(byte[] buf, int offSet, int len)
+        throws IOException {
+        out.write(buf, offSet, len);
+    }
+
+    public void writeObject(
+        Object obj)
+        throws IOException {
+        if (obj == null) {
+            writeNull();
+        } else if (obj instanceof DERObject) {
+            ((DERObject) obj).encode(this);
+        } else if (obj instanceof DEREncodable) {
+            ((DEREncodable) obj).getDERObject().encode(this);
+        } else {
+            throw new IOException("object not DEREncodable");
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERPrintableString.java b/src/java/org/apache/commons/ssl/asn1/DERPrintableString.java
new file mode 100644
index 0000000..48bd5c7
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERPrintableString.java
@@ -0,0 +1,172 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER PrintableString object. */
+public class DERPrintableString
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return a printable string from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERPrintableString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERPrintableString) {
+            return (DERPrintableString) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERPrintableString(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return a Printable String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERPrintableString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - byte encoded string. */
+    public DERPrintableString(
+        byte[] string) {
+        char[] cs = new char[string.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) (string[i] & 0xff);
+        }
+
+        this.string = new String(cs);
+    }
+
+    /** basic constructor - this does not validate the string */
+    public DERPrintableString(
+        String string) {
+        this(string, false);
+    }
+
+    /**
+     * Constructor with optional validation.
+     *
+     * @param string   the base string to wrap.
+     * @param validate whether or not to check the string.
+     * @throws IllegalArgumentException if validate is true and the string
+     *                                  contains characters that should not be in a PrintableString.
+     */
+    public DERPrintableString(
+        String string,
+        boolean validate) {
+        if (validate && !isPrintableString(string)) {
+            throw new IllegalArgumentException("string contains illegal characters");
+        }
+
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public byte[] getOctets() {
+        char[] cs = string.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(PRINTABLE_STRING, this.getOctets());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERPrintableString)) {
+            return false;
+        }
+
+        DERPrintableString s = (DERPrintableString) o;
+
+        return this.getString().equals(s.getString());
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    /**
+     * return true if the passed in String can be represented without
+     * loss as a PrintableString, false otherwise.
+     *
+     * @return true if in printable set, false otherwise.
+     */
+    public static boolean isPrintableString(
+        String str) {
+        for (int i = str.length() - 1; i >= 0; i--) {
+            char ch = str.charAt(i);
+
+            if (ch > 0x007f) {
+                return false;
+            }
+
+            if ('a' <= ch && ch <= 'z') {
+                continue;
+            }
+
+            if ('A' <= ch && ch <= 'Z') {
+                continue;
+            }
+
+            if ('0' <= ch && ch <= '9') {
+                continue;
+            }
+
+            switch (ch) {
+                case ' ':
+                case '\'':
+                case '(':
+                case ')':
+                case '+':
+                case '-':
+                case '.':
+                case ':':
+                case '=':
+                case '?':
+                case '/':
+                case ',':
+                    continue;
+            }
+
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERSequence.java b/src/java/org/apache/commons/ssl/asn1/DERSequence.java
new file mode 100644
index 0000000..9416a2d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERSequence.java
@@ -0,0 +1,62 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class DERSequence
+    extends ASN1Sequence {
+    /** create an empty sequence */
+    public DERSequence() {
+    }
+
+    /** create a sequence containing one object */
+    public DERSequence(
+        DEREncodable obj) {
+        this.addObject(obj);
+    }
+
+    /** create a sequence containing a vector of objects. */
+    public DERSequence(
+        DEREncodableVector v) {
+        for (int i = 0; i != v.size(); i++) {
+            this.addObject(v.get(i));
+        }
+    }
+
+    /** create a sequence containing an array of objects. */
+    public DERSequence(
+        ASN1Encodable[] a) {
+        for (int i = 0; i != a.length; i++) {
+            this.addObject(a[i]);
+        }
+    }
+
+    /*
+    * A note on the implementation:
+    * <p>
+    * As DER requires the constructed, definite-length model to
+    * be used for structured types, this varies slightly from the
+    * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
+    * we also have to specify CONSTRUCTED, and the objects length.
+    */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        DEROutputStream dOut = new DEROutputStream(bOut);
+        Enumeration e = this.getObjects();
+
+        while (e.hasMoreElements()) {
+            Object obj = e.nextElement();
+
+            dOut.writeObject(obj);
+        }
+
+        dOut.close();
+
+        byte[] bytes = bOut.toByteArray();
+
+        out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERSequenceGenerator.java b/src/java/org/apache/commons/ssl/asn1/DERSequenceGenerator.java
new file mode 100644
index 0000000..4fd7003
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERSequenceGenerator.java
@@ -0,0 +1,39 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class DERSequenceGenerator
+    extends DERGenerator {
+    private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
+
+    public DERSequenceGenerator(
+        OutputStream out)
+        throws IOException {
+        super(out);
+    }
+
+    public DERSequenceGenerator(
+        OutputStream out,
+        int tagNo,
+        boolean isExplicit)
+        throws IOException {
+        super(out, tagNo, isExplicit);
+    }
+
+    public void addObject(
+        DEREncodable object)
+        throws IOException {
+        object.getDERObject().encode(new DEROutputStream(_bOut));
+    }
+
+    public OutputStream getRawOutputStream() {
+        return _bOut;
+    }
+
+    public void close()
+        throws IOException {
+        writeDEREncoded(DERTags.CONSTRUCTED | DERTags.SEQUENCE, _bOut.toByteArray());
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERSet.java b/src/java/org/apache/commons/ssl/asn1/DERSet.java
new file mode 100644
index 0000000..4fbb0f8
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERSet.java
@@ -0,0 +1,76 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+/** A DER encoded set object */
+public class DERSet
+    extends ASN1Set {
+    /** create an empty set */
+    public DERSet() {
+    }
+
+    /** @param obj - a single object that makes up the set. */
+    public DERSet(
+        DEREncodable obj) {
+        this.addObject(obj);
+    }
+
+    /** @param v - a vector of objects making up the set. */
+    public DERSet(
+        DEREncodableVector v) {
+        this(v, true);
+    }
+
+    /** create a set from an array of objects. */
+    public DERSet(
+        ASN1Encodable[] a) {
+        for (int i = 0; i != a.length; i++) {
+            this.addObject(a[i]);
+        }
+
+        this.sort();
+    }
+
+    /** @param v - a vector of objects making up the set. */
+    DERSet(
+        DEREncodableVector v,
+        boolean needsSorting) {
+        for (int i = 0; i != v.size(); i++) {
+            this.addObject(v.get(i));
+        }
+
+        if (needsSorting) {
+            this.sort();
+        }
+    }
+
+    /*
+     * A note on the implementation:
+     * <p>
+     * As DER requires the constructed, definite-length model to
+     * be used for structured types, this varies slightly from the
+     * ASN.1 descriptions given. Rather than just outputing SET,
+     * we also have to specify CONSTRUCTED, and the objects length.
+     */
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        DEROutputStream dOut = new DEROutputStream(bOut);
+        Enumeration e = this.getObjects();
+
+        while (e.hasMoreElements()) {
+            Object obj = e.nextElement();
+
+            dOut.writeObject(obj);
+        }
+
+        dOut.close();
+
+        byte[] bytes = bOut.toByteArray();
+
+        out.writeEncoded(SET | CONSTRUCTED, bytes);
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERString.java b/src/java/org/apache/commons/ssl/asn1/DERString.java
new file mode 100644
index 0000000..71565b0
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERString.java
@@ -0,0 +1,6 @@
+package org.apache.commons.ssl.asn1;
+
+/** basic interface for DER string objects. */
+public interface DERString {
+    public String getString();
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERT61String.java b/src/java/org/apache/commons/ssl/asn1/DERT61String.java
new file mode 100644
index 0000000..bd92539
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERT61String.java
@@ -0,0 +1,103 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER T61String (also the teletex string) */
+public class DERT61String
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return a T61 string from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERT61String getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERT61String) {
+            return (DERT61String) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERT61String(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an T61 String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERT61String getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - with bytes. */
+    public DERT61String(
+        byte[] string) {
+        char[] cs = new char[string.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) (string[i] & 0xff);
+        }
+
+        this.string = new String(cs);
+    }
+
+    /** basic constructor - with string. */
+    public DERT61String(
+        String string) {
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(T61_STRING, this.getOctets());
+    }
+
+    public byte[] getOctets() {
+        char[] cs = string.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERT61String)) {
+            return false;
+        }
+
+        return this.getString().equals(((DERT61String) o).getString());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERTaggedObject.java b/src/java/org/apache/commons/ssl/asn1/DERTaggedObject.java
new file mode 100644
index 0000000..6dd457c
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERTaggedObject.java
@@ -0,0 +1,74 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * DER TaggedObject - in ASN.1 nottation this is any object proceeded by
+ * a [n] where n is some number - these are assume to follow the construction
+ * rules (as with sequences).
+ */
+public class DERTaggedObject
+    extends ASN1TaggedObject {
+    /**
+     * @param tagNo the tag number for this object.
+     * @param obj   the tagged object.
+     */
+    public DERTaggedObject(
+        int tagNo,
+        DEREncodable obj) {
+        super(tagNo, obj);
+    }
+
+    /**
+     * @param explicit true if an explicitly tagged object.
+     * @param tagNo    the tag number for this object.
+     * @param obj      the tagged object.
+     */
+    public DERTaggedObject(
+        boolean explicit,
+        int tagNo,
+        DEREncodable obj) {
+        super(explicit, tagNo, obj);
+    }
+
+    /**
+     * create an implicitly tagged object that contains a zero
+     * length sequence.
+     */
+    public DERTaggedObject(
+        int tagNo) {
+        super(false, tagNo, new DERSequence());
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        if (!empty) {
+            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+            DEROutputStream dOut = new DEROutputStream(bOut);
+
+            dOut.writeObject(obj);
+            dOut.close();
+
+            byte[] bytes = bOut.toByteArray();
+
+            if (explicit) {
+                out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, bytes);
+            } else {
+                //
+                // need to mark constructed types...
+                //
+                if ((bytes[0] & CONSTRUCTED) != 0) {
+                    bytes[0] = (byte) (CONSTRUCTED | TAGGED | tagNo);
+                } else {
+                    bytes[0] = (byte) (TAGGED | tagNo);
+                }
+
+                out.write(bytes);
+            }
+        } else {
+            out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, new byte[0]);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERTags.java b/src/java/org/apache/commons/ssl/asn1/DERTags.java
new file mode 100644
index 0000000..9fb9b41
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERTags.java
@@ -0,0 +1,35 @@
+package org.apache.commons.ssl.asn1;
+
+public interface DERTags {
+    public static final int BOOLEAN = 0x01;
+    public static final int INTEGER = 0x02;
+    public static final int BIT_STRING = 0x03;
+    public static final int OCTET_STRING = 0x04;
+    public static final int NULL = 0x05;
+    public static final int OBJECT_IDENTIFIER = 0x06;
+    public static final int EXTERNAL = 0x08;
+    public static final int ENUMERATED = 0x0a;
+    public static final int SEQUENCE = 0x10;
+    public static final int SEQUENCE_OF = 0x10; // for completeness
+    public static final int SET = 0x11;
+    public static final int SET_OF = 0x11; // for completeness
+
+
+    public static final int NUMERIC_STRING = 0x12;
+    public static final int PRINTABLE_STRING = 0x13;
+    public static final int T61_STRING = 0x14;
+    public static final int VIDEOTEX_STRING = 0x15;
+    public static final int IA5_STRING = 0x16;
+    public static final int UTC_TIME = 0x17;
+    public static final int GENERALIZED_TIME = 0x18;
+    public static final int GRAPHIC_STRING = 0x19;
+    public static final int VISIBLE_STRING = 0x1a;
+    public static final int GENERAL_STRING = 0x1b;
+    public static final int UNIVERSAL_STRING = 0x1c;
+    public static final int BMP_STRING = 0x1e;
+    public static final int UTF8_STRING = 0x0c;
+
+    public static final int CONSTRUCTED = 0x20;
+    public static final int APPLICATION = 0x40;
+    public static final int TAGGED = 0x80;
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERUTCTime.java b/src/java/org/apache/commons/ssl/asn1/DERUTCTime.java
new file mode 100644
index 0000000..c858e0c
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERUTCTime.java
@@ -0,0 +1,214 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+/** UTC time object. */
+public class DERUTCTime
+    extends ASN1Object {
+    String time;
+
+    /**
+     * return an UTC Time from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERUTCTime getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERUTCTime) {
+            return (DERUTCTime) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERUTCTime(((ASN1OctetString) obj).getOctets());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return an UTC Time from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERUTCTime getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /**
+     * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+     * never encoded. When you're creating one of these objects from scratch, that's
+     * what you want to use, otherwise we'll try to deal with whatever gets read from
+     * the input stream... (this is why the input format is different from the getTime()
+     * method output).
+     * <p/>
+     *
+     * @param time the time string.
+     */
+    public DERUTCTime(
+        String time) {
+        this.time = time;
+        try {
+            this.getDate();
+        }
+        catch (ParseException e) {
+            throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+        }
+    }
+
+    /** base constructer from a java.util.date object */
+    public DERUTCTime(
+        Date time) {
+        SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
+
+        dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+        this.time = dateF.format(time);
+    }
+
+    DERUTCTime(
+        byte[] bytes) {
+        //
+        // explicitly convert to characters
+        //
+        char[] dateC = new char[bytes.length];
+
+        for (int i = 0; i != dateC.length; i++) {
+            dateC[i] = (char) (bytes[i] & 0xff);
+        }
+
+        this.time = new String(dateC);
+    }
+
+    /**
+     * return the time as a date based on whatever a 2 digit year will return. For
+     * standardised processing use getAdjustedDate().
+     *
+     * @return the resulting date
+     * @throws ParseException if the date string cannot be parsed.
+     */
+    public Date getDate()
+        throws ParseException {
+        SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
+
+        return dateF.parse(getTime());
+    }
+
+    /**
+     * return the time as an adjusted date
+     * in the range of 1950 - 2049.
+     *
+     * @return a date in the range of 1950 to 2049.
+     * @throws ParseException if the date string cannot be parsed.
+     */
+    public Date getAdjustedDate()
+        throws ParseException {
+        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+
+        dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+        return dateF.parse(getAdjustedTime());
+    }
+
+    /**
+     * return the time - always in the form of
+     * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+     * <p/>
+     * Normally in a certificate we would expect "Z" rather than "GMT",
+     * however adding the "GMT" means we can just use:
+     * <pre>
+     *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
+     * </pre>
+     * To read in the time and get a date which is compatible with our local
+     * time zone.
+     * <p/>
+     * <b>Note:</b> In some cases, due to the local date processing, this
+     * may lead to unexpected results. If you want to stick the normal
+     * convention of 1950 to 2049 use the getAdjustedTime() method.
+     */
+    public String getTime() {
+        //
+        // standardise the format.
+        //
+        if (time.indexOf('-') < 0 && time.indexOf('+') < 0) {
+            if (time.length() == 11) {
+                return time.substring(0, 10) + "00GMT+00:00";
+            } else {
+                return time.substring(0, 12) + "GMT+00:00";
+            }
+        } else {
+            int index = time.indexOf('-');
+            if (index < 0) {
+                index = time.indexOf('+');
+            }
+            String d = time;
+
+            if (index == time.length() - 3) {
+                d += "00";
+            }
+
+            if (index == 10) {
+                return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
+            } else {
+                return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
+            }
+        }
+    }
+
+    /**
+     * return a time string as an adjusted date with a 4 digit year. This goes
+     * in the range of 1950 - 2049.
+     */
+    public String getAdjustedTime() {
+        String d = this.getTime();
+
+        if (d.charAt(0) < '5') {
+            return "20" + d;
+        } else {
+            return "19" + d;
+        }
+    }
+
+    private byte[] getOctets() {
+        char[] cs = time.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(UTC_TIME, this.getOctets());
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERUTCTime)) {
+            return false;
+        }
+
+        return time.equals(((DERUTCTime) o).time);
+    }
+
+    public int hashCode() {
+        return time.hashCode();
+    }
+
+    public String toString() {
+        return time;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERUTF8String.java b/src/java/org/apache/commons/ssl/asn1/DERUTF8String.java
new file mode 100644
index 0000000..768c525
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERUTF8String.java
@@ -0,0 +1,83 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER UTF8String object. */
+public class DERUTF8String
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return an UTF8 string from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERUTF8String getInstance(Object obj) {
+        if (obj == null || obj instanceof DERUTF8String) {
+            return (DERUTF8String) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERUTF8String(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: "
+                                           + obj.getClass().getName());
+    }
+
+    /**
+     * return an UTF8 String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly tagged false
+     *                 otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot be converted.
+     */
+    public static DERUTF8String getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - byte encoded string. */
+    DERUTF8String(byte[] string) {
+        this.string = Strings.fromUTF8ByteArray(string);
+    }
+
+    /** basic constructor */
+    public DERUTF8String(String string) {
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+
+    boolean asn1Equals(DERObject o) {
+        if (!(o instanceof DERUTF8String)) {
+            return false;
+        }
+
+        DERUTF8String s = (DERUTF8String) o;
+
+        return this.getString().equals(s.getString());
+    }
+
+    void encode(DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(UTF8_STRING, Strings.toUTF8ByteArray(string));
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERUniversalString.java b/src/java/org/apache/commons/ssl/asn1/DERUniversalString.java
new file mode 100644
index 0000000..29be4bf
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERUniversalString.java
@@ -0,0 +1,100 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/** DER UniversalString object. */
+public class DERUniversalString
+    extends ASN1Object
+    implements DERString {
+    private static final char[] table = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+    private byte[] string;
+
+    /**
+     * return a Universal String from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERUniversalString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERUniversalString) {
+            return (DERUniversalString) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERUniversalString(((ASN1OctetString) obj).getOctets());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return a Universal String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERUniversalString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - byte encoded string. */
+    public DERUniversalString(
+        byte[] string) {
+        this.string = string;
+    }
+
+    public String getString() {
+        StringBuffer buf = new StringBuffer("#");
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+        try {
+            aOut.writeObject(this);
+        }
+        catch (IOException e) {
+            throw new RuntimeException("internal error encoding BitString");
+        }
+
+        byte[] string = bOut.toByteArray();
+
+        for (int i = 0; i != string.length; i++) {
+            buf.append(table[(string[i] >>> 4) & 0xf]);
+            buf.append(table[string[i] & 0xf]);
+        }
+
+        return buf.toString();
+    }
+
+    public String toString() {
+        return getString();
+    }
+
+    public byte[] getOctets() {
+        return string;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERUniversalString)) {
+            return false;
+        }
+
+        return this.getString().equals(((DERUniversalString) o).getString());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERUnknownTag.java b/src/java/org/apache/commons/ssl/asn1/DERUnknownTag.java
new file mode 100644
index 0000000..5a02fde
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERUnknownTag.java
@@ -0,0 +1,71 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** We insert one of these when we find a tag we don't recognise. */
+public class DERUnknownTag
+    extends DERObject {
+    int tag;
+    byte[] data;
+
+    /**
+     * @param tag  the tag value.
+     * @param data the octets making up the time.
+     */
+    public DERUnknownTag(
+        int tag,
+        byte[] data) {
+        this.tag = tag;
+        this.data = data;
+    }
+
+    public int getTag() {
+        return tag;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(tag, data);
+    }
+
+    public boolean equals(
+        Object o) {
+        if (!(o instanceof DERUnknownTag)) {
+            return false;
+        }
+
+        DERUnknownTag other = (DERUnknownTag) o;
+
+        if (tag != other.tag) {
+            return false;
+        }
+
+        if (data.length != other.data.length) {
+            return false;
+        }
+
+        for (int i = 0; i < data.length; i++) {
+            if (data[i] != other.data[i]) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public int hashCode() {
+        byte[] b = this.getData();
+        int value = 0;
+
+        for (int i = 0; i != b.length; i++) {
+            value ^= (b[i] & 0xff) << (i % 4);
+        }
+
+        return value ^ this.getTag();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DERVisibleString.java b/src/java/org/apache/commons/ssl/asn1/DERVisibleString.java
new file mode 100644
index 0000000..0b8ec89
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DERVisibleString.java
@@ -0,0 +1,103 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+
+/** DER VisibleString object. */
+public class DERVisibleString
+    extends ASN1Object
+    implements DERString {
+    String string;
+
+    /**
+     * return a Visible String from the passed in object.
+     *
+     * @throws IllegalArgumentException if the object cannot be converted.
+     */
+    public static DERVisibleString getInstance(
+        Object obj) {
+        if (obj == null || obj instanceof DERVisibleString) {
+            return (DERVisibleString) obj;
+        }
+
+        if (obj instanceof ASN1OctetString) {
+            return new DERVisibleString(((ASN1OctetString) obj).getOctets());
+        }
+
+        if (obj instanceof ASN1TaggedObject) {
+            return getInstance(((ASN1TaggedObject) obj).getObject());
+        }
+
+        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+    }
+
+    /**
+     * return a Visible String from a tagged object.
+     *
+     * @param obj      the tagged object holding the object we want
+     * @param explicit true if the object is meant to be explicitly
+     *                 tagged false otherwise.
+     * @throws IllegalArgumentException if the tagged object cannot
+     *                                  be converted.
+     */
+    public static DERVisibleString getInstance(
+        ASN1TaggedObject obj,
+        boolean explicit) {
+        return getInstance(obj.getObject());
+    }
+
+    /** basic constructor - byte encoded string. */
+    public DERVisibleString(
+        byte[] string) {
+        char[] cs = new char[string.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            cs[i] = (char) (string[i] & 0xff);
+        }
+
+        this.string = new String(cs);
+    }
+
+    /** basic constructor */
+    public DERVisibleString(
+        String string) {
+        this.string = string;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public String toString() {
+        return string;
+    }
+
+    public byte[] getOctets() {
+        char[] cs = string.toCharArray();
+        byte[] bs = new byte[cs.length];
+
+        for (int i = 0; i != cs.length; i++) {
+            bs[i] = (byte) cs[i];
+        }
+
+        return bs;
+    }
+
+    void encode(
+        DEROutputStream out)
+        throws IOException {
+        out.writeEncoded(VISIBLE_STRING, this.getOctets());
+    }
+
+    boolean asn1Equals(
+        DERObject o) {
+        if (!(o instanceof DERVisibleString)) {
+            return false;
+        }
+
+        return this.getString().equals(((DERVisibleString) o).getString());
+    }
+
+    public int hashCode() {
+        return this.getString().hashCode();
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/DefiniteLengthInputStream.java b/src/java/org/apache/commons/ssl/asn1/DefiniteLengthInputStream.java
new file mode 100644
index 0000000..f88a078
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/DefiniteLengthInputStream.java
@@ -0,0 +1,83 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+class DefiniteLengthInputStream
+    extends LimitedInputStream {
+    private int _length;
+
+    DefiniteLengthInputStream(
+        InputStream in,
+        int length) {
+        super(in);
+
+        if (length < 0) {
+            throw new IllegalArgumentException("negative lengths not allowed");
+        }
+
+        this._length = length;
+    }
+
+    public int read()
+        throws IOException {
+        if (_length > 0) {
+            int b = _in.read();
+
+            if (b < 0) {
+                throw new EOFException();
+            }
+
+            --_length;
+            return b;
+        }
+
+        setParentEofDetect(true);
+
+        return -1;
+    }
+
+    public int read(byte[] buf, int off, int len)
+        throws IOException {
+        if (_length > 0) {
+            int toRead = Math.min(len, _length);
+            int numRead = _in.read(buf, off, toRead);
+
+            if (numRead < 0)
+                throw new EOFException();
+
+            _length -= numRead;
+            return numRead;
+        }
+
+        setParentEofDetect(true);
+
+        return -1;
+    }
+
+    byte[] toByteArray()
+        throws IOException {
+        byte[] bytes = new byte[_length];
+
+        if (_length > 0) {
+            int pos = 0;
+            do {
+                int read = _in.read(bytes, pos, _length - pos);
+
+                if (read < 0) {
+                    throw new EOFException();
+                }
+
+                pos += read;
+            }
+            while (pos < _length);
+
+            _length = 0;
+        }
+
+        setParentEofDetect(true);
+
+        return bytes;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/IndefiniteLengthInputStream.java b/src/java/org/apache/commons/ssl/asn1/IndefiniteLengthInputStream.java
new file mode 100644
index 0000000..1f48af8
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/IndefiniteLengthInputStream.java
@@ -0,0 +1,98 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+class IndefiniteLengthInputStream
+    extends LimitedInputStream {
+    private int _b1;
+    private int _b2;
+    private boolean _eofReached = false;
+    private boolean _eofOn00 = true;
+
+    IndefiniteLengthInputStream(
+        InputStream in)
+        throws IOException {
+        super(in);
+
+        _b1 = in.read();
+        _b2 = in.read();
+        _eofReached = (_b2 < 0);
+    }
+
+    void setEofOn00(
+        boolean eofOn00) {
+        _eofOn00 = eofOn00;
+    }
+
+    boolean checkForEof() {
+        if (_eofOn00 && (_b1 == 0x00 && _b2 == 0x00)) {
+            _eofReached = true;
+            setParentEofDetect(true);
+        }
+        return _eofReached;
+    }
+
+    public int read(byte[] b, int off, int len)
+        throws IOException {
+        // Only use this optimisation if we aren't checking for 00
+        if (_eofOn00 || len < 3) {
+            return super.read(b, off, len);
+        }
+
+        if (_eofReached) {
+            return -1;
+        }
+
+        int numRead = _in.read(b, off + 2, len - 2);
+
+        if (numRead < 0) {
+//          throw new EOFException();
+            _eofReached = true;
+            return -1;
+        }
+
+        b[off] = (byte) _b1;
+        b[off + 1] = (byte) _b2;
+
+        _b1 = _in.read();
+        _b2 = _in.read();
+
+        if (_b2 < 0) {
+            // Corrupted stream
+//            throw new EOFException();
+            _eofReached = true;
+            // Just fall thru...
+        }
+
+        return numRead + 2;
+    }
+
+    public int read()
+        throws IOException {
+        if (checkForEof()) {
+            return -1;
+        }
+
+        int b = _in.read();
+
+        //
+        // strictly speaking we should return b1 and b2, but if this happens the stream
+        // is corrupted so we are already in trouble.
+        //
+        if (b < 0) {
+            // Corrupted stream
+//            throw new EOFException();
+            _eofReached = true;
+
+            return -1;
+        }
+
+        int v = _b1;
+
+        _b1 = _b2;
+        _b2 = b;
+
+        return v;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/LimitedInputStream.java b/src/java/org/apache/commons/ssl/asn1/LimitedInputStream.java
new file mode 100644
index 0000000..e1af7d2
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/LimitedInputStream.java
@@ -0,0 +1,23 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.InputStream;
+
+abstract class LimitedInputStream
+    extends InputStream {
+    protected final InputStream _in;
+
+    LimitedInputStream(
+        InputStream in) {
+        this._in = in;
+    }
+
+    InputStream getUnderlyingStream() {
+        return _in;
+    }
+
+    protected void setParentEofDetect(boolean on) {
+        if (_in instanceof IndefiniteLengthInputStream) {
+            ((IndefiniteLengthInputStream) _in).setEofOn00(on);
+        }
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/OIDTokenizer.java b/src/java/org/apache/commons/ssl/asn1/OIDTokenizer.java
new file mode 100644
index 0000000..b59c009
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/OIDTokenizer.java
@@ -0,0 +1,42 @@
+package org.apache.commons.ssl.asn1;
+
+/**
+ * class for breaking up an OID into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+public class OIDTokenizer {
+    private String oid;
+    private int index;
+
+    public OIDTokenizer(
+        String oid) {
+        this.oid = oid;
+        this.index = 0;
+    }
+
+    public boolean hasMoreTokens() {
+        return (index != -1);
+    }
+
+    public String nextToken() {
+        if (index == -1) {
+            return null;
+        }
+
+        String token;
+        int end = oid.indexOf('.', index);
+
+        if (end == -1) {
+            token = oid.substring(index);
+            index = -1;
+            return token;
+        }
+
+        token = oid.substring(index, end);
+
+        index = end + 1;
+        return token;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/asn1/Strings.java b/src/java/org/apache/commons/ssl/asn1/Strings.java
new file mode 100644
index 0000000..74104be
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/asn1/Strings.java
@@ -0,0 +1,195 @@
+package org.apache.commons.ssl.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Vector;
+
+public final class Strings {
+    public static String fromUTF8ByteArray(byte[] bytes) {
+        int i = 0;
+        int length = 0;
+
+        while (i < bytes.length) {
+            length++;
+            if ((bytes[i] & 0xf0) == 0xf0) {
+                // surrogate pair
+                length++;
+                i += 4;
+            } else if ((bytes[i] & 0xe0) == 0xe0) {
+                i += 3;
+            } else if ((bytes[i] & 0xc0) == 0xc0) {
+                i += 2;
+            } else {
+                i += 1;
+            }
+        }
+
+        char[] cs = new char[length];
+
+        i = 0;
+        length = 0;
+
+        while (i < bytes.length) {
+            char ch;
+
+            if ((bytes[i] & 0xf0) == 0xf0) {
+                int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i + 1] & 0x3F) << 12) | ((bytes[i + 2] & 0x3F) << 6) | (bytes[i + 3] & 0x3F);
+                int U = codePoint - 0x10000;
+                char W1 = (char) (0xD800 | (U >> 10));
+                char W2 = (char) (0xDC00 | (U & 0x3FF));
+                cs[length++] = W1;
+                ch = W2;
+                i += 4;
+            } else if ((bytes[i] & 0xe0) == 0xe0) {
+                ch = (char) (((bytes[i] & 0x0f) << 12)
+                             | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
+                i += 3;
+            } else if ((bytes[i] & 0xd0) == 0xd0) {
+                ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+                i += 2;
+            } else if ((bytes[i] & 0xc0) == 0xc0) {
+                ch = (char) (((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+                i += 2;
+            } else {
+                ch = (char) (bytes[i] & 0xff);
+                i += 1;
+            }
+
+            cs[length++] = ch;
+        }
+
+        return new String(cs);
+    }
+
+    public static byte[] toUTF8ByteArray(String string) {
+        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        char[] c = string.toCharArray();
+        int i = 0;
+
+        while (i < c.length) {
+            char ch = c[i];
+
+            if (ch < 0x0080) {
+                bOut.write(ch);
+            } else if (ch < 0x0800) {
+                bOut.write(0xc0 | (ch >> 6));
+                bOut.write(0x80 | (ch & 0x3f));
+            }
+            // surrogate pair
+            else if (ch >= 0xD800 && ch <= 0xDFFF) {
+                // in error - can only happen, if the Java String class has a
+                // bug.
+                if (i + 1 >= c.length) {
+                    throw new IllegalStateException("invalid UTF-16 codepoint");
+                }
+                char W1 = ch;
+                ch = c[++i];
+                char W2 = ch;
+                // in error - can only happen, if the Java String class has a
+                // bug.
+                if (W1 > 0xDBFF) {
+                    throw new IllegalStateException("invalid UTF-16 codepoint");
+                }
+                int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
+                bOut.write(0xf0 | (codePoint >> 18));
+                bOut.write(0x80 | ((codePoint >> 12) & 0x3F));
+                bOut.write(0x80 | ((codePoint >> 6) & 0x3F));
+                bOut.write(0x80 | (codePoint & 0x3F));
+            } else {
+                bOut.write(0xe0 | (ch >> 12));
+                bOut.write(0x80 | ((ch >> 6) & 0x3F));
+                bOut.write(0x80 | (ch & 0x3F));
+            }
+
+            i++;
+        }
+
+        return bOut.toByteArray();
+    }
+
+    /**
+     * A locale independent version of toUpperCase.
+     *
+     * @param string input to be converted
+     * @return a US Ascii uppercase version
+     */
+    public static String toUpperCase(String string) {
+        boolean changed = false;
+        char[] chars = string.toCharArray();
+
+        for (int i = 0; i != chars.length; i++) {
+            char ch = chars[i];
+            if ('a' <= ch && 'z' >= ch) {
+                changed = true;
+                chars[i] = (char) (ch - 'a' + 'A');
+            }
+        }
+
+        if (changed) {
+            return new String(chars);
+        }
+
+        return string;
+    }
+
+    /**
+     * A locale independent version of toLowerCase.
+     *
+     * @param string input to be converted
+     * @return a US ASCII lowercase version
+     */
+    public static String toLowerCase(String string) {
+        boolean changed = false;
+        char[] chars = string.toCharArray();
+
+        for (int i = 0; i != chars.length; i++) {
+            char ch = chars[i];
+            if ('A' <= ch && 'Z' >= ch) {
+                changed = true;
+                chars[i] = (char) (ch - 'A' + 'a');
+            }
+        }
+
+        if (changed) {
+            return new String(chars);
+        }
+
+        return string;
+    }
+
+    public static byte[] toByteArray(String string) {
+        byte[] bytes = new byte[string.length()];
+
+        for (int i = 0; i != bytes.length; i++) {
+            char ch = string.charAt(i);
+
+            bytes[i] = (byte) ch;
+        }
+
+        return bytes;
+    }
+
+    public static String[] split(String input, char delimiter) {
+        Vector v = new Vector();
+        boolean moreTokens = true;
+        String subString;
+
+        while (moreTokens) {
+            int tokenLocation = input.indexOf(delimiter);
+            if (tokenLocation > 0) {
+                subString = input.substring(0, tokenLocation);
+                v.addElement(subString);
+                input = input.substring(tokenLocation + 1);
+            } else {
+                moreTokens = false;
+                v.addElement(input);
+            }
+        }
+
+        String[] res = new String[v.size()];
+
+        for (int i = 0; i != res.length; i++) {
+            res[i] = (String) v.elementAt(i);
+        }
+        return res;
+    }
+}
diff --git a/src/java/org/apache/commons/ssl/rmi/DateRMI.java b/src/java/org/apache/commons/ssl/rmi/DateRMI.java
new file mode 100644
index 0000000..c76bc74
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/rmi/DateRMI.java
@@ -0,0 +1,69 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/rmi/DateRMI.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl.rmi;
+
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Date;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class DateRMI extends UnicastRemoteObject
+    implements Remote, Serializable, RemoteDate {
+    private Date d;
+
+    public DateRMI() throws RemoteException {
+        super();
+        this.d = new Date();
+    }
+
+    public Date getDate() throws RemoteException {
+        return d;
+    }
+
+    public boolean equals(Object o) {
+        RemoteDate rd = (RemoteDate) o;
+        try {
+            return d.equals(rd.getDate());
+        }
+        catch (RemoteException re) {
+            return false;
+        }
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/rmi/IntegerRMI.java b/src/java/org/apache/commons/ssl/rmi/IntegerRMI.java
new file mode 100644
index 0000000..de05f0d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/rmi/IntegerRMI.java
@@ -0,0 +1,69 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/rmi/IntegerRMI.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl.rmi;
+
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class IntegerRMI extends UnicastRemoteObject
+    implements Remote, Serializable, RemoteInteger {
+    private int i;
+
+    public IntegerRMI() throws RemoteException {
+        super();
+        this.i = (int) Math.round(Math.random() * 1000000.0);
+    }
+
+    public int getInt() throws RemoteException {
+        return i;
+    }
+
+    public boolean equals(Object o) {
+        RemoteInteger ri = (RemoteInteger) o;
+        try {
+            return i == ri.getInt();
+        }
+        catch (RemoteException re) {
+            return false;
+        }
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/rmi/RemoteDate.java b/src/java/org/apache/commons/ssl/rmi/RemoteDate.java
new file mode 100644
index 0000000..555c13e
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/rmi/RemoteDate.java
@@ -0,0 +1,46 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/rmi/RemoteDate.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl.rmi;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Date;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public interface RemoteDate extends Remote {
+    public Date getDate() throws RemoteException;
+}
diff --git a/src/java/org/apache/commons/ssl/rmi/RemoteInteger.java b/src/java/org/apache/commons/ssl/rmi/RemoteInteger.java
new file mode 100644
index 0000000..6e70e1a
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/rmi/RemoteInteger.java
@@ -0,0 +1,45 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/rmi/RemoteInteger.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl.rmi;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public interface RemoteInteger extends Remote {
+    public int getInt() throws RemoteException;
+}
diff --git a/src/java/org/apache/commons/ssl/rmi/Test.java b/src/java/org/apache/commons/ssl/rmi/Test.java
new file mode 100644
index 0000000..c2531d6
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/rmi/Test.java
@@ -0,0 +1,200 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/rmi/Test.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl.rmi;
+
+import org.apache.commons.ssl.LogWrapper;
+import org.apache.commons.ssl.RMISocketFactoryImpl;
+
+import java.net.MalformedURLException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.server.RMISocketFactory;
+
+/**
+ * @author Credit Union Central of British Columbia
+ * @author <a href="http://www.cucbc.com/">www.cucbc.com</a>
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at cucbc.com</a>
+ * @since 22-Feb-2007
+ */
+public class Test {
+    private final static LogWrapper log = LogWrapper.getLogger(Test.class);
+    private final static String TEST_DATE_NAME = "/org.apache.commons.ssl.rmi.testdate";
+    private final static String TEST_INT_NAME = "/org.apache.commons.ssl.rmi.testint";
+    protected final static int PORT;
+    protected final static String URL;
+
+    private static boolean rmiRunning = false;
+
+    static {
+        int port = 1099;
+        String host = "127.0.0.1";
+        PORT = port;
+        // e.g. "rmi://localhost:1099/"
+        URL = "rmi://" + host + ":" + port;
+    }
+
+    /**
+     * <p/>
+     * JNDI/RMI lookup wrapper.  Appends "java:" if we expect
+     * binding/lookup to occur in the same JVM.  Otherwise, appends "rmi:".
+     * </p>
+     *
+     * @param ref String reference.
+     * @return Object  Object previously bound with String reference.
+     * @throws java.rmi.RemoteException       rmi problem
+     * @throws java.rmi.NotBoundException     rmi problem
+     * @throws java.net.MalformedURLException rmi problem
+     */
+    public static Object lookup(String ref)
+        throws RemoteException, NotBoundException, MalformedURLException {
+        return Naming.lookup(URL + ref);
+    }
+
+    /**
+     * <p/>
+     * JNDI/RMI rebind wrapper for the UCS.  Appends "java:" if we expect
+     * binding/lookup to occur in the same JVM.  Otherwise, append "rmi:".
+     * </p><p>
+     * Also attempts to start a naming server on the localhost if one is
+     * not already running.  Currently we use RMI.
+     * </p>
+     *
+     * @param ref String reference to bind with.
+     * @param obj Object to bind.
+     * @throws java.rmi.RemoteException       rmi problem
+     * @throws java.net.MalformedURLException rmi problem
+     */
+    public static void rebind(String ref, Remote obj)
+        throws RemoteException, MalformedURLException {
+        requireNameServer();
+        String realRef = URL + ref;
+        Naming.rebind(realRef, obj);
+        try {
+            Object o = lookup(ref);
+            log.debug("Bound " + o.getClass().getName() + " to [" + realRef + "]");
+        }
+        catch (NotBoundException nbe) {
+            log.debug("Error binding " + obj.getClass().getName() + " to [" + realRef + "]");
+        }
+    }
+
+    private static void rebindTest() throws Exception {
+        Remote remoteTest = new DateRMI();
+        Naming.rebind(URL + TEST_DATE_NAME, remoteTest);
+        Object o = Naming.lookup(URL + TEST_DATE_NAME);
+        if (!remoteTest.equals(o)) {
+            throw new RuntimeException("rmi: Test failed. Lookup != Rebind");
+        }
+    }
+
+    /**
+     * <p/>
+     * Attempts to start a naming server on the localhost if one is not
+     * already running.
+     * </p>
+     */
+    private synchronized static void requireNameServer() {
+        if (rmiRunning) {
+            // We've already established that the name server is running.
+            return;
+        }
+        try {
+            // If this rebind works, then the naming server is running.
+            rebindTest();
+            rmiRunning = true;
+        }
+        catch (Exception e) {
+            Test.tryToStartNameServer();
+            try {
+                // Okay, we've started our naming server.  Now we must perform a
+                // quick test to see that it's actually doing something.
+                rebindTest();
+                log.debug(Test.class.getName() + " successfully started.");
+                rmiRunning = true;
+                return;
+            }
+            catch (Exception e2) {
+                e2.printStackTrace();
+                log.error(e2.getMessage(), e2);
+            }
+
+            String msg = Test.class.getName() + " cannot start.";
+            log.error(msg);
+            throw new RuntimeException(msg);
+        }
+    }
+
+    public static void tryToStartNameServer() {
+        String className = Test.class.getName();
+        log.debug(className + " probably not running.   Trying to start one.");
+        try {
+            LocateRegistry.createRegistry(PORT);
+            log.debug("registry on " + PORT + " started!");
+        }
+        catch (Exception problem) {
+            // bah - no luck
+            problem.printStackTrace();
+            log.warn(problem, problem);
+        }
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        System.setProperty(RMISocketFactoryImpl.RMI_HOSTNAME_KEY, "localhost");
+        RMISocketFactoryImpl impl = new RMISocketFactoryImpl();
+        RMISocketFactory.setSocketFactory(impl);
+
+        if (args.length > 0) {
+
+        } else {
+            Test.requireNameServer();
+            Test.rebindTest();
+
+            IntegerRMI remoteInt = new IntegerRMI();
+            Test.rebind(TEST_INT_NAME, remoteInt);
+        }
+
+        Object o = Test.lookup(TEST_DATE_NAME);
+        RemoteDate rd = (RemoteDate) o;
+        System.out.println("The remote-date is: " + rd.getDate());
+
+        o = Test.lookup(TEST_INT_NAME);
+        RemoteInteger ri = (RemoteInteger) o;
+        System.out.println("The remote-int  is: " + ri.getInt());
+
+    }
+
+
+}
diff --git a/src/java/org/apache/commons/ssl/util/Hex.java b/src/java/org/apache/commons/ssl/util/Hex.java
new file mode 100644
index 0000000..52a83fa
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/util/Hex.java
@@ -0,0 +1,83 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/src/java/org/apache/commons/ssl/util/Hex.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.commons.ssl.util;
+
+/**
+ * Utility class for dealing with hex-encoding of binary data.
+ *
+ * @author <a href="mailto:juliusdavies at cucbc.com">juliusdavies at gmail.com</a>
+ * @since 13-Nov-2007
+ */
+public class Hex {
+
+    public static byte[] decode(String s) {
+        byte[] b = new byte[s.length() / 2];
+        for (int i = 0; i < b.length; i++) {
+            String hex = s.substring(2 * i, 2 * (i + 1));
+            b[i] = (byte) Integer.parseInt(hex, 16);
+        }
+        return b;
+    }
+
+    public static byte[] decode(byte[] hexString) {
+        byte[] b = new byte[hexString.length / 2];
+        char[] chars = new char[2];
+        for (int i = 0; i < b.length; i++) {
+            chars[0] = (char) hexString[2 * i];
+            chars[1] = (char) hexString[2 * i + 1];
+            String hex = new String(chars);
+            b[i] = (byte) Integer.parseInt(hex, 16);
+        }
+        return b;
+    }
+
+    public static String encode(byte[] b) {
+        return encode(b, 0, b.length);
+    }
+
+    public static String encode(byte[] b, int offset, int length) {
+        StringBuffer buf = new StringBuffer();
+        int len = Math.min(offset + length, b.length);
+        for (int i = offset; i < len; i++) {
+            int c = (int) b[i];
+            if (c < 0) {
+                c = c + 256;
+            }
+            if (c >= 0 && c <= 15) {
+                buf.append('0');
+            }
+            buf.append(Integer.toHexString(c));
+        }
+        return buf.toString();
+    }
+
+}
diff --git a/src/java/org/apache/commons/ssl/util/PublicKeyDeriver.java b/src/java/org/apache/commons/ssl/util/PublicKeyDeriver.java
new file mode 100644
index 0000000..aa3e26d
--- /dev/null
+++ b/src/java/org/apache/commons/ssl/util/PublicKeyDeriver.java
@@ -0,0 +1,82 @@
+/*
+ * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/trunk/src/java/org/apache/commons/ssl/Certificates.java $
+ * $Revision: 121 $
+ * $Date: 2007-11-13 21:26:57 -0800 (Tue, 13 Nov 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.commons.ssl.util;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyException;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+/**
+ * Utility class for deriving a public key from a given private key.
+ *
+ * @author Chad La Joie <lajoie OF georgetown.edu>
+ * @since November 14th, 2007
+ */
+public class PublicKeyDeriver {
+
+    /**
+     * Utility method for deriving a public key from a given private key.
+     *
+     * @param key private key for which we need a public key (DSA or RSA).
+     * @return the corresponding public key
+     * @throws GeneralSecurityException if it didn't work
+     */
+    public static PublicKey derivePublicKey(PrivateKey key) throws GeneralSecurityException {
+        if (key instanceof DSAPrivateKey) {
+            DSAPrivateKey dsaKey = (DSAPrivateKey) key;
+            DSAParams keyParams = dsaKey.getParams();
+            BigInteger g = keyParams.getG();
+            BigInteger p = keyParams.getP();
+            BigInteger q = keyParams.getQ();
+            BigInteger x = dsaKey.getX();
+            BigInteger y = q.modPow(x, p);
+            DSAPublicKeySpec keySpec = new DSAPublicKeySpec(y, p, q, g);
+            return KeyFactory.getInstance("DSA").generatePublic(keySpec);
+        } else if (key instanceof RSAPrivateCrtKey) {
+            RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
+            BigInteger modulus = rsaKey.getModulus();
+            BigInteger exponent = rsaKey.getPublicExponent();
+            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
+            return KeyFactory.getInstance("RSA").generatePublic(keySpec);
+        } else {
+            throw new KeyException("Private key was not a DSA or RSA key");
+        }
+    }
+}
+
diff --git a/version.txt b/version.txt
new file mode 100644
index 0000000..8db9de5
--- /dev/null
+++ b/version.txt
@@ -0,0 +1,3 @@
+$URL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.9/version.txt $
+$Date: 2007-11-13 21:36:51 -0800 (Tue, 13 Nov 2007) $
+$Revision: 123 $

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/not-yet-commons-ssl.git



More information about the pkg-java-commits mailing list