【问题标题】:Encrypt and decrypt a SecretKey with RSA public and private keys使用 RSA 公钥和私钥加密和解密 SecretKey
【发布时间】:2016-03-01 16:05:34
【问题描述】:

我正在尝试用我的 publicKey 加密一个 secretKey,然后用私钥在其他地方解密它。我可以很好地加密和解密,但是当我这样做时,我得到了一个完全不同的密钥。

这是创建公钥/私钥对的代码

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;
}

我指定了 SunJSSE 提供程序,但与使用 SunJCE 或 RSA/SunRSASign 提供程序的 DiffieHellman 运行时没有任何不同的结果。我是 Java 安全的新手,所以这些概念仍然有点超出我的想象。

这是我用来生成密钥的代码

    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;
}

这是我用来加密/解密我的密钥的两种方法

    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;
}

RSA 算法是我唯一可以使用我的密钥的算法。如果我指定 DiffieHellman alg。对于密钥对,我根本无法加密/解密。如果有人对我做错了什么有任何见解,我们将不胜感激。当我在当前状态下调用它时,我从这个值的密钥开始 = cGFzczEyMw== 并在加密/解密后以这个值的密钥结束

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

【问题讨论】:

    标签: java encryption rsa jce secret-key


    【解决方案1】:

    在做之前你首先应该知道你想做什么:

    • 没有填充的 RSA 完全不安全;
    • 您使用基于密码的加密密钥,这仅对密码有意义;
    • 你得到了一个 DES 密钥,这又是完全不安全的;
    • 您可能使用随机的盐生成它,因此输出是随机的。

    整个协议没有意义。您尝试直接使用 DH(一种执行密钥协商的方案)进行加密,这表明您对加密的研究还不够。

    使用密码学不是为了让事情发挥作用。这是为了让事情安全。你不能仅仅通过尝试来做到这一点。至少了解密码学的基础知识然后编码

    【讨论】:

    • 我使用了 PBE 的密码,而不是您上面建议的密钥。我从来没有拿出 DES 密钥,所以我不确定你在哪里看到这个。此外,我没有按照您的建议使用 DH 进行加密/解密,尽管我试图从该算法中获取工作密钥。该代码准确地显示了我正在尝试的内容。我相信这些都是基本概念。
    • 我的错误。谢谢
    【解决方案2】:

    事实上,问题在于我存储/检索密钥的方式。我为私人使用了一个密钥库,为公共使用了一个文件。我检索这些密钥的方式导致它们格式错误,因此我的密码失败并且需要使用 NOPADDING 运行以获得任何类型的输出。 这是我用于 RSA 密钥的新存储代码 - 将它们写入文件。

        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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-08
      • 2013-05-07
      • 2017-05-11
      • 1970-01-01
      • 2020-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多