type = KeyType.SSH_RSA;
} else if( buf[i] == 'S' && buf[i + 1] == 'S' && buf[i + 2] == 'H' ) { // FSecure
type = KeyType.UNKNOWN;
vendor = VENDOR_FSECURE;
} else {
throw new JSchException("invalid privatekey: " + prvkey);
}
i += 3;
continue;
}
if( buf[i] == 'C' && buf[i + 1] == 'B' && buf[i + 2] == 'C' && buf[i + 3] == ',' ) {
i += 4;
for( int ii = 0; ii < iv.length; ii++ ) {
iv[ii] = (byte) (((DataUtil.a2b(buf[i++]) << 4) & 0xf0) + (DataUtil.a2b(buf[i++]) & 0xf));
}
continue;
}
if( buf[i] == 0x0d
&& i + 1 < buf.length && buf[i + 1] == 0x0a ) {
i++;
continue;
}
if( buf[i] == 0x0a && i + 1 < buf.length ) {
if( buf[i + 1] == 0x0a ) {
i += 2;
break;
}
if( buf[i + 1] == 0x0d
&& i + 2 < buf.length && buf[i + 2] == 0x0a ) {
i += 3;
break;
}
boolean inheader = false;
for( int j = i + 1; j < buf.length; j++ ) {
if( buf[j] == 0x0a ) {
break;
}
//if(buf[j]==0x0d) break;
if( buf[j] == ':' ) {
inheader = true;
break;
}
}
if( !inheader ) {
i++;
encrypted = false; // no passphrase
break;
}
}
i++;
}
if( type == null ) {
throw new JSchException("invalid privatekey: " + prvkey);
}
int start = i;
while( i < len ) {
if( buf[i] == 0x0a ) {
boolean xd = (buf[i - 1] == 0x0d);
System.arraycopy(buf, i + 1,
buf,
i - (xd ? 1 : 0),
len - i - 1 - (xd ? 1 : 0));
if( xd ) {
len--;
}
len--;
continue;
}
if( buf[i] == '-' ) {
break;
}
i++;
}
data = Util.fromBase64(buf, start, i - start);
if( data.length > 4 && // FSecure
data[0] == (byte) 0x3f
&& data[1] == (byte) 0x6f
&& data[2] == (byte) 0xf9
&& data[3] == (byte) 0xeb ) {
Buffer _buf = new Buffer(data);
_buf.getInt(); // 0x3f6ff9be
_buf.getInt();
@SuppressWarnings("unused")
byte[] _type = _buf.getString();
byte[] _cipher = _buf.getString();
String cipher = Util.byte2str(_cipher);
if( cipher.equals("3des-cbc") ) {
_buf.getInt();
byte[] foo = new byte[data.length - _buf.getOffSet()];
_buf.getBytes(foo);
data = foo;
encrypted = true;
throw new JSchException("unknown privatekey format: " + prvkey);
} else if( cipher.equals("none") ) {
_buf.getInt();
_buf.getInt();
encrypted = false;
byte[] foo = new byte[data.length - _buf.getOffSet()];
_buf.getBytes(foo);
data = foo;
}
}
if( pubkey != null ) {
try {
fc = new FileInputStream(pubkey).getChannel();
len = (int) fc.size();
fc.read(ByteBuffer.wrap(buf = new byte[len]));
fc.close();
if( buf.length > 4 && // FSecure's public key
buf[0] == '-' && buf[1] == '-' && buf[2] == '-' && buf[3] == '-' ) {
boolean valid = true;
i = 0;
do {
i++;
} while( buf.length > i && buf[i] != 0x0a );
if( buf.length <= i ) {
valid = false;
}
while( valid ) {
if( buf[i] == 0x0a ) {
boolean inheader = false;
for( int j = i + 1; j < buf.length; j++ ) {
if( buf[j] == 0x0a ) {
break;
}
if( buf[j] == ':' ) {
inheader = true;
break;
}
}
if( !inheader ) {
i++;
break;
}
}
i++;
}
if( buf.length <= i ) {
valid = false;
}
start = i;
while( valid && i < len ) {
if( buf[i] == 0x0a ) {
System.arraycopy(buf, i + 1, buf, i, len - i - 1);
len--;
continue;
}
if( buf[i] == '-' ) {
break;
}
i++;
}
if( valid ) {
publickeyblob = Util.fromBase64(buf, start, i - start);
if( type == KeyType.UNKNOWN ) {
if( publickeyblob[8] == 'd' ) {
type = KeyType.SSH_DSS;
} else if( publickeyblob[8] == 'r' ) {
type = KeyType.SSH_RSA;
}
}
}
} else {
if( buf[0] == 's' && buf[1] == 's' && buf[2] == 'h' && buf[3] == '-' ) {
i = 0;
while( i < len ) {
if( buf[i] == ' ' ) {
break;
}
i++;
}
i++;
if( i < len ) {
start = i;
while( i < len ) {
if( buf[i] == ' ' ) {
break;
}
i++;
}
publickeyblob = Util.fromBase64(buf, start, i - start);
}
}
}
} catch(Exception ee) {
// TODO Error handling???
}
}
} catch(JSchException e) {
throw e;
} catch(Exception e) {
throw new JSchException("Failed to load KeyPair: "+e, e);
}
KeyPair keyPair = null;
switch( type ) {
case SSH_DSS: keyPair = new KeyPairDSA(); break;
case SSH_RSA: keyPair = new KeyPairRSA(); break;
default: throw new JSchException("Unsupported key type: "+type);
}
keyPair._encrypted = encrypted;
keyPair._publicKeyBlob = publickeyblob;
keyPair._vendor = vendor;
if( encrypted ) {
keyPair._iv = iv;
keyPair._data = data;
} else if( !keyPair.parse(data) ) {
throw new JSchException("Invalid private key: " + prvkey);
}
return keyPair;
}