package com.jcraft.jsch;
import java.math.BigInteger;
public class KeyPairRSA extends KeyPair{
private byte[] n_array;
private byte[] pub_array;
private byte[] prv_array;
private byte[] p_array;
private byte[] q_array;
private byte[] ep_array;
private byte[] eq_array;
private byte[] c_array;
private int key_size=1024;
public KeyPairRSA(JSch jsch){
this(jsch, null, null, null);
}
public KeyPairRSA(JSch jsch,
byte[] n_array,
byte[] pub_array,
byte[] prv_array){
super(jsch);
this.n_array = n_array;
this.pub_array = pub_array;
this.prv_array = prv_array;
if(n_array!=null){
key_size = (new java.math.BigInteger(n_array)).bitLength();
}
}
void generate(int key_size) throws JSchException{
this.key_size=key_size;
try{
Class c=Class.forName(jsch.getConfig("keypairgen.rsa"));
KeyPairGenRSA keypairgen=(KeyPairGenRSA)(c.newInstance());
keypairgen.init(key_size);
pub_array=keypairgen.getE();
prv_array=keypairgen.getD();
n_array=keypairgen.getN();
p_array=keypairgen.getP();
q_array=keypairgen.getQ();
ep_array=keypairgen.getEP();
eq_array=keypairgen.getEQ();
c_array=keypairgen.getC();
keypairgen=null;
}
catch(Exception e){
if(e instanceof Throwable)
throw new JSchException(e.toString(), (Throwable)e);
throw new JSchException(e.toString());
}
}
private static final byte[] begin=Util.str2byte("-----BEGIN RSA PRIVATE KEY-----");
private static final byte[] end=Util.str2byte("-----END RSA PRIVATE KEY-----");
byte[] getBegin(){ return begin; }
byte[] getEnd(){ return end; }
byte[] getPrivateKey(){
int content=
1+countLength(1) + 1 +
1+countLength(n_array.length) + n_array.length +
1+countLength(pub_array.length) + pub_array.length +
1+countLength(prv_array.length) + prv_array.length+
1+countLength(p_array.length) + p_array.length+
1+countLength(q_array.length) + q_array.length+
1+countLength(ep_array.length) + ep_array.length+
1+countLength(eq_array.length) + eq_array.length+
1+countLength(c_array.length) + c_array.length;
int total=
1+countLength(content)+content;
byte[] plain=new byte[total];
int index=0;
index=writeSEQUENCE(plain, index, content);
index=writeINTEGER(plain, index, new byte[1]);
index=writeINTEGER(plain, index, n_array);
index=writeINTEGER(plain, index, pub_array);
index=writeINTEGER(plain, index, prv_array);
index=writeINTEGER(plain, index, p_array);
index=writeINTEGER(plain, index, q_array);
index=writeINTEGER(plain, index, ep_array);
index=writeINTEGER(plain, index, eq_array);
index=writeINTEGER(plain, index, c_array);
return plain;
}
boolean parse(byte [] plain){
try{
int index=0;
int length=0;
if(vendor==VENDOR_PUTTY){
Buffer buf = new Buffer(plain);
buf.skip(plain.length);
try {
byte[][] tmp = buf.getBytes(4, "");
prv_array = tmp[0];
p_array = tmp[1];
q_array = tmp[2];
c_array = tmp[3];
}
catch(JSchException e){
return false;
}
getEPArray();
getEQArray();
return true;
}
if(vendor==VENDOR_FSECURE){
if(plain[index]!=0x30){
Buffer buf=new Buffer(plain);
pub_array=buf.getMPIntBits();
prv_array=buf.getMPIntBits();
n_array=buf.getMPIntBits();
byte[] u_array=buf.getMPIntBits();
p_array=buf.getMPIntBits();
q_array=buf.getMPIntBits();
if(n_array!=null){
key_size = (new java.math.BigInteger(n_array)).bitLength();
}
getEPArray();
getEQArray();
getCArray();
return true;
}
return false;
}
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
if(plain[index]!=0x02)return false;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
n_array=new byte[length];
System.arraycopy(plain, index, n_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
pub_array=new byte[length];
System.arraycopy(plain, index, pub_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
prv_array=new byte[length];
System.arraycopy(plain, index, prv_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
p_array=new byte[length];
System.arraycopy(plain, index, p_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
q_array=new byte[length];
System.arraycopy(plain, index, q_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
ep_array=new byte[length];
System.arraycopy(plain, index, ep_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
eq_array=new byte[length];
System.arraycopy(plain, index, eq_array, 0, length);
index+=length;
index++;
length=plain[index++]&0xff;
if((length&0x80)!=0){
int foo=length&0x7f; length=0;
while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); }
}
c_array=new byte[length];
System.arraycopy(plain, index, c_array, 0, length);
index+=length;
if(n_array!=null){
key_size = (new java.math.BigInteger(n_array)).bitLength();
}
}
catch(Exception e){
return false;
}
return true;
}
public byte[] getPublicKeyBlob(){
byte[] foo=super.getPublicKeyBlob();
if(foo!=null) return foo;
if(pub_array==null) return null;
byte[][] tmp = new byte[3][];
tmp[0] = sshrsa;
tmp[1] = pub_array;
tmp[2] = n_array;
return Buffer.fromBytes(tmp).buffer;
}
private static final byte[] sshrsa=Util.str2byte("ssh-rsa");
byte[] getKeyTypeName(){return sshrsa;}
public int getKeyType(){return RSA;}
public int getKeySize(){
return key_size;
}
public byte[] getSignature(byte[] data){
try{
Class c=Class.forName((String)jsch.getConfig("signature.rsa"));
SignatureRSA rsa=(SignatureRSA)(c.newInstance());
rsa.init();
rsa.setPrvKey(prv_array, n_array);
rsa.update(data);
byte[] sig = rsa.sign();
byte[][] tmp = new byte[2][];
tmp[0] = sshrsa;
tmp[1] = sig;
return Buffer.fromBytes(tmp).buffer;
}
catch(Exception e){
}
return null;
}
public Signature getVerifier(){
try{
Class c=Class.forName((String)jsch.getConfig("signature.rsa"));
SignatureRSA rsa=(SignatureRSA)(c.newInstance());
rsa.init();
if(pub_array == null && n_array == null && getPublicKeyBlob()!=null){
Buffer buf = new Buffer(getPublicKeyBlob());
buf.getString();
pub_array = buf.getString();
n_array = buf.getString();
}
rsa.setPubKey(pub_array, n_array);
return rsa;
}
catch(Exception e){
}
return null;
}
static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException {
byte[][] tmp = buf.getBytes(8, "invalid key format");
byte[] n_array = tmp[1];
byte[] pub_array = tmp[2];
byte[] prv_array = tmp[3];
KeyPairRSA kpair = new KeyPairRSA(jsch, n_array, pub_array, prv_array);
kpair.c_array = tmp[4];
kpair.p_array = tmp[5];
kpair.q_array = tmp[6];
kpair.publicKeyComment = new String(tmp[7]);
kpair.vendor=VENDOR_OPENSSH;
return kpair;
}
public byte[] () throws JSchException {
if(isEncrypted()){
throw new JSchException("key is encrypted.");
}
Buffer buf = new Buffer();
buf.putString(sshrsa);
buf.putString(n_array);
buf.putString(pub_array);
buf.putString(prv_array);
buf.putString(getCArray());
buf.putString(p_array);
buf.putString(q_array);
buf.putString(Util.str2byte(publicKeyComment));
byte[] result = new byte[buf.getLength()];
buf.getByte(result, 0, result.length);
return result;
}
private byte[] getEPArray(){
if(ep_array==null){
ep_array=(new BigInteger(prv_array)).mod(new BigInteger(p_array).subtract(BigInteger.ONE)).toByteArray();
}
return ep_array;
}
private byte[] getEQArray(){
if(eq_array==null){
eq_array=(new BigInteger(prv_array)).mod(new BigInteger(q_array).subtract(BigInteger.ONE)).toByteArray();
}
return eq_array;
}
private byte[] getCArray(){
if(c_array==null){
c_array=(new BigInteger(q_array)).modInverse(new BigInteger(p_array)).toByteArray();
}
return c_array;
}
public void dispose(){
super.dispose();
Util.bzero(prv_array);
}
}