如何获取序列化密文消息的类型?

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

我根据 Signal 的文档使用 libsignal-protocol-java 在消息应用程序中实现端到端加密。

假设爱丽丝向鲍勃发送一条(成对的)序列化密文消息。 Bob 如何知道如何反序列化它?他不是首先需要知道密文消息的类型吗?我的理解是,成对密文消息可以是信号消息(

WHISPER_TYPE
)或预密钥信号消息(
PREKEY_TYPE
)。那么 Bob 如何知道它是什么类型呢?

Alice 是否也应该向 Bob 发送密文消息的类型(作为明文)?

或者 Bob 是否有其他方法可以检测类型?例如,Bob 是否应该尝试将其反序列化为信号消息,如果失败,则尝试将其反序列化为预关键信号消息?

java encryption end-to-end-encryption signal-protocol
3个回答
2
投票

在查看了Signal Android的源代码后,我认为Alice也应该向Bob发送密文消息的类型(作为明文)。

在课堂上

SignalServiceCipher
:


0
投票

1 - Alice 生成identityKeyPair(长期)、signedPreKey(中期)和临时PreKeys 并将这些密钥保存到base64 中的存储中。 例如

public static String generateIdentityKeyPair() {
    IdentityKeyPair identityKeyPair = KeyHelper.generateIdentityKeyPair();
    return encodeToBase64(identityKeyPair.serialize());
}

2 - 发送

  • 序列化格式的服务器预密钥 ID 和公钥列表
  • 签名的 PreKey Id、signedPreKeyPublicKey、signedPreKeyRecordSignature
  • IdentityKeyPair 的公钥
  • 注册ID

对于加密和解密,您首先必须进行加密会话

private void initSessionFromPreKey() throws UntrustedIdentityException, InvalidKeyException {
        InMemorySignalProtocolStore protocolStore = new InMemorySignalProtocolStore(localUser.getIdentityKeyPair(), localUser.getRegistrationId());
        protocolStore.storePreKey(localUser.getPreKeys().get(0).getId(), localUser.getPreKeys().get(0));
        protocolStore.storeSignedPreKey(localUser.getSignedPreKey().getId(), localUser.getSignedPreKey());
        this.protocolStore = protocolStore;


        //Session
        SessionBuilder sessionBuilder = new SessionBuilder(protocolStore, remoteUser.getSignalProtocolAddress());
        PreKeyBundle preKeyBundle = new PreKeyBundle(
                remoteUser.getRegistrationId(),
                remoteUser.getSignalProtocolAddress().getDeviceId(),
                remoteUser.getPreKeyId(),
                remoteUser.getPreKeyPublicKey(),
                remoteUser.getSignedPreKeyId(),
                remoteUser.getSignedPreKeyPublicKey(),
                remoteUser.getSignedPreKeySignature(),
                remoteUser.getIdentityKeyPairPublicKey()
        );

        sessionBuilder.process(preKeyBundle);
        mSessionCipher = new SessionCipher(protocolStore, protocolAddress);
    }

加密与解密

public String encrypt(String message) throws InvalidVersionException, InvalidMessageException, UntrustedIdentityException, InvalidKeyException {
        createSession(Operation.ENCRYPT);
        CiphertextMessage ciphertextMessage = mSessionCipher.encrypt(message.getBytes());
        PreKeySignalMessage preKeySignalMessage = new PreKeySignalMessage(ciphertextMessage.serialize());
        return KeyUtils.encodeToBase64(preKeySignalMessage.serialize());
    }

    public String decrypt(String message) throws InvalidVersionException, InvalidMessageException, InvalidKeyException, DuplicateMessageException, InvalidKeyIdException, UntrustedIdentityException, LegacyMessageException {
        createSession(Operation.DECRYPT);
        byte[] bytes = KeyUtils.decodeToByteArray(message);
        byte[] decryptedMessage = mSessionCipher.decrypt(new PreKeySignalMessage(bytes));
        return new String(decryptedMessage, StandardCharsets.UTF_8);
    }

您还可以查看 github 上提供的其他源代码 https://github.com/lvijay/DemoSignal

https://github.com/signalapp/libsignal-protocol-java/pull/21/commits/3496ed996359f6d3d8ee52dcecb8f8b0d45b3cbc(库作者使用的是信号协议的包装器,您可以将包装器库更改为信号协议)


0
投票

你可以在我的 github 上找到工作示例 https://github.com/eatakishiyev/signal-protocol-example

© www.soinside.com 2019 - 2024. All rights reserved.