libsignal加密协议
github:https://github.com/signalapp/libsignal-protocol-java
一、基础概念
PreKey
协议使用了称为“ PreKeys”的概念。PreKey是存储在服务器中的ECPublicKey和关联的唯一ID(如上图的结构)。PreKeys也可以被签名。
在安装时,客户端会生成单个已签名的PreKey以及大量未签名的PreKey,并将它们全部传输到服务器。
public class PreKeyEntity {
@JsonProperty
private int keyId;
@JsonProperty
@JsonSerialize(using = ECPublicKeySerializer.class)
@JsonDeserialize(using = ECPublicKeyDeserializer.class)
private ECPublicKey publicKey;
public PreKeyEntity() {}
public PreKeyEntity(int keyId, ECPublicKey publicKey) {
this.keyId = keyId;
this.publicKey = publicKey;
}
public int getKeyId() {
return keyId;
}
public ECPublicKey getPublicKey() {
return publicKey;
}
private static class ECPublicKeySerializer extends JsonSerializer<ECPublicKey> {
@Override
public void serialize(ECPublicKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize()));
}
}
private static class ECPublicKeyDeserializer extends JsonDeserializer<ECPublicKey> {
@Override
public ECPublicKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
return Curve.decodePoint(Base64.decodeWithoutPadding(p.getValueAsString()), 0);
} catch (InvalidKeyException e) {
throw new IOException(e);
}
}
}
}
Sessions
协议是面向会话的。客户端建立一个“会话”,然后将其用于所有后续的加密/解密操作。建立会话后,无需拆除会话。
通过以下三种方式的其中一种可以建立会话:
- PreKeyBundles。希望向收件人发送消息的客户端可以通过从服务器检索该收件人的PreKeyBundle来建立会话。
- PreKeySignalMessages。客户端可以从收件人接收PreKeySignalMessage消息并使用它来建立会话。
- KeyExchangeMessages。两个客户端可以交换KeyExchange消息来建立会话。
/**
* A class that contains a remote PreKey and collection
* of associated items.
*
* @author Moxie Marlinspike
*/
public class PreKeyBundle {
private int registrationId;
private int deviceId;
private int preKeyId;
private ECPublicKey preKeyPublic;
private int signedPreKeyId;
private ECPublicKey signedPreKeyPublic;
private byte[] signedPreKeySignature;
private IdentityKey identityKey;
public PreKeyBundle(int registrationId, int deviceId, int preKeyId, ECPublicKey preKeyPublic,
int signedPreKeyId, ECPublicKey signedPreKeyPublic, byte[] signedPreKeySignature,
IdentityKey identityKey)
{
this.registrationId = registrationId;
this.deviceId = deviceId;
this.preKeyId = preKeyId;
this.preKeyPublic = preKeyPublic;
this.signedPreKeyId = signedPreKeyId;
this.signedPreKeyPublic = signedPreKeyPublic;
this.signedPreKeySignature = signedPreKeySignature;
this.identityKey = identityKey;
}
/**
* @return the device ID this PreKey belongs to.
*/
public int getDeviceId() {
return deviceId;
}
/**
* @return the unique key ID for this PreKey.
*/
public int getPreKeyId() {
return preKeyId;
}
/**
* @return the public key for this PreKey.
*/
public ECPublicKey getPreKey() {
return preKeyPublic;
}
/**
* @return the unique key ID for this signed prekey.
*/
public int getSignedPreKeyId() {
return signedPreKeyId;
}
/**
* @return the signed prekey for this PreKeyBundle.
*/
public ECPublicKey getSignedPreKey() {
return signedPreKeyPublic;
}
/**
* @return the signature over the signed prekey.
*/
public byte[] getSignedPreKeySignature() {
return signedPreKeySignature;
}
/**
* @return the {@link org.whispersystems.libsignal.IdentityKey} of this PreKeys owner.
*/
public IdentityKey getIdentityKey() {
return identityKey;
}
/**
* @return the registration ID associated with this PreKey.
*/
public int getRegistrationId() {
return registrationId;
}
}
State
建立的会话封装了两个客户端之间的许多状态。该状态保存在持久记录中,在会话的整个生命周期中都需要保留这些记录。
状态保存在以下位置:
- 身份状态。客户端将需要维护自己的身份密钥对,以及从其他客户端收到的身份密钥的状态。
- PreKey的状态。客户将需要维护其生成的PreKey的状态。
- 已签名的PreKey状态。客户将需要维护其已签名的PreKey的状态。
- 会话状态。客户将需要保持他们已建立的会话的状态。
二、数据记录
identities:终端的身份凭证
prekeys:随机加密密钥对
signed_prekeys:已签名的密钥对
sessions:会话记录
三、密钥交互过程
1、注册时记录生产终端身份,已签名对密钥对,然后上报给服务器
2、登录时批量生产加密密钥
3、消息发送时,获取对方的加密密钥,加密发送对文本
4、消息接收时,使用本地的密钥,解密接收到对文本。
四、加密例子
原始文本:
<message type="text" id="88AB4E8F976E6FEEF4B715C829BD5289" t="1585733956" from="923127077123@s.whatsapp.net" notify="Hassan">
<body>
【8】5572206e616d653f
</body>
</message>
已加密对文本:
<message type="text" id="28F31BE78B2F4EFC931C0F963FB3C305" to="6285268065063@s.whatsapp.net">
<enc type="msg" v="2">
【162】330a210536c05d2b0e37ae0c7e7ad9f6999491fadb361f724ace8a97c7c46044bb931954100018002270c043e1d7ccd2dde22f6fe5157990bd28c6713eb57bc54de89356b7f2b23f3b6a326e52afd40f579a6e25b2cedb16aacfe62fba325ae3340d4b54284989b7a42169058e0aa0991c4454b71fdeb22cb81c56695f6a1260deb554ebc1c80c805f261c5264326916326f87f90859086a90e863d71ef0f9b63963
</enc>
</message>
更多相关内容可参看:
https://github.com/signalapp/libsignal-protocol-java
whatsapp协议简单分析之-端对端加密
Whatsapp传输协议调研
WhatsApp 分析
【翻译】WhatsApp 加密概述(技术白皮书)