无需subprocess库,实现ssh-keygen签名OpenSSH用户证书的Python方案
无需subprocess生成OpenSSH用户证书的方法
要实现和以下ssh-keygen命令等价的功能:
ssh-keygen -s user_ca -I ID_USER -n user1,user2 -V+1d user-key.pub
且不依赖subprocess库,可以借助Python的cryptography库直接处理密钥和证书结构,最终生成格式为ssh-rsa-cert-v01@openssh.com AAAAHHNza ... user@hostname的用户证书。
实现步骤及代码
安装依赖
先确保安装cryptography库:pip install cryptography核心代码
from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.backends import default_backend import time import base64 import struct def generate_user_cert(ca_priv_key_path, user_pub_key_path, key_id, principals, valid_days=1): # 加载CA私钥(对应ssh-keygen的-s user_ca) with open(ca_priv_key_path, "rb") as f: ca_priv_key = serialization.load_ssh_private_key( f.read(), password=None, backend=default_backend() ) # 加载用户公钥(对应user-key.pub) with open(user_pub_key_path, "rb") as f: user_pub_key = serialization.load_ssh_public_key( f.read(), backend=default_backend() ) # 构造证书有效期(对应-V+1d) current_time = int(time.time()) valid_after = current_time valid_before = current_time + valid_days * 86400 # 证书基础字段配置 cert_type = 1 # 1表示用户证书 serial = 12345 # 自定义唯一序列号 key_id_bytes = key_id.encode() principals_bytes = b"\x00".join(p.encode() for p in principals) extensions = b"" reserved = b"" comment = b"user@hostname" # 自定义证书注释 # 序列化用户公钥核心内容 user_pub_bytes = user_pub_key.public_bytes( encoding=serialization.Encoding.OpenSSH, format=serialization.PublicFormat.OpenSSH ) user_pub_core = base64.b64decode(user_pub_bytes.split(b" ")[1]) # 组装待签名的证书数据 cert_data = struct.pack(">I", cert_type) + \ struct.pack(">Q", serial) + \ struct.pack(">I", valid_after) + \ struct.pack(">Q", valid_before) + \ struct.pack(">I", len(key_id_bytes)) + key_id_bytes + \ struct.pack(">I", len(principals_bytes)) + principals_bytes + \ struct.pack(">I", len(extensions)) + extensions + \ struct.pack(">I", len(reserved)) + reserved + \ user_pub_core # CA私钥签名证书数据 signature = ca_priv_key.sign( cert_data, padding.PKCS1v15(), hashes.SHA256() ) # 组装完整的OpenSSH证书字符串 full_cert = b"ssh-rsa-cert-v01@openssh.com " + \ base64.b64encode(struct.pack(">I", len(cert_data)) + cert_data + struct.pack(">I", len(signature)) + signature) + \ b" " + comment return full_cert.decode() # 调用示例 if __name__ == "__main__": cert = generate_user_cert( ca_priv_key_path="user_ca", user_pub_key_path="user-key.pub", key_id="ID_USER", principals=["user1", "user2"], valid_days=1 ) print(cert)
代码说明
- 直接通过
cryptography的序列化API解析SSH格式的CA私钥和用户公钥,无需调用外部命令 - 证书字段完全对应原
ssh-keygen命令参数:key_id对应-I ID_USERprincipals对应-n user1,user2valid_days=1对应-V+1d
- 最终生成的证书字符串格式与
ssh-keygen输出完全一致
内容的提问来源于stack exchange,提问作者Jarosław Wieczorek
相关产品推荐
相关产品推荐

