JAVA - AES密钥长度不匹配

问题描述 投票:0回答:1

我有两种方法可以在客户端和服务器之间加密/解密JSON消息。服务器有一对RSA密钥(一个私有和一个公共),客户端也是如此。此外,两者都可以访问首次建立通信时生成的对称会话密钥,用于加密JSON消息,因为通道本身不安全。客户端生成一个AES密钥(会话密钥),然后使用服务器的公钥(所有人都知道)对其进行密码并将其发送到服务器,服务器将解密会话密钥并将其存储在客户ID下的HashMap中。

不过这是问题所在:我在发送之前检查了密钥长度,长度为16个字节。当服务器收到加密的会话密钥并对其进行解密时,它的长度为24个字节。我假设在密码或解密操作期间出现了问题。这是一个问题,因为当客户端想要开始发送请求时(以加密的JSON消息的形式),服务器无法解密和读取请求,因为密钥的大小错误(它会抛出一个java.security.InvalidKeyException:非法的密钥大小或默认参数)。

密码/解密方法发布如下:

public String cipher(Key key, String alg, String msg){
    try {
        Cipher c = Cipher.getInstance(alg);
        c.init(Cipher.ENCRYPT_MODE, key);
        return encoder.encodeToString(c.doFinal(msg.getBytes("UTF-8")));
    } catch (IllegalBlockSizeException e) {
        (...)
    }
}

encoder / decoder来自java.util.Base64

public String decipher(Key key, String alg, String msg){
    try {
        Cipher c = Cipher.getInstance(alg);
        c.init(Cipher.DECRYPT_MODE,key);
        return new String(c.doFinal(decoder.decode(msg)), "UTF-8");
    } catch (IllegalBlockSizeException e) {
        (...)
    }
}

客户端加密并发送会话密钥:

SecretKey sk = KeyGenerator.getInstance("AES/CBC/PKCS5Padding").generateKey();

System.out.println(sk.getEncoded().length) //length = 16 bytes

String sessionKey = cipher(client.getServerPublicKey(),
    "RSA/ECB/PKCS5Padding", encoder.encodeToString(sk.getEncoded()));

printWriter.write("{(...), \"key\":\"" + sessionKey + "\"}");

服务器接收加密的会话密钥并将其保存在HashMap中:

byte[] aux = decipher(registry.getServerPrivateKey(),
    "RSA/ECB/PKCS5Padding", data.get("key").toString().replace("\"", ""))
        .getBytes("UTF-8");

System.out.println(aux.length) //length = 24 bytes

registry.addSession(..., new SecretKeySpec(aux, 0, aux.length, "AES"));

我尝试过不同的算法和不同的填充,但我似乎无法弄清楚错误的位置。

java encryption client-server aes rsa
1个回答
1
投票

在使用此语句进行加密之前,您对base64进行了base64编码:

String sessionKey = cipher(client.getServerPublicKey(),
    "RSA/ECB/PKCS5Padding", encoder.encodeToString(sk.getEncoded()));

..将您的16字节密钥转换为24个字符长的base64表示。在加密之前,您不需要对密钥进行base64编码,因为加密完全能够处理二进制数据。试试这个:

String sessionKey = cipher(client.getServerPublicKey(),
    "RSA/ECB/PKCS5Padding", sk.getEncoded());

同时改变你的qazxsw poi方法接受msg作为qazxsw poi

cipher(..)

另外,将你的byte[]改为二进制,如:

public String cipher(Key key, String alg, byte[] msg){
    try {
        Cipher c = Cipher.getInstance(alg);
        c.init(Cipher.ENCRYPT_MODE, key);
        return encoder.encodeToString(c.doFinal(msg));
    } catch (IllegalBlockSizeException e) {
        (...)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.