Signal 協議 的 java接口庫

Signal 協議 的 java接口庫

概述
Signal協議是一種基於雙棘輪技術的前向保密協議。可應用於在同步和異步這兩種消息傳遞環境。

接口庫開源地址:https://github.com/signalapp/libsignal-protocol-java

預共享密鑰
Signal協議中應用了預共享密鑰(PreKey)概念。預共享密鑰包括一個公鑰和一個對應的惟一ID。

準備數據時,客戶端生成一個已簽名的預共享密鑰,以及一組未簽名的預共享密鑰的列表,並將它們全部傳輸到服務器上存儲,以供查詢。預共享密鑰也可以簽名。

會話
Signal協議是面向會話的。客戶端建立一個“會話”,用於後續的加密/解密操作。一旦建立了一個會話,通信過程中就不必再拆掉它。

會話可以通過以下三種方式建立:

基於預共享密鑰包(PreKeyBundles):預向某收件人發送消息的客戶端,可以通過從服務器上檢索該收件人的預共享密鑰包來建立會話。
預共享密鑰消息(PreKeySignalMessages):客戶端可以從收件人接收預共享密鑰消息並使用它建立會話。
密鑰交換消息(KeyExchangeMessages):兩個客戶端可以交換密鑰交換消息以建立會話。
狀態
已建立的會話封裝了兩個客戶端之間的許多狀態。這些狀態與會話同生命週期,保存在記錄中:

身份信息狀態:客戶端需要維護自己的身份密鑰對以及從其他客戶端接收的身份密鑰的狀態;
預共享密鑰狀態:客戶端需要維護生成的預共享密鑰的狀態;
已簽名預共享密鑰狀態:客戶端需要維護其已簽名預密鑰的狀態;
會話狀態:客戶端需要維護其已建立會話的狀態。
接口庫使用
準備數據
準備數據時,libsignal客戶端需要生成其身份認證密鑰、註冊id和預共享密鑰。以下代碼是以bob端爲例:

// 構建bob的數據內容
int bobId = 0x10203040;
// bob 的地址
SignalProtocolAddress bobAddress = new SignalProtocolAddress("BobName", bobId);
// IKP-B,身份認證密鑰對
IdentityKeyPair bobIdentityKeyPair = KeyHelper.generateIdentityKeyPair();
// 註冊編號,
int bobRegistrationId = KeyHelper.generateRegistrationId(false);
// 預共享密鑰
List bobPreKeys = KeyHelper.generatePreKeys(bobId, 100);
// 已簽名預共享密鑰SPK-B ID
int bobSignedPreKeyId = 1;
// 已簽名預共享密鑰
SignedPreKeyRecord bobSignedPreKey = KeyHelper.generateSignedPreKey(bobIdentityKeyPair, bobSignedPreKeyId);
// 獲取到的,bob的某一個預共享的密鑰包
// 一次性預共享密鑰OPK-B ID
int bobPreKeyId = 1;
// 一次性預共享密鑰OPK-B公鑰
ECPublicKey bobPreKeyPublic = bobPreKeys.get(bobPreKeyId).getKeyPair().getPublicKey();
// 已簽名預共享密鑰SPK-B公鑰
ECPublicKey bobSignedPreKeyPublic = bobSignedPreKey.getKeyPair().getPublicKey();
// 預共享密鑰簽名Sig(IK-B,Encode(SPK-B))
byte[] bobSignedPreKeySignature = Curve.calculateSignature(bobIdentityKeyPair.getPrivateKey(),
bobSignedPreKeyPublic.serialize());
// 身份認證公鑰IK-B
IdentityKey bobIdentityKey = bobIdentityKeyPair.getPublicKey();
// 組建預共享密鑰包
PreKeyBundle bobProKeyBundle = new PreKeyBundle(bobRegistrationId, bobRegistrationId, bobPreKeyId,bobPreKeyPublic, bobSignedPreKeyId, bobSignedPreKeyPublic, bobSignedPreKeySignature, bobIdentityKey);
//發送預共享密鑰包到服務器...
建立會話
應用接口庫的客戶端需要實現四個接口:IdentityKeyStore、PreKeyStore、SignedPreKeyStore和SessionStore。它們將用於管理身份認證密鑰、預共享密鑰、已簽名預共享密鑰和會話狀態的加載和存儲。

通過這些構建會話就相當簡單:

// IKP-A,身份認證密鑰對
IdentityKeyPair aliceIdentityKeyPair = KeyHelper.generateIdentityKeyPair();
// 註冊編號,
int aliceRegistrationId = KeyHelper.generateRegistrationId(false);
// 會話存儲
SessionStore aliceSessionStore = new InMemorySessionStore();
// 預共享存儲
PreKeyStore alicePreKeyStore = new InMemoryPreKeyStore();
// 已簽名預共享密鑰
SignedPreKeyStore aliceSignedPreKeyStore = new InMemorySignedPreKeyStore();
// 身份認證密鑰對
IdentityKeyStore aliceIdentityStore = new InMemoryIdentityKeyStore(aliceIdentityKeyPair, aliceRegistrationId);
// 創建會話處理器
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore,
aliceSignedPreKeyStore, aliceIdentityStore, bobAddress);
// 從服務器獲取bob的預共享密鑰包,初始化會話
aliceSessionBuilder.process(bobProKeyBundle);
//創建消息加解密器
SessionCipher sessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore,aliceIdentityStore, bobAddress);
// 組建初始消息
CiphertextMessage message = sessionCipher.encrypt("Hello world!".getBytes("UTF-8"));
//將消息內容發送到bob...
bob端收到後可通過PreKeySignalMessage的方式初始化會話。

//SessionBuilder以及各種store的創建,類似alice端
bobSessionBuilder.process(sessionRecord ,(PreKeySignalMessage) message);
原文地址https://my.oschina.net/piorcn/blog/4270661

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章