物联网设备身份认证与安全通信
本文探讨了AIDC自动气象站系统中的物联网设备安全通信方案。针对广泛分布的物联网气象设备,系统采用X.509证书进行强身份认证,构建双向TLS加密通信通道,并实现动态令牌机制。文章分析了物联网设备面临的安全威胁(物理篡改、中间人攻击、DDoS等),提出了包含证书层次结构、设备注册流程、双向认证机制的安全架构,通过mermaid图表展示了认证流程和证书管理方案。系统实现了设备注册、证书签发、TLS握
·
物联网设备身份认证与安全通信
作者: zry
标签: 物联网, 安全, 身份认证, TLS, AIDC, 加密通信
目录
引言
在AIDC自动气象站数据收集系统中,成千上万的物联网气象设备分布在广阔的地域,通过公共网络与数据中心通信。这些设备采集的温度、湿度、气压等敏感气象数据需要严格保护,防止被窃听、篡改或伪造。
本文将深入探讨AIDC系统中采用的物联网设备身份认证与安全通信方案,包括基于X.509证书的强身份认证、双向TLS加密通信、动态令牌机制等核心技术。
物联网安全挑战
AIDC系统面临的安全威胁
安全需求分析
| 安全属性 | 威胁场景 | 防护手段 |
|---|---|---|
| 机密性 | 数据在传输中被窃听 | TLS 1.3加密 |
| 完整性 | 数据被篡改 | HMAC签名验证 |
| 身份认证 | 伪造设备接入 | X.509证书认证 |
| 不可否认性 | 设备否认发送数据 | 数字签名 |
| 可用性 | DDoS攻击 | 速率限制、熔断 |
身份认证架构设计
整体架构
认证流程时序图
设备注册与证书管理
证书层次结构
设备注册实现
// device_registration.hpp
#pragma once
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <string>
#include <vector>
#include <memory>
#include <chrono>
namespace aidc::security {
// 前向声明
class CertificateAuthority;
// 设备注册信息
struct DeviceRegistrationInfo {
std::string device_id; // 设备唯一标识
std::string hardware_id; // 硬件序列号
std::string model; // 设备型号
std::string firmware_version; // 固件版本
std::string location; // 安装位置
std::chrono::system_clock::time_point registered_at;
std::chrono::system_clock::time_point expires_at;
};
// 证书签名请求
struct CertificateSigningRequest {
std::vector<uint8_t> der_data; // DER编码的CSR
std::string device_id;
std::string common_name;
// 从DER解析CSR信息
bool parse_from_der(const std::vector<uint8_t>& der);
// 验证CSR签名
bool verify_signature() const;
};
// 设备证书
class DeviceCertificate {
public:
explicit DeviceCertificate(X509* cert = nullptr);
~DeviceCertificate();
// 禁止拷贝,允许移动
DeviceCertificate(const DeviceCertificate&) = delete;
DeviceCertificate& operator=(const DeviceCertificate&) = delete;
DeviceCertificate(DeviceCertificate&& other) noexcept;
DeviceCertificate& operator=(DeviceCertificate&& other) noexcept;
// 序列化
std::vector<uint8_t> to_der() const;
std::string to_pem() const;
bool from_der(const std::vector<uint8_t>& der);
bool from_pem(const std::string& pem);
// 获取证书信息
std::string get_subject() const;
std::string get_issuer() const;
std::string get_serial_number() const;
std::chrono::system_clock::time_point get_not_before() const;
std::chrono::system_clock::time_point get_not_after() const;
// 验证证书
bool verify_signature(EVP_PKEY* issuer_key) const;
bool is_expired() const;
bool is_valid_now() const;
// 获取公钥
EVP_PKEY* get_public_key() const;
// 内部X509指针访问
X509* native_handle() const { return cert_; }
private:
X509* cert_;
};
// 设备注册管理器
class DeviceRegistrationManager {
public:
explicit DeviceRegistrationManager(
std::shared_ptr<CertificateAuthority> ca);
// 处理设备注册请求
struct RegistrationResult {
bool success;
std::string error_message;
DeviceCertificate certificate;
std::string issued_token;
};
RegistrationResult register_device(
const CertificateSigningRequest& csr,
const DeviceRegistrationInfo& info);
// 批量注册(用于预置设备)
std::vector<RegistrationResult> batch_register(
const std::vector<std::pair<CertificateSigningRequest,
DeviceRegistrationInfo>>& requests);
// 吊销设备证书
bool revoke_device(const std::string& device_id);
// 更新设备证书
RegistrationResult renew_certificate(
const std::string& device_id,
const CertificateSigningRequest& csr);
// 查询设备状态
struct DeviceStatus {
std::string device_id;
bool is_active;
bool is_revoked;
std::chrono::system_clock::time_point cert_expires;
std::chrono::system_clock::time_point last_seen;
};
std::optional<DeviceStatus> query_device_status(
const std::string& device_id) const;
private:
std::shared_ptr<CertificateAuthority> ca_;
// 设备注册存储
class DeviceRegistryImpl;
std::unique_ptr<DeviceRegistryImpl> registry_;
// 生成设备证书
DeviceCertificate issue_certificate(
const CertificateSigningRequest& csr,
const DeviceRegistrationInfo& info);
// 验证设备合法性
bool validate_device_identity(const DeviceRegistrationInfo& info) const;
};
} // namespace aidc::security
证书颁发机构实现
// certificate_authority.cpp
#include "certificate_authority.hpp"
#include <openssl/x509v3.h>
#include <openssl/rand.h>
#include <spdlog/spdlog.h>
#include <fstream>
namespace aidc::security {
// 生成序列号
static std::vector<uint8_t> generate_serial_number() {
std::vector<uint8_t> serial(20);
if (RAND_bytes(serial.data(), serial.size()) != 1) {
throw std::runtime_error("Failed to generate random serial number");
}
// 确保正数
serial[0] &= 0x7F;
return serial;
}
// 设置证书有效期
static void set_certificate_validity(X509* cert,
int days_valid,
std::chrono::system_clock::time_point not_before =
std::chrono::system_clock::now()) {
ASN1_TIME* not_before_asn1 = ASN1_TIME_new();
ASN1_TIME* not_after_asn1 = ASN1_TIME_new();
auto not_before_t = std::chrono::system_clock::to_time_t(not_before);
auto not_after = not_before + std::chrono::hours(24 * days_valid);
auto not_after_t = std::chrono::system_clock::to_time_t(not_after);
ASN1_TIME_set(not_before_asn1, not_before_t);
ASN1_TIME_set(not_after_asn1, not_after_t);
X509_set_notBefore(cert, not_before_asn1);
X509_set_notAfter(cert, not_after_asn1);
ASN1_TIME_free(not_before_asn1);
ASN1_TIME_free(not_after_asn1);
}
class CertificateAuthority::Impl {
public:
Impl(const std::string& ca_cert_path,
const std::string& ca_key_path,
const std::string& passphrase = "") {
// 加载CA证书
FILE* cert_file = fopen(ca_cert_path.c_str(), "r");
if (!cert_file) {
throw std::runtime_error("Failed to open CA certificate file");
}
ca_cert_.reset(PEM_read_X509(cert_file, nullptr, nullptr, nullptr));
fclose(cert_file);
if (!ca_cert_) {
throw std::runtime_error("Failed to load CA certificate");
}
// 加载CA私钥
FILE* key_file = fopen(ca_key_path.c_str(), "r");
if (!key_file) {
throw std::runtime_error("Failed to open CA key file");
}
auto password_cb = [](char* buf, int size, int rwflag, void* userdata) -> int {
const std::string* pass = static_cast<const std::string*>(userdata);
if (pass->empty()) return 0;
int len = std::min(size, static_cast<int>(pass->size()));
memcpy(buf, pass->data(), len);
return len;
};
ca_key_.reset(PEM_read_PrivateKey(key_file, nullptr,
password_cb,
const_cast<void*>(
static_cast<const void*>(&passphrase))));
fclose(key_file);
if (!ca_key_) {
throw std::runtime_error("Failed to load CA private key");
}
spdlog::info("CertificateAuthority initialized successfully");
}
DeviceCertificate issue_certificate(const CertificateSigningRequest& csr,
int validity_days = 365) {
// 解析CSR
const uint8_t* data = csr.der_data.data();
std::unique_ptr<X509_REQ, decltype(&X509_REQ_free)> req(
d2i_X509_REQ(nullptr, &data, csr.der_data.size()),
X509_REQ_free);
if (!req) {
throw std::runtime_error("Failed to parse CSR");
}
// 验证CSR签名
EVP_PKEY* req_pubkey = X509_REQ_get_pubkey(req.get());
if (X509_REQ_verify(req.get(), req_pubkey) != 1) {
EVP_PKEY_free(req_pubkey);
throw std::runtime_error("CSR signature verification failed");
}
// 创建新证书
X509* cert = X509_new();
if (!cert) {
EVP_PKEY_free(req_pubkey);
throw std::runtime_error("Failed to create certificate");
}
// 设置版本号(v3)
X509_set_version(cert, 2);
// 设置序列号
auto serial = generate_serial_number();
BIGNUM* serial_bn = BN_bin2bn(serial.data(), serial.size(), nullptr);
ASN1_INTEGER* serial_asn1 = BN_to_ASN1_INTEGER(serial_bn, nullptr);
X509_set_serialNumber(cert, serial_asn1);
BN_free(serial_bn);
ASN1_INTEGER_free(serial_asn1);
// 设置签发者
X509_set_issuer_name(cert, X509_get_subject_name(ca_cert_.get()));
// 设置主体(使用CSR中的信息)
X509_set_subject_name(cert, X509_REQ_get_subject_name(req.get()));
// 设置有效期
set_certificate_validity(cert, validity_days);
// 设置公钥
X509_set_pubkey(cert, req_pubkey);
EVP_PKEY_free(req_pubkey);
// 添加扩展
add_extensions(cert, csr);
// 签名证书
if (X509_sign(cert, ca_key_.get(), EVP_sha256()) <= 0) {
X509_free(cert);
throw std::runtime_error("Failed to sign certificate");
}
spdlog::info("Issued certificate for device: {}", csr.device_id);
return DeviceCertificate(cert);
}
bool verify_certificate(const DeviceCertificate& cert) const {
// 验证证书签名
if (!cert.verify_signature(ca_key_.get())) {
spdlog::warn("Certificate signature verification failed");
return false;
}
// 检查有效期
if (cert.is_expired()) {
spdlog::warn("Certificate has expired");
return false;
}
// 检查吊销列表
std::string serial = cert.get_serial_number();
if (is_revoked(serial)) {
spdlog::warn("Certificate is revoked: {}", serial);
return false;
}
return true;
}
void revoke_certificate(const std::string& serial_number) {
std::lock_guard<std::mutex> lock(revoked_certs_mutex_);
revoked_certs_.insert(serial_number);
spdlog::info("Certificate revoked: {}", serial_number);
// 持久化吊销列表
persist_crl();
}
private:
void add_extensions(X509* cert, const CertificateSigningRequest& csr) {
X509V3_CTX ctx;
X509V3_set_ctx(&ctx, ca_cert_.get(), cert, nullptr, nullptr, 0);
// 基本约束
add_extension(cert, &ctx, NID_basic_constraints, "CA:FALSE");
// 密钥用途
add_extension(cert, &ctx, NID_key_usage,
"digitalSignature,keyEncipherment");
// 扩展密钥用途
add_extension(cert, &ctx, NID_ext_key_usage,
"clientAuth");
// 主体密钥标识符
add_extension(cert, &ctx, NID_subject_key_identifier, "hash");
// 授权密钥标识符
add_extension(cert, &ctx, NID_authority_key_identifier,
"keyid:always,issuer:always");
// 自定义扩展:设备ID
std::string device_id_ext = "DeviceID:" + csr.device_id;
// 使用自定义OID或注释字段存储
}
void add_extension(X509* cert, X509V3_CTX* ctx, int nid,
const char* value) {
X509_EXTENSION* ext = X509V3_EXT_conf_nid(nullptr, ctx, nid,
const_cast<char*>(value));
if (ext) {
X509_add_ext(cert, ext, -1);
X509_EXTENSION_free(ext);
}
}
bool is_revoked(const std::string& serial) const {
std::lock_guard<std::mutex> lock(revoked_certs_mutex_);
return revoked_certs_.find(serial) != revoked_certs_.end();
}
void persist_crl() {
// 持久化吊销证书列表到文件或数据库
// 实现省略...
}
std::unique_ptr<X509, decltype(&X509_free)> ca_cert_{nullptr, X509_free};
std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> ca_key_{nullptr, EVP_PKEY_free};
mutable std::mutex revoked_certs_mutex_;
std::unordered_set<std::string> revoked_certs_;
};
CertificateAuthority::CertificateAuthority(
const std::string& ca_cert_path,
const std::string& ca_key_path,
const std::string& passphrase)
: impl_(std::make_unique<Impl>(ca_cert_path, ca_key_path, passphrase)) {}
CertificateAuthority::~CertificateAuthority() = default;
DeviceCertificate CertificateAuthority::issue_certificate(
const CertificateSigningRequest& csr,
int validity_days) {
return impl_->issue_certificate(csr, validity_days);
}
bool CertificateAuthority::verify_certificate(const DeviceCertificate& cert) const {
return impl_->verify_certificate(cert);
}
void CertificateAuthority::revoke_certificate(const std::string& serial_number) {
impl_->revoke_certificate(serial_number);
}
} // namespace aidc::security
双向TLS实现
TLS配置管理
// tls_context.hpp
#pragma once
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
#include <memory>
#include <functional>
namespace aidc::security {
// TLS版本
enum class TlsVersion {
TLS_1_2,
TLS_1_3,
AUTO
};
// TLS配置
struct TlsConfig {
TlsVersion min_version = TlsVersion::TLS_1_2;
std::string cert_chain_file; // 证书链文件
std::string private_key_file; // 私钥文件
std::string ca_cert_file; // CA证书文件(用于验证对方)
std::string cipher_list; // 加密套件列表
bool verify_peer = true; // 验证对方证书
bool fail_if_no_peer_cert = true; // 必须提供证书
int verify_depth = 4; // 证书链最大深度
std::chrono::seconds handshake_timeout{30};
};
// TLS上下文管理
class TlsContext {
public:
explicit TlsContext(const TlsConfig& config);
~TlsContext();
// 禁止拷贝
TlsContext(const TlsContext&) = delete;
TlsContext& operator=(const TlsContext&) = delete;
// 创建SSL对象
SSL* create_ssl();
// 获取底层上下文
SSL_CTX* native_handle() const { return ctx_; }
// 设置证书验证回调
using VerifyCallback = std::function<bool(X509_STORE_CTX*, void*)>;
void set_verify_callback(VerifyCallback callback, void* user_data);
// 加载证书吊销列表
bool load_crl(const std::string& crl_file);
// 启用OCSP Stapling
bool enable_ocsp_stapling();
private:
SSL_CTX* ctx_;
TlsConfig config_;
VerifyCallback verify_callback_;
void* verify_user_data_;
void configure_tls_version();
void configure_cipher_suites();
static int verify_callback_wrapper(int preverify_ok, X509_STORE_CTX* ctx);
};
// 安全连接
class SecureConnection {
public:
SecureConnection(SSL* ssl, int socket_fd);
~SecureConnection();
// 禁止拷贝,允许移动
SecureConnection(const SecureConnection&) = delete;
SecureConnection& operator=(const SecureConnection&) = delete;
SecureConnection(SecureConnection&& other) noexcept;
SecureConnection& operator=(SecureConnection&& other) noexcept;
// TLS握手
enum class HandshakeResult {
SUCCESS,
WANT_READ,
WANT_WRITE,
FAILED
};
HandshakeResult do_handshake();
bool complete_handshake_with_timeout(std::chrono::seconds timeout);
// 获取连接信息
std::string get_peer_cert_subject() const;
std::string get_cipher_name() const;
TlsVersion get_tls_version() const;
std::vector<uint8_t> get_peer_cert_der() const;
// 发送/接收数据
ssize_t send(const void* data, size_t len);
ssize_t receive(void* buffer, size_t len);
// 关闭连接
void shutdown();
// 检查连接状态
bool is_established() const;
int get_error(int ret_code) const;
private:
SSL* ssl_;
int socket_fd_;
bool established_;
};
} // namespace aidc::security
Connect模块TLS服务器实现
// connect_tls_server.cpp
#include "tls_context.hpp"
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <poll.h>
#include <spdlog/spdlog.h>
namespace aidc::connect {
class TlsDeviceServer {
public:
TlsDeviceServer(const security::TlsConfig& config,
std::shared_ptr<security::CertificateAuthority> ca)
: tls_ctx_(config)
, ca_(ca)
, running_(false) {}
bool start(uint16_t port) {
// 创建监听socket
listen_fd_ = socket(AF_INET6, SOCK_STREAM, 0);
if (listen_fd_ < 0) {
spdlog::error("Failed to create socket");
return false;
}
// 设置地址重用
int reuse = 1;
setsockopt(listen_fd_, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
// 绑定地址
sockaddr_in6 addr{};
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(port);
addr.sin6_addr = in6addr_any;
if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
spdlog::error("Failed to bind to port {}", port);
close(listen_fd_);
return false;
}
// 开始监听
if (listen(listen_fd_, 128) < 0) {
spdlog::error("Failed to listen on socket");
close(listen_fd_);
return false;
}
// 设置非阻塞
int flags = fcntl(listen_fd_, F_GETFL, 0);
fcntl(listen_fd_, F_SETFL, flags | O_NONBLOCK);
running_ = true;
accept_thread_ = std::thread(&TlsDeviceServer::accept_loop, this);
spdlog::info("TLS device server started on port {}", port);
return true;
}
void stop() {
running_ = false;
close(listen_fd_);
if (accept_thread_.joinable()) {
accept_thread_.join();
}
}
// 设置设备认证回调
using AuthCallback = std::function<bool(const std::string& device_id,
const std::vector<uint8_t>& cert_der)>;
void set_auth_callback(AuthCallback callback) {
auth_callback_ = callback;
}
private:
void accept_loop() {
while (running_) {
sockaddr_in6 client_addr{};
socklen_t addr_len = sizeof(client_addr);
int client_fd = accept(listen_fd_,
reinterpret_cast<sockaddr*>(&client_addr),
&addr_len);
if (client_fd < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
spdlog::error("Accept failed: {}", strerror(errno));
continue;
}
// 创建新线程处理连接
std::thread(&TlsDeviceServer::handle_connection, this, client_fd).detach();
}
}
void handle_connection(int client_fd) {
// 创建SSL对象
SSL* ssl = tls_ctx_.create_ssl();
if (!ssl) {
close(client_fd);
return;
}
// 设置文件描述符
SSL_set_fd(ssl, client_fd);
// 设置验证回调
SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
security::SecureConnection conn(ssl, client_fd);
// 完成握手
if (!conn.complete_handshake_with_timeout(std::chrono::seconds(30))) {
spdlog::warn("TLS handshake failed");
return;
}
// 获取并验证设备证书
auto cert_der = conn.get_peer_cert_der();
std::string device_id = extract_device_id(conn.get_peer_cert_subject());
spdlog::info("Device {} connected via TLS 1.3", device_id);
// 验证设备身份
if (auth_callback_ && !auth_callback_(device_id, cert_der)) {
spdlog::warn("Device {} authentication failed", device_id);
return;
}
// 进入数据传输循环
handle_device_communication(conn, device_id);
}
void handle_device_communication(security::SecureConnection& conn,
const std::string& device_id) {
std::vector<uint8_t> buffer(4096);
while (running_) {
ssize_t received = conn.receive(buffer.data(), buffer.size());
if (received <= 0) {
int ssl_error = conn.get_error(static_cast<int>(received));
if (ssl_error == SSL_ERROR_WANT_READ ||
ssl_error == SSL_ERROR_WANT_WRITE) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
break;
}
// 处理接收到的数据
process_device_data(device_id,
std::span(buffer.data(), received));
}
spdlog::info("Device {} disconnected", device_id);
}
void process_device_data(const std::string& device_id,
std::span<const uint8_t> data) {
// 解析气象数据包
// 转发到ISOS模块处理
// 实现省略...
}
std::string extract_device_id(const std::string& subject) {
// 从证书主题提取设备ID
// 例如:/CN=Station-001/O=AIDC/...
size_t cn_pos = subject.find("/CN=");
if (cn_pos != std::string::npos) {
size_t end = subject.find('/', cn_pos + 4);
return subject.substr(cn_pos + 4, end - cn_pos - 4);
}
return "";
}
security::TlsContext tls_ctx_;
std::shared_ptr<security::CertificateAuthority> ca_;
std::atomic<bool> running_;
int listen_fd_;
std::thread accept_thread_;
AuthCallback auth_callback_;
};
} // namespace aidc::connect
令牌认证机制
JWT令牌实现
// jwt_token.hpp
#pragma once
#include <string>
#include <vector>
#include <chrono>
#include <unordered_map>
#include <optional>
namespace aidc::security {
// JWT令牌结构
class JwtToken {
public:
using Claims = std::unordered_map<std::string, std::string>;
// 创建令牌
static std::string create(const std::string& device_id,
const std::string& secret_key,
std::chrono::seconds validity,
const Claims& additional_claims = {});
// 验证令牌
struct ValidationResult {
bool valid;
std::string device_id;
std::chrono::system_clock::time_point expires_at;
Claims claims;
std::string error;
};
static ValidationResult validate(const std::string& token,
const std::string& secret_key);
// 刷新令牌
static std::string refresh(const std::string& token,
const std::string& secret_key,
std::chrono::seconds new_validity);
private:
static std::string base64_encode(const std::vector<uint8_t>& data);
static std::vector<uint8_t> base64_decode(const std::string& encoded);
static std::string sign(const std::string& header_payload,
const std::string& secret);
};
// 令牌管理器
class TokenManager {
public:
explicit TokenManager(std::string secret_key,
std::chrono::seconds default_validity =
std::chrono::hours(24));
// 为设备颁发令牌
std::string issue_token(const std::string& device_id,
const JwtToken::Claims& claims = {});
// 验证令牌
std::optional<JwtToken::ValidationResult> verify_token(
const std::string& token);
// 吊销令牌
void revoke_token(const std::string& token);
// 检查令牌是否被吊销
bool is_revoked(const std::string& token) const;
// 清理过期令牌
void cleanup_expired();
private:
std::string secret_key_;
std::chrono::seconds default_validity_;
mutable std::mutex revoked_mutex_;
std::unordered_set<std::string> revoked_tokens_;
};
} // namespace aidc::security
gRPC拦截器集成
// grpc_auth_interceptor.hpp
#pragma once
#include <grpcpp/grpcpp.h>
#include <grpcpp/server_context.h>
#include "jwt_token.hpp"
namespace aidc::grpc {
// 认证拦截器
class AuthInterceptor : public grpc::experimental::Interceptor {
public:
explicit AuthInterceptor(
grpc::experimental::ServerRpcInfo* info,
std::shared_ptr<security::TokenManager> token_manager);
void Intercept(grpc::experimental::InterceptorBatchMethods* methods) override;
private:
std::shared_ptr<security::TokenManager> token_manager_;
bool authenticate(grpc::ServerContext* context);
std::string extract_token(const std::string& auth_header);
};
// 拦截器工厂
class AuthInterceptorFactory
: public grpc::experimental::ServerInterceptorFactoryInterface {
public:
explicit AuthInterceptorFactory(
std::shared_ptr<security::TokenManager> token_manager)
: token_manager_(token_manager) {}
grpc::experimental::Interceptor* CreateServerInterceptor(
grpc::experimental::ServerRpcInfo* info) override {
return new AuthInterceptor(info, token_manager_);
}
private:
std::shared_ptr<security::TokenManager> token_manager_;
};
} // namespace aidc::grpc
密钥轮转与更新
密钥轮转策略
实现代码
// key_rotation.hpp
#pragma once
#include <string>
#include <vector>
#include <chrono>
#include <atomic>
namespace aidc::security {
// 密钥轮转管理器
class KeyRotationManager {
public:
struct KeyInfo {
std::string key_id;
std::string secret;
std::chrono::system_clock::time_point created_at;
std::chrono::system_clock::time_point expires_at;
bool is_active;
};
explicit KeyRotationManager(std::chrono::hours rotation_interval =
std::chrono::hours(720)); // 30天
// 启动轮转定时器
void start_rotation_timer();
void stop_rotation_timer();
// 手动触发轮转
void rotate_keys();
// 获取当前活跃密钥
KeyInfo get_current_key() const;
// 获取用于验证的所有密钥(包括即将过期的)
std::vector<KeyInfo> get_verification_keys() const;
// 使用指定密钥ID验证
bool verify_with_key(const std::string& token,
const std::string& key_id);
private:
void rotation_worker();
std::string generate_secure_key();
std::atomic<bool> running_;
std::chrono::hours rotation_interval_;
mutable std::shared_mutex keys_mutex_;
std::vector<KeyInfo> keys_;
std::thread rotation_thread_;
};
} // namespace aidc::security
AIDC系统中的实现
整体安全架构
设备端TLS客户端
// device_tls_client.hpp
#pragma once
#include <openssl/ssl.h>
#include <string>
#include <vector>
#include <functional>
namespace aidc::device {
class SecureDeviceClient {
public:
struct Config {
std::string server_address;
uint16_t server_port;
std::string device_cert_file;
std::string device_key_file;
std::string ca_cert_file;
std::chrono::seconds reconnect_interval{30};
std::chrono::seconds heartbeat_interval{60};
};
explicit SecureDeviceClient(const Config& config);
~SecureDeviceClient();
// 连接服务器
bool connect();
void disconnect();
// 发送气象数据
bool send_observation(const std::vector<uint8_t>& data);
// 发送心跳
bool send_heartbeat();
// 设置消息回调
using MessageCallback = std::function<void(const std::vector<uint8_t>&)>;
void set_message_callback(MessageCallback callback);
// 获取连接状态
bool is_connected() const;
std::chrono::system_clock::time_point last_heartbeat() const;
private:
bool perform_handshake();
void receive_loop();
bool verify_server_certificate(X509* cert);
Config config_;
SSL_CTX* ssl_ctx_;
SSL* ssl_;
int socket_fd_;
std::atomic<bool> connected_;
std::atomic<bool> should_stop_;
std::thread receive_thread_;
std::thread heartbeat_thread_;
MessageCallback message_callback_;
};
} // namespace aidc::device
最佳实践
1. 证书管理清单
// 证书检查清单
class CertificateChecklist {
public:
static bool validate_production_readiness(const DeviceCertificate& cert) {
// 检查1: 密钥长度
if (!has_sufficient_key_size(cert)) {
spdlog::error("Certificate key size too small");
return false;
}
// 检查2: 签名算法
if (!uses_strong_signature(cert)) {
spdlog::error("Weak signature algorithm");
return false;
}
// 检查3: 有效期
if (get_validity_days(cert) > 365) {
spdlog::warn("Certificate validity too long");
}
// 检查4: 扩展字段
if (!has_required_extensions(cert)) {
spdlog::error("Missing required extensions");
return false;
}
return true;
}
private:
static bool has_sufficient_key_size(const DeviceCertificate& cert);
static bool uses_strong_signature(const DeviceCertificate& cert);
static int get_validity_days(const DeviceCertificate& cert);
static bool has_required_extensions(const DeviceCertificate& cert);
};
2. 安全编码实践
// 安全编码检查点
namespace security_best_practices {
// 1. 永不硬编码密钥
// 错误:
// const char* SECRET_KEY = "hardcoded_secret";
// 正确:
// 从环境变量或安全存储读取
std::string load_secret_from_env() {
const char* secret = std::getenv("AIDC_JWT_SECRET");
if (!secret) {
throw std::runtime_error("JWT secret not configured");
}
return std::string(secret);
}
// 2. 使用安全随机数生成器
std::vector<uint8_t> generate_secure_random(size_t length) {
std::vector<uint8_t> buffer(length);
if (RAND_bytes(buffer.data(), length) != 1) {
throw std::runtime_error("Failed to generate secure random");
}
return buffer;
}
// 3. 常量时间比较(防时序攻击)
bool constant_time_compare(const std::string& a, const std::string& b) {
if (a.size() != b.size()) return false;
volatile unsigned char result = 0;
for (size_t i = 0; i < a.size(); ++i) {
result |= a[i] ^ b[i];
}
return result == 0;
}
// 4. 安全的内存清零
void secure_clear(void* ptr, size_t len) {
OPENSSL_cleanse(ptr, len);
}
template<typename T>
void secure_clear(T& obj) {
secure_clear(&obj, sizeof(T));
}
} // namespace security_best_practices
3. 监控与审计
// 安全事件审计
class SecurityAuditor {
public:
enum class EventType {
DEVICE_AUTHENTICATED,
DEVICE_AUTH_FAILED,
CERTIFICATE_EXPIRED,
CERTIFICATE_REVOKED,
SUSPICIOUS_ACTIVITY,
TOKEN_REFRESHED,
TOKEN_REVOKED
};
void log_event(EventType type,
const std::string& device_id,
const std::string& details);
// 异常检测
void detect_anomalies();
private:
struct SecurityEvent {
EventType type;
std::string device_id;
std::string details;
std::chrono::system_clock::time_point timestamp;
};
std::vector<SecurityEvent> events_;
mutable std::mutex events_mutex_;
};
总结
本文详细介绍了AIDC自动气象站数据收集系统中的物联网设备身份认证与安全通信方案。通过实施以下安全措施,我们构建了一个可靠的安全体系:
- X.509证书体系:基于PKI的强身份认证,确保设备身份可信
- 双向TLS 1.3:提供加密传输和双向身份验证
- JWT令牌机制:无状态的会话管理,支持细粒度访问控制
- 密钥轮转策略:定期更新密钥,降低密钥泄露风险
- 安全审计:完整的日志记录和异常检测
安全是一项持续的工作,建议定期进行安全评估和渗透测试,确保系统始终符合最新的安全标准。
https://github.com/0voice
更多推荐

所有评论(0)