如何将 ECDSA 公钥转换为 OpenSSH 格式?

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

如何将 ECDSA 公钥转换为 OpenSSH 格式以便与 ssh 一起使用?

java bouncycastle openssh
1个回答
0
投票
/**
 * SSH helper functions.
 */
public class SshKeys
{
    /**
     * Creates a new instance.
     */
    public SshKeys()
    {
    }

    /**
     * Returns the OpenSSH representation of a public key.
     *
     * @param publicKey the public key
     * @param comment   the comment to append to the end of the key
     * @return the PEM representation of the public key
     */
    public String toOpenSshPublicKey(PublicKey publicKey, String comment)
    {
        return switch (publicKey)
        {
            case ECPublicKey ecPublicKey -> toOpenSshPublicKey(ecPublicKey, comment);
            default -> throw new ClassCastException(publicKey.getClass().getName());
        };
    }

    /**
     * @param publicKey the public key
     * @param comment   the comment to append to the end of the key
     * @return the OpenSSH representation of the key
     * @throws NullPointerException if any of the arguments are null
     */
    public String toOpenSshPublicKey(ECPublicKey publicKey, String comment)
    {
        requireThat(comment, "comment").isNotNull();
        AsymmetricKeyParameter param = getAsymmetricKeyParameter(publicKey);

        // Encode the public key in OpenSSH format
        byte[] encodedPublicKey;
        try
        {
            encodedPublicKey = OpenSSHPublicKeyUtil.encodePublicKey(param);
        }
        catch (IOException e)
        {
            // The exception is declared but never actually thrown by the method
            throw new AssertionError(e);
        }

        // Determine the SSH key type based on the curve name
        String sshKeyType = getSshKeyType(publicKey);
        return sshKeyType + " " + Base64.getEncoder().encodeToString(encodedPublicKey) + " " + comment;
    }

    /**
     * @param publicKey a public key
     * @return the asymmetric key parameters of the key
     * @throws NullPointerException if {@code publicKey} is null
     */
    private AsymmetricKeyParameter getAsymmetricKeyParameter(ECPublicKey publicKey)
    {
        // Retrieve the curve parameters from the named curve
        X9ECParameters ecParams = ECNamedCurveTable.getByName(getCurveName(publicKey));
        ECCurve curve = ecParams.getCurve();
        ECPoint g = ecParams.getG();
        BigInteger n = ecParams.getN();
        BigInteger h = ecParams.getH();

        // Convert java.security.spec.ECPoint to BouncyCastle ECPoint
        java.security.spec.ECPoint w = publicKey.getW();
        ECPoint q = curve.createPoint(w.getAffineX(), w.getAffineY());

        ECDomainParameters domainParams = new ECDomainParameters(curve, g, n, h);
        return new ECPublicKeyParameters(q, domainParams);
    }

    /**
     * @param publicKey a public key
     * @return the name of the elliptic curve used in the public key
     * @throws NullPointerException if {@code publicKey} is null
     */
    private String getCurveName(ECPublicKey publicKey)
    {
        ECNamedCurveSpec params = (ECNamedCurveSpec) publicKey.getParams();
        return params.getName();
    }

    /**
     * @param publicKey a public key
     * @return the SSH type of the public key
     * @throws NullPointerException if {@code publicKey} is null
     */
    private String getSshKeyType(ECPublicKey publicKey)
    {
        String curveName = getCurveName(publicKey);
        // SSH key prefix: https://datatracker.ietf.org/doc/html/rfc5656#section-6.2
        return "ecdsa-sha2-" + switch (curveName)
        {
            // Mapping from curve type to SSH key type: https://datatracker.ietf.org/doc/html/rfc5656#section-10.1
            // Equivalent curves: https://www.rfc-editor.org/rfc/rfc4492.html#page-32
            case "secp256r1", "prime256v1" -> "nistp256";
            case "secp384r1" -> "nistp384";
            case "secp521r1" -> "nistp521";
            default -> throw new IllegalArgumentException("Invalid curve type: " + publicKey);
        };
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.