📄 secure.java
字号:
data.incrementPosition(length);
for(int i = 0; i < buf.length; i++){
buf[i] = (byte) (buf[i] & 0xFF);
}
ByteArrayInputStream bIn = new ByteArrayInputStream(buf);
X509Certificate cert = null;
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X.509");
cert = (X509Certificate)cf.generateCertificate(bIn);
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bIn.reset();
return cert;
}
*/
public void generateRandom() {
/*try{
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.nextBytes(this.client_random);
} catch(NoSuchAlgorithmException e){logger.warn("No Such Random Algorithm");}*/
}
public void RSAEncrypt(int length) throws RdesktopException {
byte[] inr = new byte[length];
//int outlength = 0;
BigInteger mod = null;
BigInteger exp = null;
BigInteger x = null;
this.reverse(this.exponent);
this.reverse(this.modulus);
System.arraycopy(this.client_random, 0, inr, 0, length);
this.reverse(inr);
if ((this.modulus[0] & 0x80) != 0) {
byte[] temp = new byte [this.modulus.length+1];
System.arraycopy(this.modulus, 0, temp, 1, this.modulus.length);
temp[0]=0;
mod = new BigInteger(temp);
} else {
mod = new BigInteger(this.modulus);
}
if ((this.exponent[0] & 0x80) != 0) {
byte[] temp = new byte [this.exponent.length+1];
System.arraycopy(this.exponent, 0, temp, 1, this.exponent.length);
temp[0]=0;
exp = new BigInteger(temp);
} else {
exp = new BigInteger(this.exponent);
}
if ((inr[0] & 0x80) != 0) {
byte[] temp = new byte [inr.length+1];
System.arraycopy(inr, 0, temp, 1, inr.length);
temp[0]=0;
x = new BigInteger(temp);
} else {
x = new BigInteger(inr);
}
BigInteger y = x.modPow(exp, mod);
this.sec_crypted_random = y.toByteArray();
if ((this.sec_crypted_random[0] & 0x80) != 0) {
throw new RdesktopException("Wrong Sign! Expected positive Integer!");
}
if (this.sec_crypted_random.length > SEC_MODULUS_SIZE) {
logger.warn("sec_crypted_random too big!"); /* FIXME */
}
this.reverse(this.sec_crypted_random);
byte[] temp = new byte[SEC_MODULUS_SIZE];
if (this.sec_crypted_random.length < SEC_MODULUS_SIZE) {
System.arraycopy(this.sec_crypted_random, 0, temp, 0, this.sec_crypted_random.length);
for (int i = this.sec_crypted_random.length; i < temp.length; i++) {
temp[i] = 0;
}
this.sec_crypted_random = temp;
}
}
/**
* Read in a public key from a provided Secure layer PDU, and store
* in this.exponent and this.modulus
* @param data Secure layer PDU containing key data
* @return True if key successfully read
* @throws RdesktopException
*/
public boolean parsePublicKey(RdpPacket_Localised data) throws RdesktopException {
int magic=0, modulus_length=0;
magic = data.getLittleEndian32();
if (magic != SEC_RSA_MAGIC) {
throw new RdesktopException("Wrong magic! Expected" + SEC_RSA_MAGIC + "got:" + magic);
}
modulus_length = data.getLittleEndian32();
if (modulus_length != SEC_MODULUS_SIZE + SEC_PADDING_SIZE) {
throw new RdesktopException("Wrong modulus size! Expected" + SEC_MODULUS_SIZE + "+" + SEC_PADDING_SIZE + "got:" + modulus_length);
}
data.incrementPosition(8); //unknown modulus bits
this.exponent = new byte[SEC_EXPONENT_SIZE];
data.copyToByteArray(this.exponent, 0, data.getPosition(), SEC_EXPONENT_SIZE);
data.incrementPosition(SEC_EXPONENT_SIZE);
this.modulus = new byte[SEC_MODULUS_SIZE];
data.copyToByteArray(this.modulus, 0, data.getPosition(), SEC_MODULUS_SIZE);
data.incrementPosition(SEC_MODULUS_SIZE);
data.incrementPosition(SEC_PADDING_SIZE);
if (data.getPosition() <= data.getEnd()) {
return true;
} else {
return false;
}
}
/**
* Reverse the values in the provided array
* @param data Array as passed reversed on return
*/
public void reverse(byte[] data) {
int i=0, j=0;
byte temp = 0;
for(i=0, j=data.length-1; i < j; i++, j--) {
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
public void reverse(byte[] data, int length) {
int i=0, j=0;
byte temp = 0;
for(i=0, j=length-1; i < j; i++, j--) {
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
public byte[] hash48(byte[] in, byte[] salt1, byte[] salt2, int salt)throws CryptoException {
byte[] shasig = new byte[20];
byte[] pad = new byte[4];
byte[] out = new byte[48];
int i = 0;
for(i=0; i< 3; i++) {
for(int j=0; j <=i; j++) {
pad[j]=(byte)(salt+i);
}
sha1.engineUpdate(pad, 0, i + 1);
sha1.engineUpdate(in, 0, 48);
sha1.engineUpdate(salt1, 0, 32);
sha1.engineUpdate(salt2, 0, 32);
shasig = sha1.engineDigest();
sha1.engineReset();
md5.engineUpdate(in, 0, 48);
md5.engineUpdate(shasig, 0, 20);
System.arraycopy(md5.engineDigest(), 0, out, i*16, 16);
}
return out;
}
public byte[] hash16(byte[] in, byte[] salt1, byte[] salt2, int in_position) throws CryptoException {
md5.engineUpdate(in, in_position, 16);
md5.engineUpdate(salt1, 0, 32);
md5.engineUpdate(salt2, 0, 32);
return md5.engineDigest();
}
/**
* Generate a 40-bit key and store in the parameter key.
* @param key
*/
public void make40bit(byte[] key) {
key[0] = (byte)0xd1;
key[1] = (byte)0x26;
key[2] = (byte)0x9e;
}
/**
*
* @param key
* @param update_key
* @return
* @throws CryptoException
*/
public byte[] update(byte[] key, byte[] update_key) throws CryptoException {
byte[] shasig = new byte[20];
byte[] update = new byte[this.keylength]; // changed from 8 - rdesktop 1.2.0
byte[] thekey = new byte[key.length];
sha1.engineReset();
sha1.engineUpdate(update_key, 0, keylength);
sha1.engineUpdate(pad_54, 0, 40);
sha1.engineUpdate(key,0 , keylength); // changed from 8 - rdesktop 1.2.0
shasig = sha1.engineDigest();
sha1.engineReset();
md5.engineReset();
md5.engineUpdate(update_key,0 ,keylength); // changed from 8 - rdesktop 1.2.0
md5.engineUpdate(pad_92, 0, 48);
md5.engineUpdate(shasig, 0, 20);
thekey = md5.engineDigest();
md5.engineReset();
System.arraycopy(thekey, 0, update, 0, this.keylength);
rc4_update.engineInitDecrypt(update);
// added
thekey = rc4_update.crypt(thekey, 0, this.keylength);
if( this.keylength == 8) {
this.make40bit(thekey);
}
return thekey;
}
/**
* Write a 32-bit integer value to an array of bytes, length 4
* @param data Modified by method to be a 4-byte array representing the parameter value
* @param value Integer value to return as a little-endian 32-bit value
*/
public void setLittleEndian32(byte[] data, int value) {
data[3] = (byte)((value >>> 24) & 0xff);
data[2] = (byte)((value >>> 16) & 0xff);
data[1] = (byte)((value >>> 8) & 0xff);
data[0] = (byte)(value & 0xff);
}
/**
* Receive a Secure layer PDU from the MCS layer
*
* @return Packet representing received Secure PDU
* @throws RdesktopException
* @throws IOException
* @throws CryptoException
* @throws OrderException
*/
public RdpPacket_Localised receive() throws RdesktopException, IOException, CryptoException, OrderException {
int sec_flags=0;
RdpPacket_Localised buffer=null;
while(true) {
int[] channel = new int[1];
buffer=McsLayer.receive(channel);
if(buffer==null) return null;
buffer.setHeader(RdpPacket_Localised.SECURE_HEADER);
if (Constants.encryption || (! this.licenceIssued)) {
sec_flags=buffer.getLittleEndian32();
if ((sec_flags & SEC_LICENCE_NEG) != 0) {
licence.process(buffer);
continue;
}
if ((sec_flags & SEC_ENCRYPT) != 0) {
buffer.incrementPosition(8); //signature
byte[] data = new byte[buffer.size() - buffer.getPosition()];
buffer.copyToByteArray(data, 0, buffer.getPosition(), data.length);
byte[] packet = this.decrypt(data);
buffer.copyFromByteArray(packet, 0, buffer.getPosition(), packet.length);
//buffer.setStart(buffer.getPosition());
//return buffer;
}
}
if (channel[0] != MCS.MCS_GLOBAL_CHANNEL)
{
channels.channel_process(buffer, channel[0]);
continue;
}
buffer.setStart(buffer.getPosition());
return buffer;
}
}
/**
* Generate encryption keys of applicable size for connection
* @param rc4_key_size Size of keys to generate (1 if 40-bit encryption, otherwise 128-bit)
* @throws CryptoException
*/
public void generate_keys(int rc4_key_size) throws CryptoException {
byte[] session_key = new byte[48];
byte[] temp_hash = new byte[48];
byte[] input = new byte[48];
System.arraycopy(this.client_random, 0, input, 0, 24);
System.arraycopy(this.server_random, 0, input, 24, 24);
temp_hash = this.hash48(input, this.client_random, this.server_random, 65);
session_key = this.hash48(temp_hash, this.client_random, this.server_random, 88);
System.arraycopy(session_key, 0, this.sec_sign_key, 0, 16); // changed from 8 - rdesktop 1.2.0
this.sec_decrypt_key = this.hash16(session_key, this.client_random, this.server_random, 16);
this.sec_encrypt_key = this.hash16(session_key, this.client_random, this.server_random, 32);
if (rc4_key_size == 1) {
logger.info("40 Bit Encryption enabled");
this.make40bit(this.sec_sign_key);
this.make40bit(this.sec_decrypt_key);
this.make40bit(this.sec_encrypt_key);
this.keylength = 8;
} else {
logger.info("128 Bit Encryption enabled");
this.keylength = 16;
}
System.arraycopy(this.sec_decrypt_key, 0, this.sec_decrypt_update_key, 0, 16); // changed from 8 - rdesktop 1.2.0
System.arraycopy(this.sec_encrypt_key, 0, this.sec_encrypt_update_key, 0, 16); // changed from 8 - rdesktop 1.2.0
byte[] key = new byte[this.keylength];
System.arraycopy(this.sec_encrypt_key, 0, key, 0, this.keylength);
rc4_enc.engineInitEncrypt(key);
System.arraycopy(this.sec_decrypt_key, 0, key, 0, this.keylength);
rc4_dec.engineInitDecrypt(key);
}
/**
* @return MCS user ID
*/
public int getUserID() {
return McsLayer.getUserID();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -