简体   繁体   中英

Encrypt and decrypt a SecretKey with RSA public and private keys

I am trying to encrypt a secretKey with my publicKey, then decrypt it somewhere else with the private key. I can encrypt and decrypt fine, However I am getting a completely different key back when I do this.

Here is the code that creates the public/ private keypair

public static KeyPair generateKeyPair()
{
    KeyPair returnPair = null;
    try
    {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "SunJSSE");

        System.out.println("provider:" + kpg.getProvider().getName());

        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

        kpg.initialize(1024, random);

        returnPair = kpg.generateKeyPair();

    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return returnPair;
}

I specified the SunJSSE provider, although I am not getting any different result than when I ran with DiffieHellman from SunJCE or the RSA/ SunRSASign provider. I am new to java security so these concepts are still a little above my head.

Here is the code I use to generate the secret key

    public static SecretKey generateSecretKey(String keyPassword)
{
    SecretKey key = null;
    try
    {
        SecretKeyFactory method = SecretKeyFactory.getInstance("PBEWithMD5AndDES");

        //System.out.println("salt length: " + new SaltIVManager().getSalt().length);

        PBEKeySpec spec = new PBEKeySpec(keyPassword.toCharArray(), new SaltIVManager().getSalt(), 10000, 128);

        key = method.generateSecret(spec);

        System.out.println("generate secret key length: " + key.getEncoded().length); 

    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return key;
}

And here are the two methods I use to encrypt/ decrypt my secret key

    public static byte[] encryptSecretKey(SecretKey secretKey, PublicKey publicKey)
{
    byte[] encryptedSecret = null;
    try
    {

        Cipher cipher = Cipher.getInstance("RSA/ECB/NOPADDING");

        System.out.println("provider: " + cipher.getProvider().getName());

        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        System.out.println("original secret key: " + Base64.getEncoder().encodeToString(secretKey.getEncoded()) + " \n secretkey encoded length: " + secretKey.getEncoded().length);

        encryptedSecret = cipher.doFinal(secretKey.getEncoded());


        System.out.println("encrypted secret: " + Base64.getEncoder().encodeToString(encryptedSecret)); 

    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return encryptedSecret;
}



public static SecretKey decryptSecretKey(byte[] encryptedKey, PrivateKey privateKey)
{
    SecretKey returnKey = null;
    try
    {
        Cipher cipher = Cipher.getInstance("RSA/ECB/NOPADDING");

        System.out.println("provider: " + cipher.getProvider().getName());

        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        System.out.println("encryptedkey length: " + encryptedKey.length);

        byte [] encodedSecret = cipher.doFinal(encryptedKey);

        System.out.println("encoded Secret after decrypt: " + Base64.getEncoder().encodeToString(encodedSecret));

        returnKey = new SecretKeySpec(encodedSecret, 0, encodedSecret.length, "PBEWithMD5AndDES");

        System.out.println("secret key: " + Base64.getEncoder().encodeToString(returnKey.getEncoded()));

        System.out.println("secret key length post decrypt: " + returnKey.getEncoded().length);
    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return returnKey;
}

The RSA algorithm is the only one I have gotten to work with my keys. If I specify the DiffieHellman alg. for the keypair, I am unable to encrypt/ decrypt at all. If anyone has any insight into what I have done wrong, any help would be greatly appreciated. When I call this in its current state, I start with a secretkey of this value = cGFzczEyMw== and end with a key of this value after encryption/ decryption

SvMNufKu2JA4hnNEwuWdOgJu6FxnNmuLYzxENhTsGgFzc/i3kQIXbeVaJUkJck918BLCnm2u2QZCyVvJjYFXMLBFga0Zq0WMxSbIZvPz1J/EDi9dpsAkbFhLyBWmdDyPr+w7DMDsqHwKuA8y/IRKVINWXVrp3Hbt8goFZ0nGIlKVzMdJbGhNi3HZSAw4R6fXZNKOJ3nN6wDldzYerEaz2MhJqnZ3Dz4psA6gskomhjp/G0yhsGO8pllMcgD0jzhL86RGrBhjj04Bj0ps3AAACkQLcCwisso8dWigvR8NX9dnI0C/gc6FqmNenWI1/AoPgmcRyFdlO7A2i9JXoSj+YQ==

You first should know what you are trying to do before doing it:

  • RSA without padding is completely insecure;
  • you use a key for Password Based Encryption which only makes sense with - well - a password;
  • you come out with a DES key, which again is completely insecure;
  • you probably generate it with a salt, which is random, so the output is random.

The whole protocol doesn't make sense. That you're trying to encrypt directly with DH (a scheme to perform key agreement) shows that you haven't studied crypto enough.

With cryptography it's not about getting things to work. It's about getting things secure . You cannot do that by just trying things out. Learn at least the basics of cryptography then code .

The issue in fact was the way in which I was storing/ retrieving my keys. I had used a keystore for the private and a file for the public. The way in which I retrieved these keys was causing them to become malformed, thus the failure in my cipher and the need to run with NOPADDING in order to get any sort of output. Here is the new storage code I am using for RSA keys- writing them to a file.

    public static boolean saveKeys(Key privateKey, Key publicKey, char[] password, String alias)
{
    boolean saved = false;
    try
    {
        KeyPair kp = generateKeyPair();


        KeyFactory kf = KeyFactory.getInstance("RSA");

        if(privateKey != null)
        {

            File privKeyFile = new File(System.getProperty("user.home") + "/.etc/privkey");

            if(!privKeyFile.exists())
            {
                privKeyFile.createNewFile();
            }

            System.out.println("private key: " + Base64.getEncoder().encodeToString(kp.getPrivate().getEncoded()));

            RSAPrivateKeySpec pubSpec = kf.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);

            ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(System.getProperty("user.home") + "/.etc/privkey")));

            oout.writeObject(pubSpec.getModulus());

            oout.writeObject(pubSpec.getPrivateExponent());

            oout.close();


        }if(publicKey != null)
        {

            File pubKeyFile = new File(System.getProperty("user.home") + "/.etc/pubkey.pub");

            if(!pubKeyFile.exists())
            {
                pubKeyFile.createNewFile();
            }

            System.out.println("public key: " + Base64.getEncoder().encodeToString(kp.getPublic().getEncoded()));

            RSAPublicKeySpec pubSpec = kf.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);

            ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(System.getProperty("user.home") + "/.etc/pubkey.pub")));

            oout.writeObject(pubSpec.getModulus());

            oout.writeObject(pubSpec.getPublicExponent());

            oout.close();

        }



    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return saved;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM