📄 secure.java
字号:
buffer.incrementPosition(SEC_MODULUS_SIZE);
buffer.incrementPosition(SEC_PADDING_SIZE);
buffer.markEnd();
this.send(buffer, flags);
}
public void processCryptInfo(RdpPacket_Localised data) throws RdesktopException, CryptoException {
int rc4_key_size=0;
rc4_key_size = this.parseCryptInfo(data);
if (rc4_key_size == 0) {
return;
}
//this.client_random = this.generateRandom(SEC_RANDOM_SIZE);
logger.debug("readCert = " + readCert);
if (readCert)
{ /* Which means we should use
RDP5-style encryption */
// *** reverse the client random
//this.reverse(this.client_random);
// *** load the server public key into the stored data for encryption
/* this.exponent = this.server_public_key.getPublicExponent().toByteArray();
this.modulus = this.server_public_key.getModulus().toByteArray();
System.out.println("Exponent: " + server_public_key.getPublicExponent());
System.out.println("Modulus: " + server_public_key.getModulus());
*/
// *** perform encryption
//this.sec_crypted_random = RSA_public_encrypt(this.client_random, this.server_public_key);
//this.RSAEncrypt(SEC_RANDOM_SIZE);
//this.RSAEncrypt(SEC_RANDOM_SIZE);
// *** reverse the random data back
//this.reverse(this.sec_crypted_random);
}
else{
this.generateRandom();
this.RSAEncrypt(SEC_RANDOM_SIZE);
}
this.generate_keys(rc4_key_size);
}
/**
* Intialise a packet at the Secure layer
* @param flags Encryption flags
* @param length Length of packet
* @return Intialised packet
* @throws RdesktopException
*/
public RdpPacket_Localised init(int flags, int length) throws RdesktopException {
int headerlength=0;
RdpPacket_Localised buffer;
if (!this.licenceIssued)
headerlength = ((flags & SEC_ENCRYPT)!=0) ? 12 : 4;
else
headerlength = ((flags & SEC_ENCRYPT)!=0) ? 12 : 0;
buffer=McsLayer.init(length+headerlength);
buffer.pushLayer(RdpPacket_Localised.SECURE_HEADER,headerlength);
//buffer.setHeader(RdpPacket_Localised.SECURE_HEADER);
//buffer.incrementPosition(headerlength);
//buffer.setStart(buffer.getPosition());
return buffer;
}
/**
* Send secure data on the global channel
* @param sec_data Data to send
* @param flags Encryption flags
* @throws RdesktopException
* @throws IOException
* @throws CryptoException
*/
public void send(RdpPacket_Localised sec_data, int flags) throws RdesktopException, IOException, CryptoException {
send_to_channel(sec_data,flags,MCS.MCS_GLOBAL_CHANNEL);
}
/**
* Prepare data as a Secure PDU and pass down to the MCS layer
* @param sec_data Data to send
* @param flags Encryption flags
* @param channel Channel over which to send data
* @throws RdesktopException
* @throws IOException
* @throws CryptoException
*/
public void send_to_channel(RdpPacket_Localised sec_data, int flags, int channel) throws RdesktopException, IOException, CryptoException {
int datalength=0;
byte[] signature = null;
byte[] data;
byte[] buffer;
sec_data.setPosition(sec_data.getHeader(RdpPacket_Localised.SECURE_HEADER));
if (this.licenceIssued == false || (flags & SEC_ENCRYPT) !=0) {
sec_data.setLittleEndian32(flags);
}
if ((flags & SEC_ENCRYPT) !=0) {
flags &= ~SEC_ENCRYPT;
datalength = sec_data.getEnd() - sec_data.getPosition() - 8;
data = new byte[datalength];
buffer = null;
sec_data.copyToByteArray(data, 0, sec_data.getPosition()+8, datalength);
signature = this.sign(this.sec_sign_key, 8, this.keylength, data, datalength);
buffer = this.encrypt(data, datalength);
sec_data.copyFromByteArray(signature, 0, sec_data.getPosition(), 8);
sec_data.copyFromByteArray(buffer, 0, sec_data.getPosition()+8, datalength);
}
//McsLayer.send(sec_data);
McsLayer.send_to_channel(sec_data,channel);
}
/**
* Generate MD5 signature
* @param session_key Key with which to sign data
* @param length Length of signature
* @param keylen Length of key
* @param data Data to sign
* @param datalength Length of data to sign
* @return Signature for data
* @throws CryptoException
*/
public byte[] sign(byte[] session_key, int length, int keylen, byte[] data, int datalength) throws CryptoException {
byte[] shasig = new byte[20];
byte[] md5sig = new byte[16];
byte[] lenhdr = new byte[4];
byte[] signature = new byte[length];
this.setLittleEndian32(lenhdr, datalength);
sha1.engineReset();
sha1.engineUpdate(session_key, 0, keylen/*length*/);
sha1.engineUpdate(pad_54, 0, 40);
sha1.engineUpdate(lenhdr, 0, 4);
sha1.engineUpdate(data, 0, datalength);
shasig = sha1.engineDigest();
sha1.engineReset();
md5.engineReset();
md5.engineUpdate(session_key, 0, keylen/*length*/);
md5.engineUpdate(pad_92, 0, 48);
md5.engineUpdate(shasig, 0, 20);
md5sig = md5.engineDigest();
md5.engineReset();
System.arraycopy(md5sig, 0, signature, 0, length);
return signature;
}
/**
* Encrypt specified number of bytes from provided data using RC4 algorithm
* @param data Data to encrypt
* @param length Number of bytes to encrypt (from start of array)
* @return Encrypted data
* @throws CryptoException
*/
public byte[] encrypt(byte[] data, int length) throws CryptoException {
byte[] buffer = null;
if (this.enc_count==4096) {
sec_encrypt_key = this.update(this.sec_encrypt_key, this.sec_encrypt_update_key);
byte[] key = new byte[this.keylength];
System.arraycopy(this.sec_encrypt_key, 0, key, 0, this.keylength);
this.rc4_enc.engineInitEncrypt(key);
// logger.debug("Packet enc_count="+enc_count);
this.enc_count=0;
}
//this.rc4.engineInitEncrypt(this.rc4_encrypt_key);
buffer = this.rc4_enc.crypt(data, 0, length);
this.enc_count++;
return buffer;
}
/**
* Encrypt provided data using the RC4 algorithm
* @param data Data to encrypt
* @return Encrypted data
* @throws CryptoException
*/
public byte[] encrypt(byte[] data) throws CryptoException {
byte[] buffer = null;
if (this.enc_count==4096) {
sec_encrypt_key = this.update(this.sec_encrypt_key, this.sec_encrypt_update_key);
byte[] key = new byte[this.keylength];
System.arraycopy(this.sec_encrypt_key, 0, key, 0, this.keylength);
this.rc4_enc.engineInitEncrypt(key);
// logger.debug("Packet enc_count="+enc_count);
this.enc_count=0;
}
// this.rc4.engineInitEncrypt(this.rc4_encrypt_key);
buffer = this.rc4_enc.crypt(data);
this.enc_count++;
return buffer;
}
/**
* Decrypt specified number of bytes from provided data using RC4 algorithm
* @param data Data to decrypt
* @param length Number of bytes to decrypt (from start of array)
* @return Decrypted data
* @throws CryptoException
*/
public byte[] decrypt(byte[] data, int length) throws CryptoException {
byte[] buffer = null;
if (this.dec_count==4096) {
sec_decrypt_key = this.update(this.sec_decrypt_key, this.sec_decrypt_update_key);
byte[] key = new byte[this.keylength];
System.arraycopy(this.sec_decrypt_key, 0, key, 0, this.keylength);
this.rc4_dec.engineInitDecrypt(key);
// logger.debug("Packet dec_count="+dec_count);
this.dec_count=0;
}
//this.rc4.engineInitDecrypt(this.rc4_decrypt_key);
buffer = this.rc4_dec.crypt(data, 0, length);
this.dec_count++;
return buffer;
}
/**
* Decrypt provided data using RC4 algorithm
* @param data Data to decrypt
* @return Decrypted data
* @throws CryptoException
*/
public byte[] decrypt(byte[] data) throws CryptoException {
byte[] buffer = null;
if (this.dec_count==4096) {
sec_decrypt_key = this.update(this.sec_decrypt_key, this.sec_decrypt_update_key);
byte[] key = new byte[this.keylength];
System.arraycopy(this.sec_decrypt_key, 0, key, 0, this.keylength);
this.rc4_dec.engineInitDecrypt(key);
// logger.debug("Packet dec_count="+dec_count);
this.dec_count=0;
}
//this.rc4.engineInitDecrypt(this.rc4_decrypt_key);
buffer = this.rc4_dec.crypt(data);
this.dec_count++;
return buffer;
}
/**
* Read encryption information from a Secure layer PDU, obtaining and storing
* level of encryption and any keys received
* @param data Packet to read encryption information from
* @return Size of RC4 key
* @throws RdesktopException
*/
public int parseCryptInfo(RdpPacket_Localised data) throws RdesktopException {
logger.debug("Secure.parseCryptInfo");
int encryption_level=0, random_length=0, RSA_info_length=0;
int tag=0, length=0;
int next_tag=0, end=0;
int rc4_key_size=0;
rc4_key_size = data.getLittleEndian32(); // 1 = 40-Bit 2 = 128 Bit
encryption_level = data.getLittleEndian32(); // 1 = low, 2 = medium, 3 = high
if (encryption_level==0) { // no encryption
return 0;
}
random_length = data.getLittleEndian32();
RSA_info_length = data.getLittleEndian32();
if ( random_length != SEC_RANDOM_SIZE) {
throw new RdesktopException("Wrong Size of Random! Got" + random_length + "expected" + SEC_RANDOM_SIZE);
}
this.server_random = new byte[random_length];
data.copyToByteArray(this.server_random, 0, data.getPosition(), random_length);
data.incrementPosition(random_length);
end = data.getPosition() + RSA_info_length;
if (end > data.getEnd()) {
logger.debug("Reached end of crypt info prematurely ");
return 0;
}
//data.incrementPosition(12); // unknown bytes
int flags = data.getLittleEndian32(); // in_uint32_le(s, flags); // 1 = RDP4-style, 0x80000002 = X.509
logger.debug("Flags = 0x" + Integer.toHexString(flags));
if ((flags & 1) != 0)
{
logger.debug(("We're going for the RDP4-style encryption"));
data.incrementPosition(8); //in_uint8s(s, 8); // unknown
while (data.getPosition() < data.getEnd()) {
tag=data.getLittleEndian16();
length=data.getLittleEndian16();
next_tag = data.getPosition() + length;
switch (tag) {
case (Secure.SEC_TAG_PUBKEY):
if (!parsePublicKey(data)) {
return 0;
}
break;
case (Secure.SEC_TAG_KEYSIG):
// Microsoft issued a key but we don't care
break;
default:
throw new RdesktopException("Unimplemented decrypt tag "+tag);
}
data.setPosition(next_tag);
}
if (data.getPosition() == data.getEnd()) {
return rc4_key_size;
} else {
logger.warn("End not reached!");
return 0;
}
}else{
//data.incrementPosition(4); // number of certificates
int num_certs = data.getLittleEndian32();
int cacert_len = data.getLittleEndian32();
data.incrementPosition(cacert_len);
int cert_len = data.getLittleEndian32();
data.incrementPosition(cert_len);
readCert = true;
return rc4_key_size;
}
}
/*
public X509Certificate readCert(int length, RdpPacket_Localised data){
byte[] buf = new byte[length];
data.copyToByteArray(buf,0,data.getPosition(),buf.length);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -