shadowsocks协议早期使用RC4加密算法用于加密数据,不过因为每次数据都适用同一个密钥流加密,存在很大的安全隐患,后面更新了RC4-MD5算法。
即便关于RC4-MD5协议的资料很难找到,而且RC4-MD5算法现在也不在安全,但还是有必要介绍一遍,因为它简单,很便于理解,在后期也会展示RC4算法的缺陷。
RC4-MD5本质上还是RC4对数据进行加密。MD5的意思是对key进行MD5运算,得到RC4的key,最终会被RC4算法用于生成密钥流。简单来说,用户的密码会经过下面步骤转换为RC4的keystream
- k1 = toBytes(password)
- k2 = ssKey(k1)
- rc4-md5-key = md5(toBytes(k2,iv))
上面步骤中,第一步把用户输入的密码转换为字节数组,第二步通过ss函数生成通用的ssKey,第三步生成RC4-MD5算法所需的key,过程就是把sskey和一个随机iv按顺序放到一个字节数组,在使用md5进行运算,得到一个最终的结果,这个Key就是RC4算法将要使用的Key。
sskey的生成算法如下
private static byte[] generateSSKey(String password) {
byte[] keys = new byte[32];
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
byte[] hash = Hash.md5(bytes);
byte[] tmp = new byte[bytes.length + hash.length];
System.arraycopy(hash, 0, keys, 0, hash.length);
for (int i=hash.length;i<keys.length;i+=hash.length) {
System.arraycopy(hash, 0, tmp, 0, hash.length);
System.arraycopy(bytes, 0, tmp, hash.length, bytes.length);
hash = Hash.md5(tmp);
System.arraycopy(hash, 0, keys, i, hash.length);
}
return keys;
}
rc4-md5-key生成算法如下
public static byte[] rc4md5Key(String password,byte[] iv) {
byte[] ssKeys = generateSSKey(password);
byte[] keys = new byte[ssKeys.length + iv.length];
System.arraycopy(ssKeys,0,keys,0,ssKeys.length);
System.arraycopy(iv,0,keys,ssKeys.length,iv.length);
return Hash.md5(keys);
}
当我们得到Key后,就可以使用它来对数据进行加密
public byte[] encrypt(byte[] keys,byte[] plaintext) throw Exception{
Cipher encoder = Cipher.getInstance("RC4");
encoder.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keys, "RC4"));
return encoder.update(content.getBytes());
}
当我们得到密文后,还需要把IV传给ss-server,ss-server会使用同样的算法计算出rc4-md5-key,从而对数据进行解密,组装方式如下:
public void combine() {
String plaintext = "123456";
String password = "654321";
byte[] iv = randomIV();
byte[] key = rc4md5Key(password,iv);
byte[] ciphertext = encrypt(key,plaintext.getBytes());
ByteArrayOutputStream os = new ByteArrayOutputStream(key.length + ciphertext.length);
os.writeBytes(key);
os.writeBytes(ciphertext);
byte[] data = os.toByteArray();
}
最终我们得到的data就是需要发送给服务端的数据。
虽然RC4-MD5算法早就可以被识别了,不过它足够简单,可以帮助我们理解为什么流加密很脆弱,作为一种入门的算法是不二之选。后续的文章将会继续介绍RC4算法的原理,以及对它的攻击方式。
PREVIOUSEIP55-以太坊账户地址校验算法