如何在java中将ssh公钥转换为PublicKey

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

我想将 *.pub 文件中的 ssh 公钥转换为 PublicKey(java.security.PublicKey)。

原因是我需要检查ssh公钥的算法,有什么办法可以做到吗?

因为我遇到了以下错误。

java.lang.IllegalArgumentException: failed to construct sequence from byte[]: unexpected end-of-contents marker

    at org.bouncycastle.asn1.ASN1Sequence.getInstance(Unknown Source)
    at org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(Unknown Source)
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

public class PublicKeyUtil {
  private PublicKeyUtil() {}
  // (skip)
  public static PublicKey loadPublicKey(String encoded)
      throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

    byte[] publicBytes = Base64.getDecoder().decode(encoded);
    PublicKey publicKey =
        new JcaPEMKeyConverter().getPublicKey(SubjectPublicKeyInfo.getInstance(publicBytes)); // I've got an error here, when calling the SubjectPublicKeyInfo.getInstance(publicBytes)

    return KeyFactory.getInstance(
            publicKey.getAlgorithm(), new org.bouncycastle.jce.provider.BouncyCastleProvider())
        .generatePublic(new X509EncodedKeySpec(publicBytes));
  }
  // (skip)
}

下面是我的build.gradle

implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.78.1'
ssh bouncycastle openssh public-key java-security
1个回答
0
投票

这可以通过 BouncyCastle 来实现。首先,必须创建一个

AsymmetricKeyParameter
实例。实际上,这足以与 BouncyCastle 类一起加密或验证,因此
PublicKey
不一定是必需的。

但是,如果出于任何原因需要

PublicKey
(例如,如果要使用 JCA/JCE 类进行加密或验证),则可以通过
OpenSSHPublicKeySpec
实例创建它。

由于您没有指定算法,因此在以下示例中使用 RSA 密钥:

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Security;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
import org.bouncycastle.jcajce.spec.OpenSSHPublicKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

...

Security.addProvider(new BouncyCastleProvider());
String ssh_rsa = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgKfP2Vvx9HwhzvKFE4Yo5NdIec1KF+awxRtj+ArN83nBLErJ1FIS5hcTrJaUjAimoLfK2kigF4QWyfgjvTBzv8djCXEsjIhavbUyATaFEtq2JzrPFf2gLkgOkPhIH7ZNXx+YhHlMa44lFeyQNGqhOqaloWKuaeNw421FYx/cemuyv//OrdCLNgEms7kqDyc9V9JUkhsjElhHHIQA/SsI4eNrxNsUbLtQJQaThTm4o9iWSAjqy4sqJj//EmBwV2C4seHIuWztZTx5TF7LxD1nlxCcxONrea4LGxMK28ngujpzimEJb7ORmjvxmO62LpyZ9HuIwwKAhPsnVuTUElUD9 whatever";
AsymmetricKeyParameter asymmetricKeyParameter = OpenSSHPublicKeyUtil.parsePublicKey(Base64.getDecoder().decode(ssh_rsa.split(" ")[1]));
OpenSSHPublicKeySpec openSSHPublicKeySpec = new OpenSSHPublicKeySpec(OpenSSHPublicKeyUtil.encodePublicKey(asymmetricKeyParameter));
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(openSSHPublicKeySpec);

...

请注意,在第二步中,必须指定算法。取决于算法,例如必须使用

Ed25519
ECDSA
代替
RSA
(可以根据前缀确定算法,例如,对于 Ed25519,前缀是
ssh-ed25519
或对于 ECDSA 类似
ecdsa-sha2-nistp256
)。

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