Introduction
After around patch 5174, Conquer Online implemented a pseudo-randomized seed for RC5 using MsgEncryptCode, and some type of substitution cipher for passwords. It bothered me that I knew anything about this "password cipher", besides how horribly programmed the logic was in every public source. I looked into it, and found that the substitutions were from keyboard scan codes to ASCII, and to make it that much more difficult, the keyboard scan codes aren't from a US keyboard.
So, what I did is I made my own scan codes based on input permitted by the client. Definitely not promising that this works for all input, as I've only tested the input I have access to on a US keyboard, but it does allow for the numpad and special characters (unlike current implementations). Use it if you want, and at your own risk.
Code
Code:
/// ScanCodeCipher is a simple substitution cipher that maps client key
/// scan codes to ASCII characters based on the user's account name, which
/// acts as a randomizer for substitution. The key map was created by me
/// just for the Conquer Online client since it doesn't use a traditional
/// US keyboard's scan code map. Don't use it for anything else.
public class ScanCodeCipher : ICipher {
private readonly byte[] _key = new byte[0x200];
private static readonly byte[] _codes = {
0x00, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x30, 0x2D, 0x00, 0x00, 0x00,
0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
0x6F, 0x70, 0x00, 0x00, 0x00, 0x00, 0x61, 0x73,
0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7A, 0x78, 0x63, 0x76,
0x62, 0x6E, 0x6D, 0x00, 0x2E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37,
0x38, 0x39, 0x00, 0x34, 0x35, 0x36, 0x00, 0x31,
0x32, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E,
0x26, 0x2A, 0x28, 0x29, 0x5F, 0x00, 0x00, 0x00,
0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49,
0x4F, 0x50, 0x00, 0x00, 0x00, 0x00, 0x41, 0x53,
0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x5A, 0x58, 0x43, 0x56,
0x42, 0x4E, 0x4D, 0x00, 0x3E
};
/// Constructor using the account checksum as seed.
public ScanCodeCipher(string account) {
int checksum = 0;
foreach (byte c in account)
checksum += c;
// Pseudo-Randomize using C's rand function.
byte[] buf = new byte[16];
for (int i = 0; i < buf.Length; i++) {
checksum = checksum * 0x343fd + 0x269ec3;
buf[i] = (byte)((checksum >> 0x10) & 0x7fff);
}
GenerateKeys(buf);
}
/// Generates key mappings based on the player's account name.
public void GenerateKeys(params object[] keys) {
var buf = keys[0] as byte[];
for (int i = 1; i < 0x100; i++) {
_key[i * 2] = (byte)i;
_key[(i * 2) + 1] = (byte)(i ^ buf[i & 15]);
}
for (int k = 1; k < 0x100; k++) {
for (int m = k + 1; m < 0x100; m++) {
int a = m * 2, b = k * 2;
if (_key[b + 1] < _key[a + 1]) {
_key[b] = (byte)(_key[b] ^ _key[a]);
_key[a] = (byte)(_key[a] ^ _key[b]);
_key[b] = (byte)(_key[b] ^ _key[a]);
_key[b + 1] = (byte)(_key[b + 1] ^ _key[a + 1]);
_key[a + 1] = (byte)(_key[a + 1] ^ _key[b + 1]);
_key[b + 1] = (byte)(_key[b + 1] ^ _key[a + 1]);
}
}
}
}
/// Decrypt maps the randomized scan codes to ASCII characters.
/// Returns the plaintext password, assuming that the RC5 decrypt
/// method has been called before this.
public void Decrypt(byte[] src, int s, byte[] dst, int d, int l) {
for (int i = 0; i < l; i++) {
if (src[i + s] == 0) {
for (int j = i; j < l; j++) dst[j] = 0;
return;
}
dst[i + d] = _codes[(byte)(_key[src[i + s] * 2])];
}
}
/// Encrypt is implemented by the client.
public void Encrypt(byte[] src, int s, byte[] dst, int d, int l) {
throw new System.NotImplementedException();
}
}
PS: I didn't implement encrypt, but that would just map virtual key codes to the scan codes. Doesn't help to implement that on the server end, unless I'm overlooking something - so decrypt only it is.
The Password Cipher for Patch 5532+!! 06/30/2012 - CO2 Private Server - 3 Replies FAKE
This is 100% fake. I can't tell you how many times I've been spammed with this. I'm not trying to hide anything, I'm not trying to throw people off. The truth about this cipher is that it's not for patches 5532 and above.
namespace Conquer_Online_Server.Network.Cryptography
{
using System;
using System.Text;
public sealed class ConquerPasswordCryptpographer
[S] 50 PSC mit FOTO/SCAN [B] 55 PSC ohne SCAN/Foto 10/24/2011 - Trading - 1 Replies So ich suche 50 Euro PSC da ich mir was kaufen möchte wo man einen Screenshot benötigt. Ich habe die 55 PSC schon länger in meinem besitz und möchte tauschen.
Nur mit Treuehand (ihr organisiert) oder ihr gebt first !!
ICQ: 637-931