com.geoxp.oss.CryptoHelperTest.java Source code

Java tutorial

Introduction

Here is the source code for com.geoxp.oss.CryptoHelperTest.java

Source

/*
 * Copyright 2012-2013 Mathias Herberts 
 *
 *    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.
 */

package com.geoxp.oss;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.KeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.generators.DSAKeyPairGenerator;
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.geoxp.oss.CryptoHelper.SSSSGF256Polynomial;

public class CryptoHelperTest {

    private static final String PLAINTEXT = "Too many secrets, Marty!";

    //
    // AES Wrapping tests
    //

    @Test
    public void testWrapAES_Ok() {
        try {
            byte[] data = PLAINTEXT.getBytes("UTF-8");
            byte[] key = "0123456789ABCDEF".getBytes();
            byte[] encrypted = CryptoHelper.wrapAES(key, data);

            Assert.assertEquals("b552b1f8a038ab01a90652321088e3520d641021409378624355c6fa8a6037ca9876dcafa74f6a0e",
                    new String(Hex.encode(encrypted)));
        } catch (UnsupportedEncodingException uee) {
            Assert.assertTrue(false);
        }
    }

    @Test
    public void testUnwrapAES_Ok() {
        try {
            byte[] encrypted = Hex
                    .decode("b552b1f8a038ab01a90652321088e3520d641021409378624355c6fa8a6037ca9876dcafa74f6a0e");
            byte[] key = "0123456789ABCDEF".getBytes();
            String data = new String(CryptoHelper.unwrapAES(key, encrypted), "UTF-8");

            Assert.assertEquals(PLAINTEXT, data);
        } catch (UnsupportedEncodingException uee) {
            Assert.assertTrue(false);
        }
    }

    @Test
    public void testUnwrapAES_WrongKey() {
        byte[] encrypted = Hex
                .decode("b552b1f8a038ab01a90652321088e3520d641021409378624355c6fa8a6037ca9876dcafa74f6a0e");
        byte[] key = "0123456789ABCDEG".getBytes();
        byte[] data = CryptoHelper.unwrapAES(key, encrypted);

        Assert.assertEquals(null, data);
    }

    //
    // Padding tests
    //

    @Test
    public void testPadPKCS7() {
        byte[] data = new byte[8];
        byte[] padded = CryptoHelper.padPKCS7(8, data);

        Assert.assertEquals("00000000000000000808080808080808", new String(Hex.encode(padded)));

        data = new byte[0];
        padded = CryptoHelper.padPKCS7(8, data);

        Assert.assertEquals("0808080808080808", new String(Hex.encode(padded)));

        data = new byte[3];
        padded = CryptoHelper.padPKCS7(8, data);

        Assert.assertEquals("0000000505050505", new String(Hex.encode(padded)));
    }

    @Test
    public void testUnpadPKCS7() {
        try {
            byte[] padded = Hex.decode("00000000000000000808080808080808");
            byte[] data = CryptoHelper.unpadPKCS7(padded);

            Assert.assertEquals("0000000000000000", new String(Hex.encode(data)));

            padded = Hex.decode("0808080808080808");
            data = CryptoHelper.unpadPKCS7(padded);

            Assert.assertEquals("", new String(Hex.encode(data)));
            padded = Hex.decode("0000000505050505");
            data = CryptoHelper.unpadPKCS7(padded);

            Assert.assertEquals("000000", new String(Hex.encode(data)));
        } catch (InvalidCipherTextException ice) {
            Assert.assertTrue(false);
        }
    }

    //
    // RSA Tests
    //

    private static RSAPublicKey pubkey = null;
    private static RSAPrivateKey privkey = null;

    private static String TEST_CIPHERTEXT = "416a5e39db06eff6b27880a1e5d060730ae9a45b28f245fe4e82d74976b72606d2062308a35db92d3d76cbf746bbed1dd6e51d3c60bbf897efce0ea11b4fd888ef61f59d1b8135479f72ba342935bab40f6484bcd8af087f815508fddb2502c4f2b24e393d682c2a439ee2a23ef148be0e3dae9d8bd60f6aeed2af41da07f3fe017702464b4f9073d5ff0e4883428d0bcb900d5fc0771d3c7d314830da7bcd0043f7cb7cbdaec59626f3e42edad4631a2a872917f8e52234dfe6052c53149952e73d12cedb4c8e844d31e0644d2fc01d67a567eb2b6fd099382804b6560acf2ff861f2a5a34ba34a4eed8b821aedf5f9447d249fcdcfb4ab412c66f057b407ba";
    private static String TEST_SHA256WITHRSA_SIG = "5572ce4db50487e52a4bd2707e557ceb9566a55937026a0fe2f8f6cdba2ce58e069b2efbcb69c8a293e651c8ca764c4c8d2d7de5a1f66290bd2720b6d1717cfda912eacae716d3e0f5251c9c266080709b21e9331ee79cc57fec90768169a9ea913e5f445579cc7c120c67bdb72a7f08ed05556b276daf0b174966c35738d8a35dd6268e2e94e676dade1c2567b4b8c0f39933dddaba6988569592954312eff378e6e51ccdf57fab2ce8961c7385831df58b18db5623d032eac7805611f0419ef2683b7d1716c639ee414e6f5809a68ce280c2edfe505a9c037b30b4646d5afd45a48a4d36a15a51370bf671c6a78baa2a4dd541f94f565b46af83a057af4717";
    private static String TEST_SHA1WITHRSA_SIG = "3ed203960c6b7c217aa1a48e5600245adf464771958e0bc4c30ef066b0bcd6e4de74af65b724cdab71c0c56d2a6dcf3c40ef675931dce64d12dd5462c4df2c54321cf4004526c97a28435ef6a51c3b28b0deefdcb33bfde7351b8eaf65a47f911cc40c4762a47cae4f4e94c7473aa714e134a4275f28a645e3bfe47dc541c63422dd64de19ba085f49d88f24b096ed67746e593b96fda7a7ea8b6a3f0e1516577771fd7f69e7d3ec168994f898867d793ab2f131563b4064ffa8d00eab8d19e61ec6b22906d1aa6e84efbac5fbd17b5e6a1024ee2296c1159f20107e4dc8418218b30ba2d0870448735d55e8435837da6381a44932495a90a7c60618359ab3e3";

    @BeforeClass
    public static void initRSA() {

        pubkey = new RSAPublicKey() {

            public BigInteger getModulus() {
                return new BigInteger(
                        "16486878486408275413767645980834450799068512761530201902904366269045701264780287813548482765230599547361495663114883133953031934796710541013969698908689227122243199249153028203405570632782038660366993871583035487813355780732353330307966740208839055253611521697790624599289584287035124227303722015732664143435627662572063369377319845149329865786129950696697707258169860504161097904037909901392070097285851111591152223867471834516850780920777180757773482764583645271112169550056347194865136966708230939966062717171772017703633226195925227390808476557633216288033679639392565309589416160575374495537295296004844165991833");
            }

            public String getFormat() {
                return "PKCS#8";
            }

            public byte[] getEncoded() {
                return null;
            }

            public String getAlgorithm() {
                return "RSA";
            }

            public BigInteger getPublicExponent() {
                return new BigInteger("65537");
            }
        };

        privkey = new RSAPrivateKey() {

            public BigInteger getModulus() {
                return new BigInteger(
                        "16486878486408275413767645980834450799068512761530201902904366269045701264780287813548482765230599547361495663114883133953031934796710541013969698908689227122243199249153028203405570632782038660366993871583035487813355780732353330307966740208839055253611521697790624599289584287035124227303722015732664143435627662572063369377319845149329865786129950696697707258169860504161097904037909901392070097285851111591152223867471834516850780920777180757773482764583645271112169550056347194865136966708230939966062717171772017703633226195925227390808476557633216288033679639392565309589416160575374495537295296004844165991833");
            }

            public String getFormat() {
                return "PKCS#8";
            }

            public byte[] getEncoded() {
                return null;
            }

            public String getAlgorithm() {
                return "RSA";
            }

            public BigInteger getPrivateExponent() {
                return new BigInteger(
                        "16462225022080216287006438887038247491344498628282876578484807426035394434685097795608574754320844771347313955453786981441818465617314510786474253122445554933128960978765048943385524766751969542331136792384794227490092450605680296352030692776999541278073216173790693549489770757881677438859396447617831284347271984130596544116183151131396911078941742892944344866258139017288536308538106615887195873638366636746767960329159670221204748613353113007335636833020656797045918057345527985852226488193916871657682561742644875120607102033893450853383621001138933634164562229114010435736620936636769693547229391425790450273613");
            }
        };

        /*
        RSAKeyPairGenerator gen = new RSAKeyPairGenerator();
        // For explanation of 'certainty', refer to http://bouncy-castle.1462172.n4.nabble.com/Questions-about-RSAKeyGenerationParameters-td1463186.html
        RSAKeyGenerationParameters params = new RSAKeyGenerationParameters(new BigInteger("65537"), CryptoHelper.getSecureRandom(), 2048, 64);
        gen.init(params);
        AsymmetricCipherKeyPair keypair = gen.generateKeyPair();
        CipherParameters priv = keypair.getPrivate();
        CipherParameters pub = keypair.getPublic();
            
        System.out.println(((RSAKeyParameters) pub).getExponent());
        System.out.println(((RSAKeyParameters) pub).getModulus());
        System.out.println(((RSAKeyParameters) priv).getExponent());
        System.out.println(((RSAKeyParameters) priv).getModulus());
            
        PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(Base64.decode(key.getBytes()));    
        PrivateKey priv = KeyFactory.getInstance("RSA").generatePrivate(pkcs8);
            
        */
    }

    @Test
    public void testEncryptRSA() throws Exception {
        byte[] data = PLAINTEXT.getBytes("UTF-8");
        String ciphertext = new String(Hex.encode(CryptoHelper.encryptRSA(privkey, data)));

        Assert.assertEquals(TEST_CIPHERTEXT, ciphertext);
    }

    @Test
    public void testDecryptRSA() throws Exception {
        byte[] data = Hex.decode(TEST_CIPHERTEXT);
        String cleartext = new String(CryptoHelper.decryptRSA(pubkey, data));

        Assert.assertEquals(PLAINTEXT, cleartext);
    }

    @Test
    public void testSign_Default() throws Exception {
        byte[] data = PLAINTEXT.getBytes("UTF-8");
        String sig = new String(
                Hex.encode(CryptoHelper.sign(CryptoHelper.DEFAULT_SIGNATURE_ALGORITHM, privkey, data)));

        Assert.assertEquals(TEST_SHA256WITHRSA_SIG, sig);
    }

    @Test
    public void testVerify_Default() throws Exception {
        byte[] data = PLAINTEXT.getBytes("UTF-8");
        Assert.assertTrue(CryptoHelper.verify(CryptoHelper.DEFAULT_SIGNATURE_ALGORITHM, pubkey, data,
                Hex.decode(TEST_SHA256WITHRSA_SIG)));
    }

    @Test
    public void testSign_SHA1() throws Exception {
        byte[] data = PLAINTEXT.getBytes("UTF-8");
        String sig = new String(Hex.encode(CryptoHelper.sign("SHA1WithRSA", privkey, data)));

        Assert.assertEquals(TEST_SHA1WITHRSA_SIG, sig);
    }

    @Test
    public void testVerify_SHA1() throws Exception {
        byte[] data = PLAINTEXT.getBytes("UTF-8");
        Assert.assertTrue(CryptoHelper.verify("SHA1WithRSA", pubkey, data, Hex.decode(TEST_SHA1WITHRSA_SIG)));
    }

    //
    // SSH tests
    //

    @Test
    public void testSSHKeyBlobToPublicKey_RSA() {
        String rsapubkey = "AAAAB3NzaC1yc2EAAAABIwAAAIEA08xecCRox1yCUudqFB4EKTgfp0SkOAXv9o2OxUN8ADsQnw4FFq0qZBC5mJXlaszSHCYb/F2gG3v5iGOvcwp79JiCKx3NkMwYxHarySJi43K3ukciR5dlKv4rnStIV7SkoQE9HxSszYDki4LYnA+6Ct9aDp4cBgNs5Cscy/o3S9k=";

        byte[] blob = Base64.decode(rsapubkey.getBytes());

        PublicKey pubkey = CryptoHelper.sshKeyBlobToPublicKey(blob);

        Assert.assertEquals("RSA", pubkey.getAlgorithm());
        Assert.assertTrue(pubkey instanceof RSAPublicKey);
        Assert.assertEquals(new BigInteger("23", 16), ((RSAPublicKey) pubkey).getPublicExponent());
        Assert.assertEquals(new BigInteger(
                "00d3cc5e702468c75c8252e76a141e0429381fa744a43805eff68d8ec5437c003b109f0e0516ad2a6410b99895e56accd21c261bfc5da01b7bf98863af730a7bf498822b1dcd90cc18c476abc92262e372b7ba47224797652afe2b9d2b4857b4a4a1013d1f14accd80e48b82d89c0fba0adf5a0e9e1c06036ce42b1ccbfa374bd9",
                16), ((RSAPublicKey) pubkey).getModulus());
    }

    @Test
    public void testSSHKeyBlobToPublicKey_DSA() {
        String dsapubkey = "AAAAB3NzaC1kc3MAAACBAMCN5PhMDoTyfaxwAdBLyxt9QPPYKB36nfEdD/NxkeblbUHAVvTy9paesjHOzXaLFaGA7MIGOMK71OokmExothsxMNjA044TLwonwR/Uy25ig2LVpZlrlrJgrF64AV84Y6rO9UXW9WAwhuvp4a3qPX5hLdhro2a34fbOhUeWNbKvAAAAFQDD3f1U20+RA07jriYJMR8zROr8vQAAAIEArzx1ehDtiCB+gkSMzCl3eYHV7y23rmp524xgxrjL9xlboI2/L69zdpyGM9J+IVAYJARQ9fWKOfMATMu+bvuO2Q6TFvMg1NSEW8MzI+6YGKZt0+muC8gwTdogSrMA0Nh45BAigsU/tjSUYaRFUO/CbnLVulUe2O1Uta4CoraOpCEAAACBAKHWahSYbnDtepBX7tE/lNuAuHAU3Pr8pWHzXI6+SlioNhSEmclG+kr8cI0MXvAgWbKe4dR8ro9sFQY70LeBkdEbhiKOkZ7Tjt3KvxOSo5T727V2P7VuFVOqI7EDlYbysp4BeT5iB0k0qrKp+73qHSv1Py2tr0GAzIAkqufDU3Po";

        byte[] blob = Base64.decode(dsapubkey.getBytes());

        PublicKey pubkey = CryptoHelper.sshKeyBlobToPublicKey(blob);

        Assert.assertEquals("DSA", pubkey.getAlgorithm());
        Assert.assertTrue(pubkey instanceof DSAPublicKey);
        Assert.assertEquals(new BigInteger(
                "00c08de4f84c0e84f27dac7001d04bcb1b7d40f3d8281dfa9df11d0ff37191e6e56d41c056f4f2f6969eb231cecd768b15a180ecc20638c2bbd4ea24984c68b61b3130d8c0d38e132f0a27c11fd4cb6e628362d5a5996b96b260ac5eb8015f3863aacef545d6f5603086ebe9e1adea3d7e612dd86ba366b7e1f6ce85479635b2af",
                16), ((DSAPublicKey) pubkey).getParams().getP());
        Assert.assertEquals(new BigInteger("00c3ddfd54db4f91034ee3ae2609311f3344eafcbd", 16),
                ((DSAPublicKey) pubkey).getParams().getQ());
        Assert.assertEquals(new BigInteger(
                "00af3c757a10ed88207e82448ccc29777981d5ef2db7ae6a79db8c60c6b8cbf7195ba08dbf2faf73769c8633d27e215018240450f5f58a39f3004ccbbe6efb8ed90e9316f320d4d4845bc33323ee9818a66dd3e9ae0bc8304dda204ab300d0d878e4102282c53fb6349461a44550efc26e72d5ba551ed8ed54b5ae02a2b68ea421",
                16), ((DSAPublicKey) pubkey).getParams().getG());
        Assert.assertEquals(new BigInteger(
                "00a1d66a14986e70ed7a9057eed13f94db80b87014dcfafca561f35c8ebe4a58a836148499c946fa4afc708d0c5ef02059b29ee1d47cae8f6c15063bd0b78191d11b86228e919ed38eddcabf1392a394fbdbb5763fb56e1553aa23b1039586f2b29e01793e62074934aab2a9fbbdea1d2bf53f2dadaf4180cc8024aae7c35373e8",
                16), ((DSAPublicKey) pubkey).getY());
    }

    @Test
    public void testSSHKeyBlobFingerprint() {

        String rsapubkey = "AAAAB3NzaC1yc2EAAAABIwAAAIEA08xecCRox1yCUudqFB4EKTgfp0SkOAXv9o2OxUN8ADsQnw4FFq0qZBC5mJXlaszSHCYb/F2gG3v5iGOvcwp79JiCKx3NkMwYxHarySJi43K3ukciR5dlKv4rnStIV7SkoQE9HxSszYDki4LYnA+6Ct9aDp4cBgNs5Cscy/o3S9k=";
        String dsapubkey = "AAAAB3NzaC1kc3MAAACBAMCN5PhMDoTyfaxwAdBLyxt9QPPYKB36nfEdD/NxkeblbUHAVvTy9paesjHOzXaLFaGA7MIGOMK71OokmExothsxMNjA044TLwonwR/Uy25ig2LVpZlrlrJgrF64AV84Y6rO9UXW9WAwhuvp4a3qPX5hLdhro2a34fbOhUeWNbKvAAAAFQDD3f1U20+RA07jriYJMR8zROr8vQAAAIEArzx1ehDtiCB+gkSMzCl3eYHV7y23rmp524xgxrjL9xlboI2/L69zdpyGM9J+IVAYJARQ9fWKOfMATMu+bvuO2Q6TFvMg1NSEW8MzI+6YGKZt0+muC8gwTdogSrMA0Nh45BAigsU/tjSUYaRFUO/CbnLVulUe2O1Uta4CoraOpCEAAACBAKHWahSYbnDtepBX7tE/lNuAuHAU3Pr8pWHzXI6+SlioNhSEmclG+kr8cI0MXvAgWbKe4dR8ro9sFQY70LeBkdEbhiKOkZ7Tjt3KvxOSo5T727V2P7VuFVOqI7EDlYbysp4BeT5iB0k0qrKp+73qHSv1Py2tr0GAzIAkqufDU3Po";

        byte[] blob = Base64.decode(rsapubkey.getBytes());
        byte[] fpr = CryptoHelper.sshKeyBlobFingerprint(blob);

        Assert.assertEquals("f9bab47184315d3fa7546043e6341887", new String(Hex.encode(fpr)));

        blob = Base64.decode(dsapubkey.getBytes());
        fpr = CryptoHelper.sshKeyBlobFingerprint(blob);

        Assert.assertEquals("4694d753ad274c18d2a286f1a326d9ac", new String(Hex.encode(fpr)));
    }

    @Test
    public void testSSHSignatureBlobVerify_DSA() throws Exception {
        String dsapubkey = "AAAAB3NzaC1kc3MAAACBAMCN5PhMDoTyfaxwAdBLyxt9QPPYKB36nfEdD/NxkeblbUHAVvTy9paesjHOzXaLFaGA7MIGOMK71OokmExothsxMNjA044TLwonwR/Uy25ig2LVpZlrlrJgrF64AV84Y6rO9UXW9WAwhuvp4a3qPX5hLdhro2a34fbOhUeWNbKvAAAAFQDD3f1U20+RA07jriYJMR8zROr8vQAAAIEArzx1ehDtiCB+gkSMzCl3eYHV7y23rmp524xgxrjL9xlboI2/L69zdpyGM9J+IVAYJARQ9fWKOfMATMu+bvuO2Q6TFvMg1NSEW8MzI+6YGKZt0+muC8gwTdogSrMA0Nh45BAigsU/tjSUYaRFUO/CbnLVulUe2O1Uta4CoraOpCEAAACBAKHWahSYbnDtepBX7tE/lNuAuHAU3Pr8pWHzXI6+SlioNhSEmclG+kr8cI0MXvAgWbKe4dR8ro9sFQY70LeBkdEbhiKOkZ7Tjt3KvxOSo5T727V2P7VuFVOqI7EDlYbysp4BeT5iB0k0qrKp+73qHSv1Py2tr0GAzIAkqufDU3Po";
        byte[] blob = Base64.decode(dsapubkey.getBytes());

        String data = PLAINTEXT;
        String sigblobstr = "000000077373682d64737300000028b7dccad1bcb058a0e7d9383922bda8d6ff54103724ce30699e12a884d0293f10ba021333d8cebf2e";
        byte[] sigBlob = Hex.decode(sigblobstr);

        Assert.assertTrue(CryptoHelper.sshSignatureBlobVerify(data.getBytes(), sigBlob,
                CryptoHelper.sshKeyBlobToPublicKey(blob)));
    }

    @Test
    public void testSSHSignatureBlobVerify_RSA() throws Exception {
        String rsapubkey = "AAAAB3NzaC1yc2EAAAABIwAAAIEA08xecCRox1yCUudqFB4EKTgfp0SkOAXv9o2OxUN8ADsQnw4FFq0qZBC5mJXlaszSHCYb/F2gG3v5iGOvcwp79JiCKx3NkMwYxHarySJi43K3ukciR5dlKv4rnStIV7SkoQE9HxSszYDki4LYnA+6Ct9aDp4cBgNs5Cscy/o3S9k=";
        byte[] blob = Base64.decode(rsapubkey.getBytes());

        String data = PLAINTEXT;
        String sigblobstr = "000000077373682d727361000000806d97905490be3e1dac74f7825e2a6c3c25693c633bb8f6413c48c9b306a6f7c2620b8fc72d70ff79ccb658ef6415d7ed2025df20967a190ce9b2ab5250c3d8f7ee0e318589e9acf212e99b2b49969c6706f76806dcb1e29d24090b89181021d8ffa401864c3621368d4fe5b89fdd76dd54019e67b014bc8a7827df2c5f59fbfe";
        byte[] sigBlob = Hex.decode(sigblobstr);

        Assert.assertTrue(CryptoHelper.sshSignatureBlobVerify(data.getBytes(), sigBlob,
                CryptoHelper.sshKeyBlobToPublicKey(blob)));
    }

    @Test
    public void testSSHKeyBlobFromPublicKey_RSA() {
        String rsapubkey = "AAAAB3NzaC1yc2EAAAABIwAAAIEA08xecCRox1yCUudqFB4EKTgfp0SkOAXv9o2OxUN8ADsQnw4FFq0qZBC5mJXlaszSHCYb/F2gG3v5iGOvcwp79JiCKx3NkMwYxHarySJi43K3ukciR5dlKv4rnStIV7SkoQE9HxSszYDki4LYnA+6Ct9aDp4cBgNs5Cscy/o3S9k=";
        PublicKey key = CryptoHelper.sshKeyBlobToPublicKey(Base64.decode(rsapubkey.getBytes()));
        String blob = new String(Base64.encode(CryptoHelper.sshKeyBlobFromPublicKey(key)));
        Assert.assertEquals(rsapubkey, blob);
    }

    @Test
    public void testSSHKeyBlobFromPublicKey_DSA() {
        String dsapubkey = "AAAAB3NzaC1kc3MAAACBAMCN5PhMDoTyfaxwAdBLyxt9QPPYKB36nfEdD/NxkeblbUHAVvTy9paesjHOzXaLFaGA7MIGOMK71OokmExothsxMNjA044TLwonwR/Uy25ig2LVpZlrlrJgrF64AV84Y6rO9UXW9WAwhuvp4a3qPX5hLdhro2a34fbOhUeWNbKvAAAAFQDD3f1U20+RA07jriYJMR8zROr8vQAAAIEArzx1ehDtiCB+gkSMzCl3eYHV7y23rmp524xgxrjL9xlboI2/L69zdpyGM9J+IVAYJARQ9fWKOfMATMu+bvuO2Q6TFvMg1NSEW8MzI+6YGKZt0+muC8gwTdogSrMA0Nh45BAigsU/tjSUYaRFUO/CbnLVulUe2O1Uta4CoraOpCEAAACBAKHWahSYbnDtepBX7tE/lNuAuHAU3Pr8pWHzXI6+SlioNhSEmclG+kr8cI0MXvAgWbKe4dR8ro9sFQY70LeBkdEbhiKOkZ7Tjt3KvxOSo5T727V2P7VuFVOqI7EDlYbysp4BeT5iB0k0qrKp+73qHSv1Py2tr0GAzIAkqufDU3Po";
        PublicKey key = CryptoHelper.sshKeyBlobToPublicKey(Base64.decode(dsapubkey.getBytes()));
        String blob = new String(Base64.encode(CryptoHelper.sshKeyBlobFromPublicKey(key)));
        Assert.assertEquals(dsapubkey, blob);
    }

    @Test
    public void testSSHKeyBlobFromKeyPair_RSA() throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        BigInteger modulus = new BigInteger(
                "CBECB7A213D1EC10C40F87C4411EE98F5F8D32C4C9409D910904A41E7444812B5399FA8BF09B36014F714C66E5D2A6E9588E8E5102003F307ED29FDD9BF840067D33A8082DE57503B9846128664B9181818AD93692C00F3DE1E64D8454239D2A086B3E1FE1794B9BAF72E35110C2D058743FA2634383470B1EED86BA03E46D969EC8BCAC2F248DFCD2D26548ECA382BEFDBB577B801EFF36ACF605FB908F249083D3FFF8CFC1E0AF268268E12BAC38850B51B5F243323C0D76D2691F2E98984E8D2906C77921EA09CBDBC33DD339443F8E88885FBE860AB522565FBC337DB02A420373B775FC89CABAE1770FA2ECC7E903EE519C1A45777FF6E56C1A303299CB",
                16);
        BigInteger publicExponent = new BigInteger("010001", 16);
        BigInteger privateExponent = new BigInteger(
                "C396B5C2649431811B2B72228FFB2034FD86A62D0C82471E76B1D6DFC6D075BBA2A1CB27318D0CCD50EEF042B927C4238766A3A59AEFB5ABC3D82CB11709920F2742C665A1EFB4BDEFCFC28847252FD830F185C8CC141E0A5282DBD29208DE931424181FE7D8B8E607EF7F8B9F31DB371BB874FE1420F3A0FCF70103A4FC110670CD9C52A8B5BD1EA33885CDE03FBF26C6FAA82E58E0C8D2F847E24983C09B713BAE8B9CE84B8FA802612C028CB0F057488578A95C716DD81A6B13A3B7608875AFA84B06217C920B737CF4995E04D44D39E8FE3C9150CA754BB22D2DB276AA1030303EE4D1901A97D3AFB71433BFBCAEFD04516C4B219436B45C373737954851",
                16);
        PublicKey pubkey = keyFactory.generatePublic(new RSAPublicKeySpec(modulus, publicExponent));
        PrivateKey privkey = keyFactory.generatePrivate(new RSAPrivateKeySpec(modulus, privateExponent));
        KeyPair kp = new KeyPair(pubkey, privkey);

        byte[] blob = CryptoHelper.sshPrivateKeyBlobFromKeyPair(kp);

        byte[] referenceBlob = Base64.decode(
                "AAAAB3NzaC1yc2EAAAEBAMvst6IT0ewQxA+HxEEe6Y9fjTLEyUCdkQkEpB50RIErU5n6i/CbNgFPcUxm5dKm6ViOjlECAD8wftKf3Zv4QAZ9M6gILeV1A7mEYShmS5GBgYrZNpLADz3h5k2EVCOdKghrPh/heUubr3LjURDC0Fh0P6JjQ4NHCx7throD5G2Wnsi8rC8kjfzS0mVI7KOCvv27V3uAHv82rPYF+5CPJJCD0//4z8HgryaCaOErrDiFC1G18kMyPA120mkfLpiYTo0pBsd5IeoJy9vDPdM5RD+OiIhfvoYKtSJWX7wzfbAqQgNzt3X8icq64XcPouzH6QPuUZwaRXd/9uVsGjAymcsAAAADAQABAAABAQDDlrXCZJQxgRsrciKP+yA0/YamLQyCRx52sdbfxtB1u6KhyycxjQzNUO7wQrknxCOHZqOlmu+1q8PYLLEXCZIPJ0LGZaHvtL3vz8KIRyUv2DDxhcjMFB4KUoLb0pII3pMUJBgf59i45gfvf4ufMds3G7h0/hQg86D89wEDpPwRBnDNnFKotb0eoziFzeA/vybG+qguWODI0vhH4kmDwJtxO66LnOhLj6gCYSwCjLDwV0iFeKlccW3YGmsTo7dgiHWvqEsGIXySC3N89JleBNRNOej+PJFQynVLsi0tsnaqEDAwPuTRkBqX06+3FDO/vK79BFFsSyGUNrRcNzc3lUhRAAAAAQAAAAABAAAAAAEA");

        Assert.assertArrayEquals(referenceBlob, blob);
    }

    @Test
    public void testSSHKeyBlobFromKeyPair_DSA() throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
        BigInteger p = new BigInteger(
                "F9272971CC7F314FC8C936C4F4579485620F396D584850A092F3B9D5CF8A117B4FD6DD14E730AEE71829D019C9DB591D68010C22DFD78D988843BE76CA3CA7BE8D2ECCCC26E4285F9E7F7C54DA3687440E156FAC9D936A1F45FCA9940C35C726110E4E752EC2B9BCD30E9DED9AE07577B5FF9852E32D638BA8D505FA547B89ED",
                16);
        BigInteger q = new BigInteger("F79746C519DE1A9D2DF9BAB1EB01A44A9D839DDF", 16);
        BigInteger g = new BigInteger(
                "E7B9DE58A36EE0931C3BDBC3D70D9B63A856627960F7B765974A995FF0B250C26FF73D47A78CBAA60C9DD6E8A17951EBD20B2AF615C6769C49C41ECCF1922319D9E54C1212789F4F4C8EF158D35644284F77399B971DAD447CFC147F15652DC595EE3F04EF7F4DFFC305E042AD182B37BB2612C969596FE513A6AA448174A587",
                16);
        BigInteger y = new BigInteger(
                "9826057402EA47BDFBE2581E9B6EEB8C7471986D5066484DB151800AF48A0C017382E2278D43E14B2898F0B3BE50CBD5EDE7BD824AAB699A143C21FCB93638BAE48D73D58013E83EBB42AB39529C6EE5AF21B95A1022A106149FDD6F1E212F936553E1FDB5F120D99F025A7CFD19485F8A310D6AF0E3258EDF3CB5C8C9D31EDD",
                16);
        BigInteger x = new BigInteger("BC6B3881B6F097B4C28A5E7FDEB6F47DBC022A3C", 16);
        PublicKey pubkey = keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
        PrivateKey privkey = keyFactory.generatePrivate(new DSAPrivateKeySpec(x, p, q, g));
        KeyPair kp = new KeyPair(pubkey, privkey);

        byte[] blob = CryptoHelper.sshPrivateKeyBlobFromKeyPair(kp);

        byte[] referenceBlob = Base64.decode(
                "AAAAB3NzaC1kc3MAAACBAPknKXHMfzFPyMk2xPRXlIViDzltWEhQoJLzudXPihF7T9bdFOcwrucYKdAZydtZHWgBDCLf142YiEO+dso8p76NLszMJuQoX55/fFTaNodEDhVvrJ2Tah9F/KmUDDXHJhEOTnUuwrm80w6d7ZrgdXe1/5hS4y1ji6jVBfpUe4ntAAAAFQD3l0bFGd4anS35urHrAaRKnYOd3wAAAIEA57neWKNu4JMcO9vD1w2bY6hWYnlg97dll0qZX/CyUMJv9z1Hp4y6pgyd1uiheVHr0gsq9hXGdpxJxB7M8ZIjGdnlTBISeJ9PTI7xWNNWRChPdzmblx2tRHz8FH8VZS3Fle4/BO9/Tf/DBeBCrRgrN7smEslpWW/lE6aqRIF0pYcAAACBAJgmBXQC6ke9++JYHptu64x0cZhtUGZITbFRgAr0igwBc4LiJ41D4UsomPCzvlDL1e3nvYJKq2maFDwh/Lk2OLrkjXPVgBPoPrtCqzlSnG7lryG5WhAioQYUn91vHiEvk2VT4f218SDZnwJafP0ZSF+KMQ1q8OMljt88tcjJ0x7dAAAAFQC8aziBtvCXtMKKXn/etvR9vAIqPA==");

        Assert.assertArrayEquals(referenceBlob, blob);
    }

    @Test
    public void testSSHSignatureBlobSign_RSA() throws Exception {
        RSAKeyPairGenerator rsakpg = new RSAKeyPairGenerator();
        RSAKeyGenerationParameters params = new RSAKeyGenerationParameters(new BigInteger("35"), new SecureRandom(),
                2048, 8);
        rsakpg.init(params);

        AsymmetricCipherKeyPair kp = rsakpg.generateKeyPair();

        RSAPrivateCrtKeyParameters privParams = (RSAPrivateCrtKeyParameters) kp.getPrivate();
        RSAKeyParameters pubParams = (RSAKeyParameters) kp.getPublic();

        KeySpec ks = new RSAPrivateKeySpec(privParams.getModulus(), privParams.getExponent());
        PrivateKey priv = KeyFactory.getInstance("RSA").generatePrivate(ks);

        ks = new RSAPublicKeySpec(pubParams.getModulus(), pubParams.getExponent());
        PublicKey pub = KeyFactory.getInstance("RSA").generatePublic(ks);

        byte[] data = PLAINTEXT.getBytes();
        byte[] sig = CryptoHelper.sshSignatureBlobSign(data, priv);

        Assert.assertTrue(CryptoHelper.sshSignatureBlobVerify(data, sig, pub));
    }

    @Test
    public void testSSHSignatureBlobSign_DSA() throws Exception {
        DSAKeyPairGenerator dsakpg = new DSAKeyPairGenerator();
        DSAParametersGenerator dpg = new DSAParametersGenerator();
        dpg.init(1024, 8, new SecureRandom());
        DSAParameters dsaparams = dpg.generateParameters();
        DSAKeyGenerationParameters params = new DSAKeyGenerationParameters(new SecureRandom(), dsaparams);
        dsakpg.init(params);

        AsymmetricCipherKeyPair kp = dsakpg.generateKeyPair();

        DSAPrivateKeyParameters privParams = (DSAPrivateKeyParameters) kp.getPrivate();
        DSAPublicKeyParameters pubParams = (DSAPublicKeyParameters) kp.getPublic();

        KeySpec ks = new DSAPrivateKeySpec(privParams.getX(), privParams.getParameters().getP(),
                privParams.getParameters().getQ(), privParams.getParameters().getG());
        PrivateKey priv = KeyFactory.getInstance("DSA").generatePrivate(ks);

        ks = new DSAPublicKeySpec(pubParams.getY(), pubParams.getParameters().getP(),
                pubParams.getParameters().getQ(), pubParams.getParameters().getG());
        PublicKey pub = KeyFactory.getInstance("DSA").generatePublic(ks);

        byte[] data = PLAINTEXT.getBytes();
        byte[] sig = CryptoHelper.sshSignatureBlobSign(data, priv);

        Assert.assertTrue(CryptoHelper.sshSignatureBlobVerify(data, sig, pub));
    }

    //
    // Shamir Secret Sharing Scheme
    //

    @Test
    public void testSSSSGF256ExpTable() {

        //
        // GF256 exp table with generator 2 and prime polynomial 0x11D
        // as used for the Reed Salomon of QR Code
        //

        short GF256_exptable[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd,
                0x87, 0x13, 0x26, 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18,
                0x30, 0x60, 0xc0, 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee,
                0xc1, 0x9f, 0x23, 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9,
                0x6f, 0xde, 0xa1, 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e,
                0x3c, 0x78, 0xf0, 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b,
                0xb6, 0x71, 0xe2, 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0,
                0xbd, 0x67, 0xce, 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97,
                0x33, 0x66, 0xcc, 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84,
                0x15, 0x2a, 0x54, 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4,
                0xd5, 0xb7, 0x73, 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b,
                0xf6, 0xf1, 0xff, 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5,
                0x57, 0xae, 0x41, 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd,
                0xa7, 0x53, 0xa6, 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac,
                0x45, 0x8a, 0x09, 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb,
                0x8b, 0x0b, 0x16, 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad,
                0x47, 0x8e, 0x01 };

        for (int i = 0; i < 256; i++) {
            Assert.assertEquals(GF256_exptable[i], SSSSGF256Polynomial.GF256_exptable[i]);
        }
    }

    @Test
    public void testSSSSGF256LogTable() {

        //
        // GF256 log table with generator 2 and prime polynomial 0x11D
        // as used for the Reed Salomon of QR Code
        //

        short GF256_logtable[] = { 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b,
                0x68, 0xc7, 0x4b, 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8,
                0x08, 0x4c, 0x71, 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0,
                0x12, 0x82, 0x45, 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d,
                0xe4, 0x72, 0xa6, 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10,
                0x91, 0x22, 0x88, 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83,
                0x38, 0x46, 0x40, 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa,
                0x85, 0xba, 0x3d, 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73,
                0xf3, 0xa7, 0x57, 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31,
                0xc5, 0xfe, 0x18, 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23,
                0x20, 0x89, 0x2e, 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc,
                0xfc, 0xbe, 0x61, 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47,
                0x6d, 0x41, 0xa2, 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f,
                0x0c, 0x6f, 0xf6, 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb,
                0xcc, 0x3e, 0x5a, 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a,
                0x75, 0x2c, 0xd7, 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8,
                0x50, 0x58, 0xaf, 0x01 };

        for (int i = 1; i < 255; i++) {
            Assert.assertEquals(GF256_logtable[i], SSSSGF256Polynomial.GF256_logtable[i]);
        }
    }

    @Test
    public void testSSSSSplit_InvalidN() {
        try {
            int n = 1;
            int k = 1;

            List<byte[]> secrets = CryptoHelper.SSSSSplit(PLAINTEXT.getBytes("UTF-8"), n, k);
            Assert.assertNull(secrets);

            n = 256;
            k = 3;

            secrets = CryptoHelper.SSSSSplit(PLAINTEXT.getBytes("UTF-8"), n, k);
            Assert.assertNull(secrets);
        } catch (Exception e) {
            Assert.assertTrue(false);
        }
    }

    @Test
    public void testSSSSSplit_InvalidK() {
        try {
            int n = 2;
            int k = 1;

            List<byte[]> secrets = CryptoHelper.SSSSSplit(PLAINTEXT.getBytes("UTF-8"), n, k);
            Assert.assertNull(secrets);

            n = 2;
            k = 3;

            secrets = CryptoHelper.SSSSSplit(PLAINTEXT.getBytes("UTF-8"), n, k);
            Assert.assertNull(secrets);
        } catch (Exception e) {
            Assert.assertTrue(false);
        }
    }

    @Test
    public void testSSSSRecover() {

        List<byte[]> secrets = new ArrayList<byte[]>();

        secrets.add(Hex.decode(
                "ab1327f622da10069f97743378dce02b6bd797ce0c4b72d1f09ead9e96f027d76625d8e2fe29c2a29ef330e194debc04"));
        secrets.add(Hex.decode(
                "e7c83a5b4193fe10b568af7e8a5981e99f11bb3840bcc7b2ebc4233ee378a0140189c4384b389d3c379daaf3de16b6cf"));
        secrets.add(Hex.decode(
                "d755e4d580d9f707c899b8a8ef29ee2595698b0fad871a08bd24217ae7bec109367518688460064e7124e715b69268dc"));
        secrets.add(Hex.decode(
                "79641dc25fef964d64d2fd2d0f6e2c5040243ed93b6595285faeecb1eb8739b531b89b862d9d5356e233579b819c6348"));

        List<byte[]> shares = new ArrayList<byte[]>();
        shares.addAll(secrets);

        //
        // Remove a random element
        //

        shares.remove(Math.random() * shares.size());

        byte[] secret = CryptoHelper.SSSSRecover(shares);

        Assert.assertEquals(PLAINTEXT, new String(secret));
    }

    @Test
    public void testSSSSRecover_DuplicateShare() {

        List<byte[]> secrets = new ArrayList<byte[]>();

        secrets.add(Hex.decode(
                "ab1327f622da10069f97743378dce02b6bd797ce0c4b72d1f09ead9e96f027d76625d8e2fe29c2a29ef330e194debc04"));
        secrets.add(Hex.decode(
                "e7c83a5b4193fe10b568af7e8a5981e99f11bb3840bcc7b2ebc4233ee378a0140189c4384b389d3c379daaf3de16b6cf"));
        secrets.add(Hex.decode(
                "e7c83a5b4193fe10b568af7e8a5981e99f11bb3840bcc7b2ebc4233ee378a0140189c4384b389d3c379daaf3de16b6cf"));

        byte[] secret = CryptoHelper.SSSSRecover(secrets);

        Assert.assertNull(secret);
    }

    //
    // PGP
    //

    @Test
    public void testPGPKeysFromKeyRing() throws IOException {
        String keyring = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" + "Version: GnuPG v1.4.6 (Darwin)\n" + "\n"
                + "mQGiBFDfB/cRBADE6Ee9TtA961l9dtQYauMJ5LCo/YWhz1dft0KmqI7k7sKWLKfz\n"
                + "OhTOnT61fwEhHdHlOwQdCD7EpeKEGfSWxeajdtuKE9/QP+PJalGA5s48XrdqfrkA\n"
                + "QJkK+77atAixoi4r9ozljP9vXHIltAlDkaoDdRZcVe1J+pW0Kw7AGHvA/wCgvwKI\n"
                + "cuyep7ViScOXkCwZ6+7eFqsD/RLzBN7mb2h+yEY+XvFqQPvenvZS/sw3JZf/cY4u\n"
                + "Mi+FzkTb0BB1X75skLvvO1JYpraGphSB075LzHW/ohKQacaY74rpxpxIZz9EjHTa\n"
                + "JSmLTT6SBQMlX+LSNwHQYQWPzitQ1os6LRmgiE5pfZGlvOLyC+sHeDxUzPEl1069\n"
                + "NqXEA/9r1e4eAu7HLED2XIP3fgOV/kkDrJC1EX0N8Ck/ON0S+hJYK1b0W6TKWdN6\n"
                + "tVH/OL37tymsfI+qSEhKNVe2sDcybG6trJj528puJdVpb2wqMwbCdxx7Cr3wX61x\n"
                + "jFQJQwqyXCWakPbWfhxvron62/RamTmf2KSMgf79yv29WOE5+7QbTWFzdGVyU2Vj\n"
                + "cmV0R2VuZXJhdG9yVGVzdCMxiGYEExECACYFAlDfB/cCGwMFCQABUYAGCwkIBwMC\n"
                + "BBUCCAMEFgIDAQIeAQIXgAAKCRD3wPNFoZ4UAw4KAJ47rbv6e5oy0p0qOu1YjCUn\n"
                + "7Sm+PACePylkvbBc7jkoJrc8n+2ZJRBL/vK5Ag0EUN8H/BAIAJdLjwQf2NwhkW/9\n"
                + "h7wV2luiCvzwPxhvOytPM9ZtckyK3f9Biam29uZt2P/EgYAlEb7odHuQ8rYquuM8\n"
                + "rZ5bNMY4SlgDfGTAYIPTC6r3oPoxVzg3bfL/VfAQWZTz7gsNexBqoxmCEGG8cbp4\n"
                + "/YYTArrW0pdAjIve/H2Wb3C6+ntbPXq60BJTlpbJXh3CPL95jUF0bJbt/WwOdE5r\n"
                + "TQ0WKikTY8RV18XekJAHRT0PrHjecAsvY1NOXlQJGbJes7unQDdCkQ2RRbg4Vdt4\n"
                + "SHSdKunIIxbLEOj6HuJyvkbQ65yHSnfLtoS2XpNe9ft/+ZtXjHsr01XE0cqbrSwf\n"
                + "GqO9068AAwcIAJS0myak/K/rqwC/MGQ7U4OEovVY/n9mpPwQKN0bUSU/uDLKy3JW\n"
                + "vqO5vvWr9iWqyq/GfPeJ2HZ/kvGiyR7Qy/7gh8Q8yDLn9qrz06ewd9G3Tyxj8n80\n"
                + "re0vRopQsyKNLhtC5ZEtq9Q3yfqt7ib8sf8hLlxCzpDNlIUdbTqpFcnfxc8p7aQB\n"
                + "4lqrT32fGtYtDjUt86VzT4LCRNTgMOxPF5iYOiOzB0iX7oPoCqGFxl0ZTvxqMpgV\n"
                + "/hr8CWJlW3AAcc3l2HONQe/Gg5nrTtm72i0vH8n8F/GgfZmU8KJc7c7cFhtGDTWV\n"
                + "dkNjrqBtuiuKpZcwf14stCFfAmZXeYZ+xTCITwQYEQIADwUCUN8H/AIbDAUJAAFR\n"
                + "gAAKCRD3wPNFoZ4UA9oLAJsFL3JRi2zHxwutO7PqMfItSub0cACgs7BQ3nPA5DP+\n" + "Hhr3Xwsu7+wSOKk=\n"
                + "=H4+g\n" + "-----END PGP PUBLIC KEY BLOCK-----\n";

        List<PGPPublicKey> pubkeys = CryptoHelper.PGPPublicKeysFromKeyRing(keyring);

        Assert.assertEquals(2, pubkeys.size());

        Set<Long> keyids = new HashSet<Long>();

        for (PGPPublicKey key : pubkeys) {
            keyids.add(key.getKeyID());
        }

        Assert.assertTrue(keyids.contains(0xf7c0f345a19e1403L));
        Assert.assertTrue(keyids.contains(0x60744f29e427916cL));
    }

    //
    // SSHAgent
    //  
}