概述
这是一个前向安全协议,适用于同步和异步消息环境。详情请参见 Java 库。
构建 libsignal-protocol-c
开发主机设置
构建依赖项
- CMake 2.8.4 或更高版本
- 检查 *1
- OpenSSL *1 1.0 或更高版本
- 在 MacOS X 上,使用 Common Crypto 代替 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.org/Wiki/CMake:Eclipse_UNIX_Tutorial
建议遵循更手动的方式来操作,即“选项2”,因为内置在CMake中的Eclipse项目生成器通常过时,并且可能导致非常不灵活甚至有时会出错的配置。
协议缓冲编译器
此项目使用基于协议缓冲的序列化代码。由于官方库不支持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库能够分配和返回的每个自定义数据类型,都提供了一个释放这种数据类型实例的方法。
更基本的、更高层次的数据类型提供了特定类型的释放或销毁函数。这些类型包括 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协议授权:http://www.gnu.org/licenses/gpl-3.0.html
将程序提交至Apple App Store的附加权限:前提是你遵守GPLv3的条款并满足其他要求(包括但不限于根据GPLv3第6节的规定提供相应的源代码),Open Whisper Systems还授予你在Mozilla Public License版本2.0协议下(https://www.mozilla.org/en-US/MPL/2.0/)通过Apple App Store传输Program的非源码可执行版本的权限,仅限于适用于每项受覆盖作品的仅执行版本。