org.apache.camel.component.file.remote.DSAKeyPairIdentity Maven / Gradle / Ivy
/**
* 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.file.remote;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import com.jcraft.jsch.Identity;
import com.jcraft.jsch.JSchException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DSAKeyPairIdentity implements Identity {
private static final String ALGORITHM_TYPE = "ssh-dss";
private final Logger log = LoggerFactory.getLogger(getClass());
private KeyPair keyPair;
private String name;
public DSAKeyPairIdentity(String name, KeyPair keyPair) {
this.name = name;
this.keyPair = keyPair;
}
@Override
public boolean setPassphrase(byte[] passphrase) throws JSchException {
return true;
}
@Override
public byte[] getPublicKeyBlob() {
DSAPublicKey publicKey = (DSAPublicKey) keyPair.getPublic();
byte[] sshDss = ALGORITHM_TYPE.getBytes();
DSAParams dsaParams = publicKey.getParams();
byte[] pArray = dsaParams.getP().toByteArray();
byte[] qArray = dsaParams.getQ().toByteArray();
byte[] gArray = dsaParams.getG().toByteArray();
byte[] yArray = publicKey.getY().toByteArray();
byte[] result = new byte[sshDss.length + 4 + pArray.length + 4 + qArray.length + 4 + gArray.length + 4 + yArray.length + 4];
int index = 0;
byte[] intAsByteArray = ByteBuffer.allocate(4).putInt(sshDss.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(sshDss, 0, result, index, sshDss.length);
index += sshDss.length;
intAsByteArray = ByteBuffer.allocate(4).putInt(pArray.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(pArray, 0, result, index, pArray.length);
index += pArray.length;
intAsByteArray = ByteBuffer.allocate(4).putInt(qArray.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(qArray, 0, result, index, qArray.length);
index += qArray.length;
intAsByteArray = ByteBuffer.allocate(4).putInt(gArray.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(gArray, 0, result, index, gArray.length);
index += gArray.length;
intAsByteArray = ByteBuffer.allocate(4).putInt(yArray.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(yArray, 0, result, index, yArray.length);
return result;
}
@Override
public byte[] getSignature(byte[] data) {
try {
PrivateKey prvKey = keyPair.getPrivate();
Signature sig;
sig = Signature.getInstance("SHA1withDSA");
sig.initSign(prvKey);
sig.update(data);
byte[] sshDss = ALGORITHM_TYPE.getBytes();
byte[] signature = sig.sign();
signature = convertDERToP1363(signature);
byte[] result = new byte[sshDss.length + 4 + signature.length + 4];
int index = 0;
byte[] intAsByteArray = ByteBuffer.allocate(4).putInt(sshDss.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(sshDss, 0, result, index, sshDss.length);
index += sshDss.length;
intAsByteArray = ByteBuffer.allocate(4).putInt(signature.length).array();
System.arraycopy(intAsByteArray, 0, result, index, 4);
index += 4;
System.arraycopy(signature, 0, result, index, signature.length);
return result;
} catch (NoSuchAlgorithmException e) {
log.error("Cannot sign", e);
} catch (InvalidKeyException e) {
log.error("Cannot sign", e);
} catch (SignatureException e) {
log.error("Cannot sign", e);
}
return null;
}
/**
* "The signature on m is (r, s). Message m and (r, s) should be sent to the
* verifier. We need to observe that both r and s are 20 bytes, since a
* modular reduction is being performed (steps 2 and 5) using q, a 160 bit
* value. This will gain significance later when we begin verifying messages
* between Crypto++ and C# (which use the IEEE P1363 signature format) and
* Java (which uses a DER encoding of a signature)." [taken from Cryptographic Interoperability Digital Signatures]
*
* @param sig
* signature in DER format
* @return signature in P1363 format; SEQUENCE ::= { r INTEGER, s INTEGER }
*/
private byte[] convertDERToP1363(byte[] sig) {
int index = 3;
int len = sig[index++] & 0xff;
byte[] r = new byte[len];
System.arraycopy(sig, index, r, 0, r.length);
index = index + len + 1;
len = sig[index++] & 0xff;
byte[] s = new byte[len];
System.arraycopy(sig, index, s, 0, s.length);
byte[] p1363Signature = new byte[40];
if (r.length > 21 || (r.length == 21 && r[0] != 0)) {
// Reject - signature verification failed
} else if (r.length == 21) {
// r[0] = 0
// r[1]'s high bit *should* be set
System.arraycopy(r, 1, p1363Signature, 0, 20);
} else if (r.length == 20) {
// r[0]'s high bit *should not* be set
System.arraycopy(r, 0, p1363Signature, 0, 20);
} else {
// fewer than 20 bytes
len = r.length;
int off = 20 - len;
System.arraycopy(r, 0, p1363Signature, off, len);
}
if (s.length > 21 || (s.length == 21 && s[0] != 0)) {
// Reject - signature verification failed
p1363Signature = new byte[0];
} else if (s.length == 21) {
// s[0] = 0
// s[1]'s high bit *should* be set
System.arraycopy(s, 1, p1363Signature, 20, 20);
} else if (s.length == 20) {
// s[0]'s high bit *should not* be set
System.arraycopy(s, 0, p1363Signature, 20, 20);
} else {
// fewer than 20 bytes
len = s.length;
int off = 40 - len;
System.arraycopy(s, 0, p1363Signature, off, len);
}
return p1363Signature;
}
@Override
public boolean decrypt() {
return true;
}
@Override
public String getAlgName() {
return ALGORITHM_TYPE;
}
@Override
public String getName() {
return name;
}
@Override
public boolean isEncrypted() {
return false;
}
@Override
public void clear() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy