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

相关文章
|
1月前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
123 3
|
3天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
26 6
|
20天前
|
Java API
Java中内置的函数式接口
Java中内置的函数式接口
20 2
|
24天前
|
Java
在Java中如何实现接口?
实现接口是 Java 编程中的一个重要环节,它有助于提高代码的规范性、可扩展性和复用性。通过正确地实现接口,可以使代码更加灵活、易于维护和扩展。
46 3
|
28天前
|
Java BI API
Java Excel报表生成:JXLS库的高效应用
在Java应用开发中,经常需要将数据导出到Excel文件中,以便于数据的分析和共享。JXLS库是一个强大的工具,它基于Apache POI,提供了一种简单而高效的方式来生成Excel报表。本文将详细介绍JXLS库的使用方法和技巧,帮助你快速掌握Java中的Excel导出功能。
61 6
|
23天前
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
66 1
|
23天前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
46 1
|
23天前
|
Java
在Java中实现接口的具体代码示例
可以根据具体的需求,创建更多的类来实现这个接口,以满足不同形状的计算需求。希望这个示例对你理解在 Java 中如何实现接口有所帮助。
37 1
|
29天前
|
Java Android开发
Eclipse 创建 Java 接口
Eclipse 创建 Java 接口
27 1
|
1月前
|
Java
java线程接口
Thread的构造方法创建对象的时候传入了Runnable接口的对象 ,Runnable接口对象重写run方法相当于指定线程任务,创建线程的时候绑定了该线程对象要干的任务。 Runnable的对象称之为:线程任务对象 不是线程对象 必须要交给Thread线程对象。 通过Thread的构造方法, 就可以把任务对象Runnable,绑定到Thread对象中, 将来执行start方法,就会自动执行Runable实现类对象中的run里面的内容。
39 1