Android Studio/ Java - 小 input/output 大小的 RSA 加密

Android Studio/ Java - RSA Encryption with small input/output size

我被要求使用 RSA 加密在蓝牙节点之间发送数据,这是我研究任何形式的加密的第一周,所以我需要一些帮助。

看来输出大小总是与模数的大小有关。 Mod 2048 和 1024 似乎很流行,它们分别具有 256 字节和 128 字节的输出大小。

我正在使用仅接受大小为 20(字节)的数据包的蓝牙低功耗(蓝牙智能)节点。

我的问题:如果我只能发送 20 个字节,加密数据有什么意义吗?我不认为将 20 字节的数据加密为 20 字节是合理的……这算不上什么加密。我什至不确定是否可以设置 160 的模数来加密它?如果您想知道,为什么模数为 160?这是因为 if (2048 / 8 = 256 bytes), then (160 / 8 = 20 bytes).

新信息: 我不能发送多个数据包,因为这个系统是网状系统。也就是说,每次我发送数据包时,节点都会断开与发送方的连接,然后将消息广播到空中的任何节点。我需要大约 4 秒才能发送第二个数据包。

到目前为止,我已经编写了一些测试代码只是为了亲自动手并检查加密 20 字节的默认输出(最终是 256 字节输出)。

public class Encryption {

    // Possibly use files for saving keys
    private static String PUBLIC_KEY_FILE = "Public.key";
    private static String PRIVATE_KEY_FILE = "Private.key";

    Key publicKey = null;
    Key privateKey = null;
    KeyPairGenerator kpg;
    KeyPair kp;
    Cipher cipher;

    public Encryption() {

        try {
            kpg = KeyPairGenerator.getInstance("RSA");
            kp = kpg.generateKeyPair();
            publicKey = kp.getPublic();
            privateKey = kp.getPrivate();
        } catch (Exception e) {
            Log.e("Encryption", "RSA KeyPair Error...");
            e.printStackTrace();
        }
    }

    // Encode
    public byte[] encode(byte[] bytesToEncode) {
        byte[] encodedBytes = null;

        try {
            // Basic Cipher (mode/padding excluded for now)
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            encodedBytes = cipher.doFinal(bytesToEncode);
        } catch (Exception e) {
            Log.e("Encryption", "RSA Encoding Error...");
            e.printStackTrace();
        }

        return encodedBytes;
    }

    public byte[] decode(byte[] encodedBytes) {
        byte[] decodedBytes = null;

        try {
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            decodedBytes = cipher.doFinal(encodedBytes);
        } catch (Exception e) {
            Log.e("Encryption", "RSA Decoding Error...");
            e.printStackTrace();
        }

        return decodedBytes;
    }
}

正如您在我的全局变量中看到的那样,我稍后必须更改代码以在某个时候保存这些密钥,而不是每次都重新创建它们,所以我总是使用相同的密钥对。此外,我需要将 public 密钥文件提供给编写节点固件的工程师,以便他可以解码我的加密。因为我严格使用字节,所以我不应该有字符集问题。

您正在尝试重新发明轮子:

  • 您应该只使用 RSA 来签署和加密您将在设备之间共享的随机生成的密钥,而不是交换任何其他类型的数据。

  • 那么您应该使用这些密钥和对称算法来验证和加密您设备之间的数据。

如今,标准的 RSA 密钥长度约为 2048 位。

如今标准的 AES 对称密钥长度约为 256 位。

但是密钥大小和块大小不一样:AES 块大小是 16 字节。这应该很适合您的小包裹。

更准确地说,由于您的数据大小可能不正好是 16 个字节,因此您应该使用分组密码算法(例如 CBC)或流密码算法(例如 GCM)来处理您的数据AES 或其他对称算法。

最先进的 AES-256-GCM 算法将身份验证和加密集成在单个流密码中。由于您应该始终在尝试解密之前对数据进行身份验证(大多数不遵守此规则的人都遇到过问题),因此仅使用 AES-256-CBC 之类的东西是个坏主意。

最后,请注意您正在使用的蓝牙 LE 引入了 AES-CCM,用于保密性、完整性和身份验证。愿您基于此功能进行交流以实现您的目标。