密码学:将C函数转换为python

时间:2016-09-15 16:20:58

标签: python c cryptography

我正在尝试解决加密问题(https://callicode.fr/pydefis/Reverse/txt),算法使用以下C函数(F1)。 我不知道C,我试图将它转换为python(F2)但没有成功。提前谢谢你让我知道我做错了什么。

F1:

void Encrypt(unsigned char key[20], unsigned char *pPlainBuffer, unsigned char *pCipherBuffer, unsigned int nLength) 
{
int nKeyPos = 0;
unsigned int n;
unsigned char KeyA = 0;

if ((pPlainBuffer != NULL) && (pCipherBuffer != NULL)) {
for (n = 0; n < 20; n++) 
  KeyA ^= key[n];
  nKeyPos = KeyA % 20;
for (n = 0; n < nLength; n++) {
  pCipherBuffer[n] = pPlainBuffer[n]^(key[nKeyPos]*KeyA);
  KeyA += pCipherBuffer[n];
  nKeyPos = pCipherBuffer[n] % 20;
}
 }
}

F2:

def Encrypt(plainText, key):  # plainText is a list of hexadecimals representing ascii 
                              # characters, key is a list of int size 20  each int 
                              # beetween 0 and 255
    keyA = 0

    for n in range(20):
        keyA ^= key[n]

    nKeyPos = KeyA % 20

    for n in range(len(plainText)):
         codedText[n] = plainText[n]^(key[nKeyPos]*KeyA)
         keyA += codedText[n]
         nKeyPos = codedText[n] % 20

2 个答案:

答案 0 :(得分:1)

这是一个小小的工作示例:

def Encrypt(key, pPlainBuffer):
    nKeyPos = 0
    KeyA = 0

    if pPlainBuffer is not None:
        pCipherBuffer = []
        for n in range(20):
            KeyA = KeyA ^ key[n]
        nKeyPos = KeyA % 20

        for n in range(len(pPlainBuffer)):
            pCipherBuffer.append(pPlainBuffer[n] ^ (key[nKeyPos] * KeyA))
            KeyA += pCipherBuffer[n]
            nKeyPos = pCipherBuffer[n] % 20

        return pCipherBuffer


def Decrypt(key, pCipherBuffer):
    nKeyPos = 0
    KeyA = 0

    if pCipherBuffer is not None:
        pPlainBuffer = []
        for n in range(20):
            KeyA ^= key[n]
        nKeyPos = KeyA % 20

        for n in range(len(pCipherBuffer)):
            pPlainBuffer.append(pCipherBuffer[n] ^ (key[nKeyPos] * KeyA))
            KeyA += pCipherBuffer[n]
            nKeyPos = pCipherBuffer[n] % 20

        return pPlainBuffer

if __name__ == "__main__":
    import random

    key = [random.randint(0, 255) for k in range(20)]

    pPlainBuffer = [ord(c) for c in "this is the unencrypted message"]
    a = Encrypt(key, pPlainBuffer)
    b = Decrypt(key, a)

    print("-"*80)
    print("Encrypted message")
    print("-"*80)
    print(":".join("{:02x}".format(c) for c in a))
    print("-"*80)
    print("Decrypted message")
    print("-"*80)
    print("".join([chr(c) for c in b]))

    # --------------------------------------------------------------------------------
    # Encrypted message
    # --------------------------------------------------------------------------------
    # 1ba:2678:197df9:bec4844:2d163e70c:1d01cf925ab:45512ab14a9b:4724251445d50:550934523b78ca:1f34a7cfbb7db6a1:1bfb485c731bcdb713:161112a22402868312ad:b1696bc757013314e2975:531cf11bdcc471dc32befef:a2627edf4f99a01240ba016f:839c3758163127edc2e955cc63:100437038699e709cce258a3ed1b:6c7fa638eaa735df4ae48a03e32a9:58911d1d6ea1c00863052f0fa160a0d:2c7f52a5aa98fec79d57f011bf256acf0:22559e3d644a5d56f620427531855711f90:81693c9711311b3cfe601f0f44c5ec6c8eb9:6a628fdbfce204d77db6eb221a161b683dee6a:c86f7e57fa208eaff7fbe01b26048cae230f1a8:308b00994e93e28e9e0f004693351a122c7da861d:2bc2e905f06bc052ef96e3dd7d68389e9df11483546:9717a6cd2ce3ac9b8757110bab10b835b11adda93df2:12072f89ef89b60cbd3d4c3735dda19daddbeecfd47b5d:1084c8b9afea8c4ece5432ef4130712f4f9a5a403acac323:27679b285784a6a9f1d42189acfc9433655c776e5ce16d191:1c6f807e0f27d47ad8ee72ba6740cb5dee4d918da413efe2f6d
    # --------------------------------------------------------------------------------
    # Decrypted message
    # --------------------------------------------------------------------------------
    # --------------------------------------------------------------------------------
    # this is the unencrypted message

这几乎是1:1 c ++重写版本,但如果你想要一个更加pythonic的版本:

def encrypt(key, plain_buffer):
    key_pos = 0
    key_a = 0

    cipher_buffer = []

    if plain_buffer is not None:
        for k in key:
            key_a = key_a ^ k
        key_pos = key_a % 20

        for n, d in enumerate(plain_buffer):
            cipher_buffer.append(d ^ (key[key_pos] * key_a))
            key_a += cipher_buffer[n]
            key_pos = cipher_buffer[n] % 20

    return cipher_buffer


def decrypt(key, cipher_buffer):
    key_pos = 0
    key_a = 0

    plain_buffer = []

    if cipher_buffer is not None:
        for k in key:
            key_a ^= k
        key_pos = key_a % 20

        for n, d in enumerate(cipher_buffer):
            plain_buffer.append(d ^ (key[key_pos] * key_a))
            key_a += cipher_buffer[n]
            key_pos = cipher_buffer[n] % 20

    return plain_buffer

if __name__ == "__main__":
    import random
    random.seed(1)

    key = [random.randint(0, 255) for k in range(20)]

    plain_buffer = [ord(c) for c in "this is the unencrypted message"]
    a = encrypt(key, plain_buffer)
    b = decrypt(key, a)

    print("-" * 80)
    print("Encrypted message")
    print("-" * 80)
    print(":".join("{:02x}".format(c) for c in a))
    print("-" * 80)
    print("Decrypted message")
    print("-" * 80)
    print("".join([chr(c) for c in b]))

虽然没有使用未签名的字符,但这就是加密消息看起来那么大的原因。

答案 1 :(得分:1)

你有很多问题......最明显的是python整数默认不限制为字节宽度,因此你必须明确设置宽度

另外你必须把字母转换成python中的数字,因为它们是根本不同的东西(用C / c ++字母实际上只是数字)

def Encrypt(plainText, key):  # plainText is a list of hexadecimals representing ascii 
                              # characters, key is a list of int size 20  each int                                   # beetween 0 and 255
    keyA = 0    
    for letter in key:
        keyA ^= ord(letter) # conver letter to number    
    keyA = keyA & 0xFF # fix width to one byte
    key = itertools.cycle(key) # repeate forever
    codedText = ""
    for letter,keyCode in zip(plainText,key):
         xorVal = (ord(keyCode) * keyA) & 0xFF # make one byte wide
         newLetter = chr((ord(letter) ^ xorVal )&0xFF) # make one byte wide

         codedText += newLetter
         keyA += ord(newLetter)
         keyA = keyA&0xFF # keep it one byte wide