概述
这是一种适用于同步和异步消息环境的前向密钥协商协议。有关详细信息,请参阅 Java 库。
构建 libsignal-protocol-c
开发主机设置
构建依赖项
- CMake 2.8.4 或更高版本
- 检查 *1
- OpenSSL *1 1.0 或更高版本
- 在 MacOS X 上,使用 通用加密 代替 OpenSSL
- LCOV *2
大多数这些依赖项仅适用于单元测试套件和库本身的开发生命周期。在实际应用集成时,您不需要 CMake 之外的任何内容。或者,您可以使用您选择的构建系统进行代码集成。标记为 *1 的项目需要用于测试,标记为 *2 的项目需要用于代码覆盖率。
设置新的源树
$ cd /path/to/libsignal-protocol-c
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug ..
$ make
运行单元测试
$ cd /path/to/libsignal-protocol-c/build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=1 ..
$ cd tests
$ make
$ cd ..
$ ctest
生成代码覆盖率报告
$ cd /path/to/libsignal-protocol-c/build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=1 -DCOVERAGE=1 ..
$ make coverage
生成的代码覆盖率报告可以在以下位置找到: /path/to/libsignal-protocol-c/build/coverage
Eclipse项目设置
CMake提供了有关Eclipse项目设置的教程: https://cmake.com.cn/Wiki/CMake:Eclipse_UNIX_Tutorial
建议遵循更手动的方式“选项2”,因为CMake内置的Eclipse项目生成器往往过时,并可能导致非常尴尬且偶尔出错的配置。
Protocol Buffers编译器
此项目使用基于Protocol Buffers的序列化代码。由于官方库不支持C,所以使用protobuf-c生成器。为了方便,生成的代码及其依赖已包含在源树中。可以在“protobuf/”子目录中安装两个提到的包,并运行“make”来随时重新生成代码。
目标平台
从以下源中包含了 CMake 工具链文件
使用 libsignal-protocol-c
库初始化
在使用库之前,libsignal-protocol-c 客户端需要初始化一个全局上下文。这个全局上下文用于提供跨整个库使用的函数的具体实现回调。请参考“signal_protocol.h”以获取这些函数的详细文档,并参考单元测试以查看示例实现。
signal_context *global_context;
signal_context_create(&global_context, user_data);
signal_context_set_crypto_provider(global_context, &provider);
signal_context_set_locking_functions(global_context, lock_function, unlock_function);
客户端安装时间
在安装时,libsignal-protocol-c 客户端需要生成其身份密钥、注册 ID 和预密钥。
ratchet_identity_key_pair *identity_key_pair;
uint32_t registration_id;
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
session_signed_pre_key *signed_pre_key;
signal_protocol_key_helper_generate_identity_key_pair(&identity_key_pair, global_context);
signal_protocol_key_helper_generate_registration_id(®istration_id, 0, global_context);
signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, global_context);
signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, identity_key_pair, 5, timestamp, global_context);
/* Store identity_key_pair somewhere durable and safe. */
/* Store registration_id somewhere durable and safe. */
/* Store pre keys in the pre key store. */
/* Store signed pre key in the signed pre key store. */
上面的示例为了清晰起见进行了简化。所有这些函数在失败时都会返回错误,并在实际使用中应该检查这些错误。
还应该根据需要使用上述类型的迭代和序列化方法。
建立会话
libsignal-protocol-c 客户端需要实现四个数据存储回调接口:signal_protocol_identity_key_store
、signal_protocol_pre_key_store
、signal_protocol_signed_pre_key_store
、和 signal_protocol_session_store
。这些接口将管理身份、预密钥、已签名预密钥和会话状态的数据加载和存储。
这些回调接口的设计目的是,实现者应将所有通过它们流动的数据视为不透明的二进制块。必要的数据引用将通过分离的函数参数提供给回调函数。如果客户端确实需要按库数据结构直接访问存储的数据,他们应使用在“signal_protocol.h”中声明的存取函数来处理这些数据存储。
实现这些数据存储的回调后,构建会话相对直接
/* Create the data store context, and add all the callbacks to it */
signal_protocol_store_context *store_context;
signal_protocol_store_context_create(&store_context, context);
signal_protocol_store_context_set_session_store(store_context, &session_store);
signal_protocol_store_context_set_pre_key_store(store_context, &pre_key_store);
signal_protocol_store_context_set_signed_pre_key_store(store_context, &signed_pre_key_store);
signal_protocol_store_context_set_identity_key_store(store_context, &identity_key_store);
/* Instantiate a session_builder for a recipient address. */
signal_protocol_address address = {
"+14159998888", 12, 1
};
session_builder *builder;
session_builder_create(&builder, store_context, &address, global_context);
/* Build a session with a pre key retrieved from the server. */
session_builder_process_pre_key_bundle(builder, retrieved_pre_key);
/* Create the session cipher and encrypt the message */
session_cipher *cipher;
session_cipher_create(&cipher, store_context, &address, global_context);
ciphertext_message *encrypted_message;
session_cipher_encrypt(cipher, message, message_len, &encrypted_message);
/* Get the serialized content and deliver it */
signal_buffer *serialized = ciphertext_message_get_serialized(encrypted_message);
deliver(signal_buffer_data(serialized), signal_buffer_len(serialized));
/* Cleanup */
SIGNAL_UNREF(encrypted_message);
session_cipher_free(cipher);
session_builder_free(builder);
signal_protocol_store_context_destroy(store_context);
上面的示例为了清晰起见进行了简化。所有这些函数在失败时都会返回错误,并在实际使用中应该检查这些错误。
内存管理说明
对于libsignal-protocol-c库可以分配和返回的每个自定义数据类型,都提供了一个与企业类型实例释放相对应的方法。
更基本和更高级的数据类型提供了类型特定的free或destroy函数。这些类型包括 signal_context
、signal_protocol_store_context
、signal_buffer
、signal_buffer_list
、signal_int_list
、signal_protocol_key_helper_pre_key_list_node
、session_builder
、session_cipher
、group_session_builder
、group_cipher
和 fingerprint_generator
。
大多数其他数据类型,包括所有内部类型,都使用引用计数机制。如果您要保留这些类型的引用,请使用 SIGNAL_REF(x)
宏来增加其计数。完成引用后,请使用 SIGNAL_UNREF(x)
来减少其计数。当计数达到0时,将调用该类型的析构函数。
法律事项
加密通知
本分发包含加密软件。您当前居住的国家可能对加密软件的进口、拥有、使用以及/或重新出口到其他国家有某些限制。在使用任何加密软件之前,请检查贵国有关加密软件进口、拥有或使用以及重新出口的法律、法规和政策,以查看这是否允许。更多信息请参见 http://www.wassenaar.org/。
美国商务部工业和安全局(BIS)已将该软件归类为出口商品控制编号(ECCN)5D002.C.1,这包括使用或执行不对称算法的加密功能的信息安全软件。本分发的形式和方式使其符合许可证例外情况ENC技术软件不受限制(TSU)的出口资格(参见BIS出口管理行政规定第740.13节),适用于目标代码和源代码。
许可协议
版权所有 2015-2016 Open Whisper Systems
遵循GPLv3协议: https://gnu.ac.cn/licenses/gpl-3.0.html
针对提交到Apple App Store的额外许可:在您遵守GPLv3对每个受影响的工程的相应条款的前提下(包括但不限于根据GPLv3第6节将相应的源代码提供给学生),Open Whisper Systems还授予您通过Apple App Store仅传递程序的可执行版本的额外许可,作为每个适用受保护工程的可执行版本,依据Mozilla公共许可证第2.0版本(https://www.mozilla.org/en-US/MPL/2.0/ )。