ssh-ed25519 字符串到java中的公钥

问题描述 投票:0回答:1

我在密码学方面几乎是新手,并且在将

ed25519
公钥字符串加载到
java.security.PublicKey
中时遇到问题。当我尝试使用
openssl
的密钥时它有效,但当我加载使用
ssh-keygen
生成的密钥时它不起作用。为了提供更多背景信息,我们有一个
apache-mina
SFTP 服务器,客户端可以使用公钥登录。

代码如下(用Scala编写),我可能犯了一个根本性错误,我只是没有看到它。如有任何帮助,我们将不胜感激。

  def main(args: Array[String]): Unit = {
    // ssh key generated from openssl:
    // openssl genpkey -algorithm ed25519 -out private_key.pem
    // openssl pkey -in private_key.pem -pubout -out public_key.pem
    val sshKey = "MCowBQYDK2VwAyEA4LSmWoy4ZBYJuwRttwzSLu0KQAYBKGRMHqPNBAun0gA="
    println(stringToKey(sshKey))

    // ssh key generated using ssh-keygen (ssh-keygen -t ed25519 -C "martin")
    val sshKeyGen = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpjh408HMAa1uE60DFrUs0GcgRflP1Hc3iLJlesVfCb martin"
    val Array(_, keyData, _) = sshKeyGen.split(" ", 3) // Split the key
    println(stringToKey(keyData)) // Not working
  }

  def stringToKey(sshKey: String): PublicKey = {
    Security.addProvider(new BouncyCastleProvider())

    val serializedKey: Array[Byte] = Base64.getDecoder.decode(sshKey)

    val kf: KeyFactory = KeyFactory.getInstance("Ed25519", "BC")
    val keySpec: X509EncodedKeySpec = new X509EncodedKeySpec(serializedKey)
    val key: PublicKey = kf.generatePublic(keySpec)
    key
  }

输出

**OpenSSL Key**
Ed25519 Public Key [70:e6:65:14:c0:99:2d:13:58:87:e1:cc:95:9b:2c:93:39:03:39:9f]
    public data: e0b4a65a8cb8641609bb046db70cd22eed0a40060128644c1ea3cd040ba7d200

**SSH Keygen Key**
Exception in thread "main" java.security.spec.InvalidKeySpecException: encoded key spec not recognized: failed to construct sequence from byte[]: unexpected end-of-contents marker
    at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.edec.KeyFactorySpi.engineGeneratePublic(KeyFactorySpi.java:224)
    at java.base/java.security.KeyFactory.generatePublic(KeyFactory.java:345)
java openssl ssh-keys key-pair ed25519
1个回答
0
投票

OpenSSH 公钥格式是非标准的。

对于所有算法的公钥,OpenSSL 使用由 X.509/PKIX 在

RFC5280
中定义的 ASN.1 结构 SubjectPublicKeyInfo,这也是 Java 加密本机使用的。虽然“SPKI”一般来说可能很复杂,但 Ed25519 的情况却非常简单。 OpenSSH 使用自己的格式,基于 SSH 协议线路格式,Ed25519 也很简单。

您可以将 OpenSSH 格式的 Ed25519 密钥转换为 Java 支持的形式,如下所示:

// in Java because I don't scale, but you should be able to convert String osshpub = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpjh408HMAa1uE60DFrUs0GcgRflP1Hc3iLJlesVfCb martin"; byte[] rawpub = Base64.getDecoder().decode( osshpub.split(" ")[1] ); byte[] prefix = { 0x30,0x2a,0x30,0x05,0x06,0x03,0x2b,0x65,0x70,0x03,0x21,0x00 }; // or equivalent and perhaps easier //byte[] prefix = Base64.getDecoder().decode("MCowBQYDK2VwAyEA"); byte[] spki = Arrays.copyOf(prefix, prefix.length+32); System.arraycopy(rawpub,19, spki,prefix.length, 32); PublicKey javapub = KeyFactory.getInstance("Ed25519").generatePublic(new X509EncodedKeySpec(spki)); // in Java 15 up the standard provider(s) support Ed25519 and you don't need BouncyCastle // below that or to force Bouncy, add ,"BC" in getInstance
但是如果使用 Apache mina,则不需要;它本身支持 OpenSSH 'authorized_keys' 格式;参见例如

https://github.com/apache/mina-sshd/blob/master/sshd-common/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry 中

readAuthorizedKeys
的重载。 java。客户端使用的“known_hosts”格式在前面有一个字段(用于主机名/地址),但在其他方面是相同的,并且也受支持。

© www.soinside.com 2019 - 2024. All rights reserved.