All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.camel.component.ssh.SSHPublicKeyHolder Maven / Gradle / Ivy

There is a newer version: 4.9.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.component.ssh;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;

import org.apache.sshd.common.cipher.ECCurves;
import org.bouncycastle.jcajce.spec.OpenSSHPublicKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class SSHPublicKeyHolder {
    private static final String SSH_RSA = "ssh-rsa";
    private static final String SSH_DSS = "ssh-dss";

    private static final String SSH_ECDSA_PREFIX = "ecdsa-sha2-";
    // ssh-keygen ... -b 256 -t ecdsa
    private static final String SSH_ECDSA = SSH_ECDSA_PREFIX + "nistp256";
    // ssh-keygen ... -b 384 -t ecdsa
    private static final String SSH_ECDSA_384 = SSH_ECDSA_PREFIX + "nistp384";
    // ssh-keygen ... -b 521 -t ecdsa # yes - "521", not "512"
    private static final String SSH_ECDSA_521 = SSH_ECDSA_PREFIX + "nistp521";

    // ssh-keygen ... -t ed25519
    private static final String SSH_ED25519 = "ssh-ed25519";

    private String keyType;

    /* RSA key parts */
    private BigInteger e;
    private BigInteger m;

    /* DSA key parts */
    private BigInteger p;
    private BigInteger q;
    private BigInteger g;
    private BigInteger y;

    /* EC key parts */
    private String curveName;
    private ECPoint ecPoint;
    private ECParameterSpec ecParams;

    /* EdDSA key parts */
    private final ByteArrayOutputStream edKeyEncoded = new ByteArrayOutputStream();

    public String getKeyType() {
        return keyType;
    }

    public void setKeyType(String keyType) {
        this.keyType = keyType;
    }

    public BigInteger getE() {
        return e;
    }

    public void setE(BigInteger e) {
        this.e = e;
    }

    public BigInteger getM() {
        return m;
    }

    public void setM(BigInteger m) {
        this.m = m;
    }

    public BigInteger getG() {
        return g;
    }

    public void setG(BigInteger g) {
        this.g = g;
    }

    public BigInteger getP() {
        return p;
    }

    public void setP(BigInteger p) {
        this.p = p;
    }

    public BigInteger getQ() {
        return q;
    }

    public void setQ(BigInteger q) {
        this.q = q;
    }

    public BigInteger getY() {
        return y;
    }

    public void setY(BigInteger y) {
        this.y = y;
    }

    public void push(byte[] keyPart) {
        if (keyType == null) {
            this.keyType = new String(keyPart, StandardCharsets.UTF_8);
            if (SSH_ED25519.equals(keyType)) {
                encode(edKeyEncoded, keyType);
            }
            return;
        }

        if (SSH_RSA.equals(keyType)) {
            if (e == null) {
                this.e = new BigInteger(keyPart);
                return;
            }

            if (m == null) {
                this.m = new BigInteger(keyPart);
                return;
            }
        }

        if (SSH_DSS.equals(keyType)) {
            if (p == null) {
                this.p = new BigInteger(keyPart);
                return;
            }

            if (q == null) {
                this.q = new BigInteger(keyPart);
                return;
            }

            if (g == null) {
                this.g = new BigInteger(keyPart);
                return;
            }

            if (y == null) {
                this.y = new BigInteger(keyPart);
                return;
            }
        }

        if (keyType.equals(SSH_ED25519)) {
            // https://tools.ietf.org/html/rfc8709
            // https://tools.ietf.org/html/rfc8032#section-5.2.5
            encode(edKeyEncoded, keyPart);
            return;
        }

        if (keyType.startsWith(SSH_ECDSA_PREFIX)) {
            // https://tools.ietf.org/html/rfc5656#section-3.1
            // see org.apache.sshd.common.util.buffer.keys.ECBufferPublicKeyParser.getRawECKey
            if (curveName == null) {
                curveName = new String(keyPart, StandardCharsets.UTF_8);
                return;
            }
            if (ecPoint == null) {
                ecParams = ECCurves.fromKeyType(keyType).getParameters();
                ecPoint = ECCurves.octetStringToEcPoint(keyPart);
            }
        }
    }

    public PublicKey toPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        PublicKey returnValue = null;

        if (SSH_RSA.equals(keyType)) {
            RSAPublicKeySpec dsaPublicKeySpec = new RSAPublicKeySpec(m, e);
            KeyFactory factory = KeyFactory.getInstance("RSA");
            returnValue = factory.generatePublic(dsaPublicKeySpec);
        }

        if (SSH_DSS.equals(keyType)) {
            DSAPublicKeySpec dsaPublicKeySpec = new DSAPublicKeySpec(y, p, q, g);
            KeyFactory factory = KeyFactory.getInstance("DSA");
            returnValue = factory.generatePublic(dsaPublicKeySpec);
        }

        if (SSH_ED25519.equals(keyType)) {
            OpenSSHPublicKeySpec ed25519PublicKeySpec = new OpenSSHPublicKeySpec(edKeyEncoded.toByteArray());
            KeyFactory factory = KeyFactory.getInstance("ED25519", new BouncyCastleProvider());
            returnValue = factory.generatePublic(ed25519PublicKeySpec);
        }

        if (keyType.startsWith(SSH_ECDSA_PREFIX)) {
            ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams);
            KeyFactory factory = KeyFactory.getInstance("EC");
            returnValue = factory.generatePublic(spec);
        }

        return returnValue;
    }

    private void encode(ByteArrayOutputStream target, byte[] value) {
        byte[] result = new byte[4 + value.length];
        result[0] = (byte) ((value.length & 0xFF) << 24);
        result[1] = (byte) ((value.length & 0xFF) << 16);
        result[2] = (byte) ((value.length & 0xFF) << 8);
        result[3] = (byte) (value.length & 0xFF);
        System.arraycopy(value, 0, result, 4, value.length);
        try {
            target.write(result);
        } catch (IOException ignored) {
        }
    }

    private void encode(ByteArrayOutputStream target, String v) {
        byte[] value = v.getBytes(StandardCharsets.UTF_8);
        encode(target, value);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy