我想将 *.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'
这可以通过 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
)。