如何在Java/Android中生成符合OpenSSH格式的Ed25519密钥?
如何用Java/Android生成符合OpenSSH格式的Ed25519密钥
你当前通过BouncyCastle直接获取的encoded是原始32字节Ed25519公钥,但OpenSSH的公钥是带固定结构的字节序列,直接给原始公钥加前缀会因格式不匹配被Github拒绝。以下是生成符合要求的OpenSSH格式密钥的解决方案:
一、生成符合OpenSSH格式的公钥
OpenSSH公钥的结构要求为:
- 4字节大端长度 + 字符串
ssh-ed25519的字节内容 - 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
相关产品推荐
相关产品推荐

