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

如何在Java/Android中生成符合OpenSSH格式的Ed25519密钥?

如何用Java/Android生成符合OpenSSH格式的Ed25519密钥

你当前通过BouncyCastle直接获取的encoded是原始32字节Ed25519公钥,但OpenSSH的公钥是带固定结构的字节序列,直接给原始公钥加前缀会因格式不匹配被Github拒绝。以下是生成符合要求的OpenSSH格式密钥的解决方案:

一、生成符合OpenSSH格式的公钥

OpenSSH公钥的结构要求为:

  1. 4字节大端长度 + 字符串ssh-ed25519的字节内容
  2. 4字节大端长度 + 原始32字节公钥内容
    将整个结构做Base64编码后,拼接前缀ssh-ed25519 和可选注释(如邮箱),就是标准的OpenSSH公钥格式。

Kotlin代码实现

import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator
import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters
import java.nio.ByteBuffer
import java.security.SecureRandom
import android.util.Base64 // Android平台使用,JVM环境替换为java.util.Base64

// 生成Ed25519密钥对
val keyPairGenerator = Ed25519KeyPairGenerator()
keyPairGenerator.init(Ed25519KeyGenerationParameters(SecureRandom()))
val keyPair = keyPairGenerator.generateKeyPair()

// 提取原始公钥字节
val publicKeyParams = keyPair.public as Ed25519PublicKeyParameters
val rawPublicKey = publicKeyParams.encoded

// 构造OpenSSH公钥结构
val keyType = "ssh-ed25519".toByteArray()
val buffer = ByteBuffer.allocate(4 + keyType.size + 4 + rawPublicKey.size)
// 写入密钥类型的长度和内容
buffer.putInt(keyType.size)
buffer.put(keyType)
// 写入原始公钥的长度和内容
buffer.putInt(rawPublicKey.size)
buffer.put(rawPublicKey)
val openSshStructBytes = buffer.array()

// 编码为Base64并拼接最终格式
val encodedPublicKey = Base64.encodeToString(openSshStructBytes, Base64.DEFAULT)
val finalOpenSshPublicKey = "ssh-ed25519 $encodedPublicKey example@gmail.com"
Log.d(TAG, finalOpenSshPublicKey)

二、生成符合OpenSSH格式的私钥

如果需要生成可直接用于SSH客户端的私钥,可以用BouncyCastle的PEM工具类生成OpenSSH格式的PEM私钥:

Kotlin代码实现

import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
import java.io.StringWriter

// 提取私钥参数
val privateKeyParams = keyPair.private as Ed25519PrivateKeyParameters
val privateKeyInfo = privateKeyParams.toPrivateKeyInfo()

// 生成PEM格式的OpenSSH私钥
val writer = StringWriter()
JcaPEMWriter(writer).use { pemWriter ->
    pemWriter.writeObject(privateKeyInfo)
}
val openSshPrivateKey = writer.toString()
Log.d(TAG, openSshPrivateKey)

注意事项

  • 确保使用的org.bouncycastle:bcpkix-jdk15on库版本为最新稳定版,避免存在格式兼容问题
  • Android平台上Base64编码请使用android.util.Base64,JVM环境则用java.util.Base64

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:23:15