Java ssh-rsa字符串到公钥

Jan*_*tze 6 java encryption ssh rsa public-key-encryption

我想获取.pub文件内容的公钥.这是一个.pub文件内容(生成ssh-keygen)的示例:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBPL2s+25Ank3zS6iHUoVk0tS63dZM0LzAaniiDon0tdWwq4vcL4+fV8BsAEcpMeijS92JhDDc9FccXlHbdDcmd6c4ITOt9h9xxhIefGsi1FTVJ/EjVtbqF5m0bu7ruIMGvuP1p5s004roHx9y0UdHvD/yNWLISMhy4nio6jLailIj3FS53Emj1WRNsOrpja3LzPXzhuuj6YnD9yfByT7iGZipxkmleaXrknChPClLI9uhcqtAzBLdd0NVTJLOt/3+d1cSNwdBw9e53wJvpEmH+P8UOZd+oV/y7cHIej4jQpBXVvpJR1Yaluh5RuxY90B0hSescUAj4g/3HVPpR/gE7op6i9Ab//0iXF15uWGlGzipI4lA2/wYEtv8swTjmdCTMNcTDw/1huTDEzZjghIKVpskHde/Lj416c7eSByLqsMg2OhlZGChKznpIjhuNRXz93DwqKuIKvJKSnhqaJDxmDGfG7nlQ/eTwGeAZ6VR50yMPiRTIpuYd767+Nsg486z7p0pnKoBlL6ffTbfeolUX2b6Nb9ZIOxJdpCSNTQRKQ50p4Y3S580cUM1Y2EfjlfIQG1JdmTQYB75AZXi/cB2PvScmF0bXRoj7iHg4lCnSUvRprWA0xbwzCW/wjNqw6MyRX42FFlvSRrmfaxGZxKYbmk3TzBv+Fp+CADPqQm3OQ== test@test.com
Run Code Online (Sandbox Code Playgroud)

如果我是对的,这不是公钥,但可以从此字符串中获取公钥.

这个答案给出了我的问题 的答案/sf/answers/1357126221/
但答案似乎不起作用.我得到一个例外:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
Run Code Online (Sandbox Code Playgroud)

在查看答案的评论时,我不是唯一有问题的人...

我该如何修复异常?或者是否有另一种方法从字符串中获取公钥?

小智 5

这是我的 SSH RSA -> RSAPublicKey 转换器实现。我在网上的某个地方找到了关键格式描述,所以感谢提供它的人。

public class CertificateUtils {
    private static final int VALUE_LENGTH = 4;
    private static final byte[] INITIAL_PREFIX = new byte[]{0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61};
    private static final Pattern SSH_RSA_PATTERN = Pattern.compile("ssh-rsa[\\s]+([A-Za-z0-9/+]+=*)[\\s]+.*");

// SSH-RSA key format
//
//        00 00 00 07             The length in bytes of the next field
//        73 73 68 2d 72 73 61    The key type (ASCII encoding of "ssh-rsa")
//        00 00 00 03             The length in bytes of the public exponent
//        01 00 01                The public exponent (usually 65537, as here)
//        00 00 01 01             The length in bytes of the modulus (here, 257)
//        00 c3 a3...             The modulus

    public static RSAPublicKey parseSSHPublicKey(String key) throws InvalidKeyException {
        Matcher matcher = SSH_RSA_PATTERN.matcher(key.trim());
        if (!matcher.matches()) {
            throw new InvalidKeyException("Key format is invalid for SSH RSA.");
        }
        String keyStr = matcher.group(1);

        ByteArrayInputStream is = new ByteArrayInputStream(Base64.decodeBase64(keyStr));

        byte[] prefix = new byte[INITIAL_PREFIX.length];

        try {
            if (INITIAL_PREFIX.length != is.read(prefix) || !ArrayUtils.isEquals(INITIAL_PREFIX, prefix)) {
                throw new InvalidKeyException("Initial [ssh-rsa] key prefix missed.");
            }

            BigInteger exponent = getValue(is);
            BigInteger modulus = getValue(is);

            return (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
        } catch (IOException | InvalidKeySpecException | NoSuchAlgorithmException e) {
            throw new InvalidKeyException("Failed to read SSH RSA certificate from string", e);
        }
    }

    private static BigInteger getValue(InputStream is) throws IOException {
        byte[] lenBuff = new byte[VALUE_LENGTH];
        if (VALUE_LENGTH != is.read(lenBuff)) {
            throw new InvalidParameterException("Unable to read value length.");
        }

        int len = ByteBuffer.wrap(lenBuff).getInt();
        byte[] valueArray = new byte[len];
        if (len != is.read(valueArray)) {
            throw new InvalidParameterException("Unable to read value.");
        }

        return new BigInteger(valueArray);
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。


dnu*_*092 3

您必须将密钥转换为 pkcs8 规范。使用下面的命令

\n\n
ssh-keygen -f private.key -e -m pkcs8 > test-pkcs8.pub\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后将其转换为x509

\n\n
openssl rsa -pubin -in test-pkcs8.pub -outform pem > test-x509.pem\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,您可以使用下面的代码将公钥读取为 Java 中的 RSAPublicKey

\n\n
import java.io.IOException;\n\nimport java.net.URISyntaxException;\n\nimport java.nio.file.Files;\n\nimport java.nio.file.Paths;\n\nimport java.security.KeyFactory;\n\nimport java.security.NoSuchAlgorithmException;\n\nimport java.security.PrivateKey;\n\nimport java.security.interfaces.RSAPublicKey;\n\nimport java.security.spec.InvalidKeySpecException;\n\nimport java.security.spec.PKCS8EncodedKeySpec;\n\nimport java.security.spec.X509EncodedKeySpec;\n\nimport java.util.Base64;\n\n\n/**\n\n* This file is intended to be used on a IDE for testing purposes.\n\n* ClassLoader.getSystemResource won\'t work in a JAR\n\n*/\n\npublic class Main {\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0public static void main(String[] args) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, URISyntaxException {\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0String privateKeyContent = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("private_key_pkcs8.pem").toURI())));\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0String publicKeyContent = new String(Files.readAllBytes(Paths.get(ClassLoader.getSystemResource("public_key.pem").toURI())));\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0privateKeyContent = privateKeyContent.replaceAll("\\\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0publicKeyContent = publicKeyContent.replaceAll("\\\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");;\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0KeyFactory kf = KeyFactory.getInstance("RSA");\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyContent));\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0PrivateKey privKey = kf.generatePrivate(keySpecPKCS8);\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyContent));\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(keySpecX509);\n\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0System.out.println(privKey);\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0System.out.println(pubKey);\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0}\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

从下面两个链接得到了答案

\n\n

在 Java 中将 ssh-rsa 转换为 X509 规范

\n\n

在 Java 中加载 X509 规范密钥作为 RSAPublicKey 对象

\n\n

希望这能给您一些直觉。

\n