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

huangapple go评论89阅读模式
英文:

How to get the type of a serialized ciphertext message?

问题

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

假设Alice向Bob发送了一个(一对一的)序列化密文消息。那么Bob如何知道如何对其进行反序列化?他不是首先需要知道密文消息的类型吗?我理解的是,一对一的密文消息既可以是信号消息(WHISPER_TYPE),也可以是预密钥信号消息(PREKEY_TYPE)。那么Bob如何知道它是哪种类型?

Alice是否也需要将密文消息的类型(作为明文)发送给Bob?

还是Bob可以通过其他方式检测到类型?例如,Bob是否应该尝试将其反序列化为信号消息,如果失败了,再尝试将其反序列化为预密钥信号消息?

英文:

I'm using libsignal-protocol-java according to Signal's Documentation to implement end-to-end encryption in a messaging app.

Let's say Alice sends Bob a (pairwise) serialized ciphertext message. How does Bob know how to deserialize it? Doesn't he first need to know the type of the ciphertext message? My understanding is that a pairwise ciphertext message could either be a signal message (WHISPER_TYPE) or a pre key signal message (PREKEY_TYPE). So how does Bob know which type it is?

Is Alice supposed to also send Bob the type (as plaintext) of the ciphertext message?

Or is there another way that Bob could detect the type? For example, is Bob supposed to try to deserialize it as if it's a signal message, and if that fails, then try to deserialize it as if it's a pre key signal message?

答案1

得分: 2

在审查了Signal Android的源代码之后,我认为Alice应该还需要将消息的类型(以明文形式)一并发送给Bob。

SignalServiceCipher类中:

英文:

After reviewing the source code of Signal Android, I think Alice is supposed to also send Bob the type (as plaintext) of the ciphertext message.

In the class SignalServiceCipher:

答案2

得分: 0

1 - Alice生成身份密钥对长期)、已签名的预密钥中期和临时预密钥并将这些密钥以Base64格式保存到存储中

例如

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

2 - 发送

- 将预密钥ID和公钥以序列化格式发送至服务器
- 已签名的预密钥ID已签名的预密钥公钥已签名的预密钥记录签名
- 身份密钥对的公钥
- 注册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;

    // 会话
    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(库的作者正在使用信号协议的封装库,您可以将封装库更改为信号协议)
英文:

1 - Alice generate identityKeyPair(Long Term), signedPreKey(Medium Term) & Ephemeral PreKeys & save those keys into storage in base64.
e.g

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

2 - Send

  • List of PreKey Id & Public key to server in Serialized format
  • Signed PreKey Id, signedPreKeyPublicKey, signedPreKeyRecordSignature
  • Public Key of IdentityKeyPair
  • Registration Id

For Encryption and Decryption you first have to make to encrypted session

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);
}

Encryption & Decryption

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);
}

You can also look other source code which are available on github
https://github.com/lvijay/DemoSignal

https://github.com/signalapp/libsignal-protocol-java/pull/21/commits/3496ed996359f6d3d8ee52dcecb8f8b0d45b3cbc (The Library author is using is wrapper of signal protocol you can change wrapper library to signal protocol)

huangapple
  • 本文由 发表于 2020年8月25日 22:30:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63581119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定