【问题标题】:RSA Encryption Illegal Block Size ExceptionRSA 加密非法块大小异常
【发布时间】:2019-04-26 20:34:57
【问题描述】:

我正在尝试使用端到端加密进行聊天,但我在这条线上得到了javax.crypto. IllegalBlockSizeExceptionbyte[] decryptedMessage = cipher.doFinal(decodedMessage);

我用这个得到别人的公钥:

CollectionReference userCollection = FirebaseFirestore.getInstance().collection("users");

userCollection.whereEqualTo("userID", targetFriendID).get().addOnCompleteListener(new OnCompleteListener < QuerySnapshot > () {@Override
    public void onComplete(@NonNull Task < QuerySnapshot > task) {

        if (task.isSuccessful()) {

            for (QueryDocumentSnapshot doc: task.getResult()) {

                User tempUser = doc.toObject(User.class);

                targetFriendSDK = tempUser.getSDK();

                String keyString = tempUser.getPublicKey();

                byte[] keyBytes = Base64.decode(keyString, Base64.NO_WRAP);

                try {

                    friendPublicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes));

                    dialog.cancel();

                } catch(Exception e) {
                    dialog.cancel();
                    Toast.makeText(ChatRoom.this, "Error, try again", Toast.LENGTH_SHORT).show();
                }

            }

        } else {
            dialog.cancel();
            Toast.makeText(ChatRoom.this, "Error", Toast.LENGTH_SHORT).show();
        }

    }
});

解密是这样完成的:

String encodedMessage = cloudMessage.getMessage();
Date date = cloudMessage.getDate();
tring senderID = cloudMessage.getSenderID();
String receivID = cloudMessage.getReceiverID();

int sdk = Build.VERSION.SDK_INT;

byte[] decodedMessage = Base64.decode(encodedMessage, Base64.NO_WRAP);

String finalMessage;

try {

    if (sdk >= Build.VERSION_CODES.M) {

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

        OAEPParameterSpec sp = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);

        cipher.init(Cipher.DECRYPT_MODE, privateKey, sp);

        byte[] decryptedMessage = cipher.doFinal(decodedMessage);

        finalMessage = new String(decryptedMessage);

    } else {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] decryptedMessage = cipher.doFinal(decodedMessage);

        finalMessage = new String(decryptedMessage);

    }

和加密:

byte[] messageBytes = messageText.getBytes();

String encodedMessage;

try {

    if (targetFriendSDK >= Build.VERSION_CODES.M) {

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

        OAEPParameterSpec sp = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);

        cipher.init(Cipher.ENCRYPT_MODE, friendPublicKey, sp);

        byte[] cipherText = cipher.doFinal(messageBytes);

        encodedMessage = Base64.encodeToString(cipherText, Base64.NO_WRAP);

    } else {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, friendPublicKey);

        byte[] cipherText = cipher.doFinal(messageBytes);

        encodedMessage = Base64.encodeToString(cipherText, Base64.NO_WRAP);

    } 

我在做基本相同的事情,但一个用户在另一个活动中,一切正常,这些活动之间的唯一区别是,在这个活动中,我尝试获取其他用户的公钥。

【问题讨论】:

    标签: android encryption rsa


    【解决方案1】:

    好的,我找到了解决方案,看起来它完全不是我所期望的。

    问题实际上是这一行 if (targetFriendSDK &gt;= Build.VERSION_CODES.M) 我正在检查其他用户的设备 Android 版本,以便区分我应该使用的加密类型。我意识到由于 Firestore 命名问题,它总是返回 0。

    我创建了一个User文档解析自定义用户类来创建文档,其中一个字段sdk字段被命名为private int SDK;,大写字母,但在实际的Firestore中它被保存为sdk,带有小写字母,当我从 Firestore 获取用户时,我使用了 .toObject(User.class);,这可能是它在寻找 sdk 的地方,因为它在数据库中但只找到 SDK,所以字段不匹配,它是留下0

    结论:在Firestore中命名字段时不要使用大写字母,因为它会在数据库中将它们更改为小字母,并且在尝试从Firestore中将文档作为Object Class取回时会导致问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-31
      • 1970-01-01
      • 2010-12-10
      相关资源
      最近更新 更多