You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java通过SSH密钥对字符串进行签名与验签

解决ssh-keygen生成的RSA私钥签名请求体的问题

我之前也踩过一模一样的坑!用ssh-keygen -t rsa生成的私钥虽然是PEM格式,但它属于PKCS#1标准的RSA私钥,和很多示例里常见的PKCS#8格式略有区别,不过主流加密库都能直接处理,不用额外转换格式。下面给你几个常用语言的实现示例:

Python 实现(用cryptography库)

首先确保安装了cryptography:

pip install cryptography

然后用这段代码读取私钥并签名:

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
import base64

# 读取ssh-keygen生成的私钥文件
with open("id_rsa", "rb") as key_file:
    private_key = serialization.load_pem_private_key(
        key_file.read(),
        password=None,  # 如果生成私钥时设置了密码,这里传入密码的bytes,比如b"your-password"
        backend=default_backend()
    )

# 待签名的请求体(注意要和API要求的编码一致,通常是UTF-8)
request_body = b"your-request-body-content"
# 执行签名,这里的哈希算法和填充方式要和第三方API要求完全匹配
signature = private_key.sign(
    request_body,
    padding.PKCS1v15(),
    hashes.SHA256()
)

# 把签名转成Base64字符串(大多数API要求这种格式传递签名)
signature_base64 = base64.b64encode(signature).decode("utf-8")
print(f"生成的签名:{signature_base64}")

Java 实现(用BouncyCastle)

Java原生JDK默认只支持PKCS#8格式的私钥,所以我们需要借助BouncyCastle库来直接解析PKCS#1格式的私钥:

  1. 先在pom.xml(Maven)里添加依赖:
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
  1. 然后编写签名代码:
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS1EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class SshRsaSigner {
    public static void main(String[] args) throws Exception {
        // 注册BouncyCastle提供者
        java.security.Security.addProvider(new BouncyCastleProvider());

        // 读取私钥文件内容
        String privateKeyStr = new String(Files.readAllBytes(Paths.get("id_rsa")), StandardCharsets.UTF_8);
        // 去除PEM格式的头部、尾部和空白字符
        privateKeyStr = privateKeyStr.replace("-----BEGIN RSA PRIVATE KEY-----", "")
                                     .replace("-----END RSA PRIVATE KEY-----", "")
                                     .replaceAll("\\s", "");
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);

        // 解析PKCS#1格式的私钥
        KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
        PKCS1EncodedKeySpec keySpec = new PKCS1EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 初始化签名器,算法要和API要求一致
        Signature signature = Signature.getInstance("SHA256withRSA", "BC");
        signature.initSign(privateKey);
        // 传入请求体内容
        String requestBody = "your-request-body-content";
        signature.update(requestBody.getBytes(StandardCharsets.UTF_8));
        // 生成签名
        byte[] signatureBytes = signature.sign();

        // 转成Base64字符串
        String signatureBase64 = Base64.getEncoder().encodeToString(signatureBytes);
        System.out.println("生成的签名:" + signatureBase64);
    }
}

关键注意事项

  • 一定要和第三方API确认签名算法(比如是SHA256withRSA还是SHA1withRSA)、填充方式(通常是PKCS1v15),这些参数必须完全匹配,否则签名验证会失败。
  • 如果生成私钥时设置了密码,读取私钥时必须传入对应的密码,否则会解析失败。
  • 大多数API要求签名结果以Base64编码的字符串形式传递,所以最后一步的转换不能少。

内容的提问来源于stack exchange,提问作者Melad Basilius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:48:17