Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中使用RSA加密加密密钥_Java_Encryption_Rsa_Encryption Asymmetric_Secret Key - Fatal编程技术网

在Java中使用RSA加密加密密钥

在Java中使用RSA加密加密密钥,java,encryption,rsa,encryption-asymmetric,secret-key,Java,Encryption,Rsa,Encryption Asymmetric,Secret Key,我正在开发一个客户机-服务器安全协议,在该协议中,我需要使用Java中的RSA对HMAC摘要的SecretKey进行加密,因为密钥必须发送到服务器。加密分为两个阶段;首先,我需要用公共非对称密钥加密对称密钥,然后,用私有非对称密钥加密加密的消息 为此,我将生成SecretKey,如下所示: public SecretKey generate(){ KeyGenerator generator = KeyGenerator.getInstance("HMACSHA256"); k = genera

我正在开发一个客户机-服务器安全协议,在该协议中,我需要使用Java中的RSA对HMAC摘要的SecretKey进行加密,因为密钥必须发送到服务器。加密分为两个阶段;首先,我需要用公共非对称密钥加密对称密钥,然后,用私有非对称密钥加密加密的消息

为此,我将生成SecretKey,如下所示:

public SecretKey generate(){
KeyGenerator generator = KeyGenerator.getInstance("HMACSHA256");
k = generator.generateKey();
return k;
}
稍后,我将使用以下代码使用公钥加密任何字节数组:

public byte[] encryptPublic(PublicKey key, byte[] array){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(array);
return encrypted;
}
使用私钥加密的代码相同,但使用私钥

对于RSA加密,我使用1024位长的非对称密钥,因此我有两个主要问题:

  • 如何将SecretKey转换为字节数组,以便使用RSA和公钥对其进行加密
  • 由于公钥加密生成一个包含128字节的字节数组,如果密钥长度为1024位且只能加密117字节长的消息,我如何使用私钥再次加密该消息
  • 如何将SecretKey转换为字节数组,以便使用RSA和公钥对其进行加密
  • 这叫做包装:

    public static byte[] wrapKey(PublicKey pubKey, SecretKey symKey)
            throws InvalidKeyException, IllegalBlockSizeException {
        try {
            final Cipher cipher = Cipher
                    .getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
            cipher.init(Cipher.WRAP_MODE, pubKey);
            final byte[] wrapped = cipher.wrap(symKey);
            return wrapped;
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new IllegalStateException(
                    "Java runtime does not support RSA/ECB/OAEPWithSHA1AndMGF1Padding",
                    e);
        }
    }
    
    请注意,这不会首先显式转换为
    字节[]
    。这是因为密钥很可能位于硬件安全模块内。在HSM中,包装是可能的,但是在本地内存中转换为
    字节[]
    通常是不可能的


  • 由于公钥加密生成一个包含128字节的字节数组,如果密钥长度为1024位且只能加密117字节长的消息,我如何使用私钥再次加密该消息
  • 你不应该这样做,你也不能这样做。您不应该这样做的原因是,使用私钥加密不会提供机密性,因为任何人都可以访问公钥

    执行安全的RSA加密需要填充。填充开销(对于PKCS#1v1.5风格的填充,为11字节)禁止您使用私钥进行加密

    请注意,整个操作:PKCS#1中甚至没有指定使用私钥的加密-这不是合法操作



    通常,更安全的临时(EC)DH用于在传输协议中建立密钥,仅将私钥用于身份验证。您可能希望从TLS1.3(草案版本)中得到提示。或者您可能只想使用TLS或其中的握手部分。

    一些评论。1) 在任何地方都不要在加密中使用默认值。在
    getInstance()
    方法中,始终指定由三部分组成的完整转换字符串。2). 不要使用私钥加密,而是执行签名。您可以使用
    Signature
    类来实现这一点。3) 键(包括SecretKeys)使用
    getEncoded()
    方法返回以某种标准格式表示键的字节数组。对于对称密钥,即
    SecretKey
    实例,由
    getEncoded()
    返回的字节数组只是原始密钥字节。对于Q2:您可以使用随机AES密钥加密密文,然后使用另一轮RSA加密新的AES密钥,但为什么要这样做?