_keyType = KeyType.SSH_RSA;
} else if( buf[i] == 'S' && buf[i + 1] == 'S' && buf[i + 2] == 'H' ) { // FSecure
_keyType = KeyType.UNKNOWN;
_vendor = FSECURE;
} else {
throw new JSchException("invalid privatekey: " + _identity);
}
i += 3;
continue;
}
if( buf[i] == 'A' && i+7 < len && buf[i + 1] == 'E' && buf[i + 2] == 'S' && buf[i + 3] == '-'
&& buf[i + 4] == '2' && buf[i + 5] == '5' && buf[i + 6] == '6' && buf[i + 7] == '-' ) {
i += 8;
if( CipherManager.getManager().isSupported(Cipher.CIPHER_AES256_CBC) ) {
_cipher = CipherManager.getManager().createCipher(Cipher.CIPHER_AES256_CBC);
_key = new byte[_cipher.getBlockSize()];
_iv = new byte[_cipher.getIVSize()];
} else {
throw new JSchException("privatekey: aes256-cbc is not available " + _identity);
}
continue;
}
// If AES-192 encryption
if( buf[i] == 'A' && i + 7 < len && buf[i + 1] == 'E' && buf[i + 2] == 'S' && buf[i + 3] == '-'
&& buf[i + 4] == '1' && buf[i + 5] == '9' && buf[i + 6] == '2' && buf[i + 7] == '-' ) {
i += 8;
if( CipherManager.getManager().isSupported(Cipher.CIPHER_AES192_CBC) ) {
_cipher = CipherManager.getManager().createCipher(Cipher.CIPHER_AES192_CBC);
_key = new byte[_cipher.getBlockSize()];
_iv = new byte[_cipher.getIVSize()];
} else {
throw new JSchException("privatekey: aes192-cbc is not available " + _identity);
}
continue;
}
// If AES-128 encryption
if( buf[i] == 'A' && i + 7 < len && buf[i + 1] == 'E' && buf[i + 2] == 'S' && buf[i + 3] == '-'
&& buf[i + 4] == '1' && buf[i + 5] == '2' && buf[i + 6] == '8' && buf[i + 7] == '-' ) {
i += 8;
if( CipherManager.getManager().isSupported(Cipher.CIPHER_AES128_CBC) ) {
_cipher = CipherManager.getManager().createCipher(Cipher.CIPHER_AES128_CBC);
_key = new byte[_cipher.getBlockSize()];
_iv = new byte[_cipher.getIVSize()];
} else {
throw new JSchException("privatekey: aes128-cbc is not available " + _identity);
}
continue;
}
if( buf[i] == 'C' && i+3 < len && buf[i + 1] == 'B' && buf[i + 2] == 'C' && buf[i + 3] == ',' ) {
i += 4;
for( int ii = 0; ii < _iv.length; ii++ ) {
_iv[ii] = (byte) (((a2b(buf[i++]) << 4) & 0xf0) + (a2b(buf[i++]) & 0xf));
}
continue;
}
if( buf[i] == 0x0d && i + 1 < len && buf[i + 1] == 0x0a ) {
i++;
continue;
}
if( buf[i] == 0x0a && i + 1 < len ) {
if( buf[i + 1] == 0x0a ) {
i += 2;
break;
}
if( buf[i + 1] == 0x0d && i + 2 < len && buf[i + 2] == 0x0a ) {
i += 3;
break;
}
boolean inheader = false;
for( int j = i + 1; j < len; j++ ) {
if( buf[j] == 0x0a ) {
break;
}
if( buf[j] == ':' ) {
inheader = true;
break;
}
}
if( !inheader ) {
i++;
_encrypted = false; // no passphrase
break;
}
}
i++;
}
if( _keyType == null ) {
throw new JSchException("invalid privatekey: " + _identity);
}
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++;
}
_encodedData = Util.fromBase64(buf, start, i - start);
if( _encodedData.length > 4 && // FSecure
_encodedData[0] == (byte) 0x3f
&& _encodedData[1] == (byte) 0x6f
&& _encodedData[2] == (byte) 0xf9
&& _encodedData[3] == (byte) 0xeb ) {
Buffer _buf = new Buffer(_encodedData);
_buf.getInt(); // 0x3f6ff9be
_buf.getInt();
@SuppressWarnings("unused")
byte[] typeName = _buf.getString();
byte[] cipherName = _buf.getString();
String cipher = Util.byte2str(cipherName);
if( cipher.equals("3des-cbc") ) {
_buf.getInt();
byte[] foo = new byte[_encodedData.length - _buf.getOffSet()];
_buf.getBytes(foo);
_encodedData = foo;
_encrypted = true;
throw new JSchException("unknown privatekey format: " + _identity);
} else if( cipher.equals("none") ) {
_buf.getInt();
//_buf.getInt();
_encrypted = false;
byte[] foo = new byte[_encodedData.length - _buf.getOffSet()];
_buf.getBytes(foo);
_encodedData = foo;
}
}
if( pubkey == null ) {
return;
}
buf = pubkey;
len = buf.length;
if( buf.length > 4 && // FSecure's public key
buf[0] == '-' && buf[1] == '-' && buf[2] == '-' && buf[3] == '-' ) {
i = 0;
do {
i++;
} while( len > i && buf[i] != 0x0a );
if( len <= i ) {
return;
}
while( i < len ) {
if( buf[i] == 0x0a ) {
boolean inheader = false;
for( int j = i + 1; j < len; j++ ) {
if( buf[j] == 0x0a ) {
break;
}
if( buf[j] == ':' ) {
inheader = true;
break;
}
}
if( !inheader ) {
i++;
break;
}
}
i++;
}
if( len <= i ) {
return;
}
start = i;
while( i < len ) {
if( buf[i] == 0x0a ) {
System.arraycopy(buf, i + 1, buf, i, len - i - 1);
len--;
continue;
}
if( buf[i] == '-' ) {
break;
}
i++;
}
_publicKeyBlob = Util.fromBase64(buf, start, i - start);
if( _keyType == KeyType.UNKNOWN && _publicKeyBlob.length > 8 ) {
if( _publicKeyBlob[8] == 'd' ) {
_keyType = KeyType.SSH_DSS;
} else if( _publicKeyBlob[8] == 'r' ) {
_keyType = KeyType.SSH_RSA;
}
}
} else {
if( buf[0] != 's' || buf[1] != 's' || buf[2] != 'h' || buf[3] != '-' ) {
return;
}
i = 0;
while( i < len ) {
if( buf[i] == ' ' ) {
break;
}
i++;
}
i++;
if( i >= len ) {
return;
}
start = i;
while( i < len ) {
if( buf[i] == ' ' || buf[i] == '\n' ) {
break;
}
i++;
}
_publicKeyBlob = Util.fromBase64(buf, start, i - start);
if( _publicKeyBlob.length < 4 + 7 ) { // It must start with "ssh-XXX".
_publicKeyBlob = null;
}
}
} catch(JSchException e) {
throw e;
} catch(Exception e) {
throw new JSchException("Failed to create IdentityFile instance: "+e, e);
}
}