summaryrefslogtreecommitdiffstats
path: root/DeDRM_plugin/alfcrypto.py
blob: ecb79166a6c52aa42a886c6b44c05de62da9e900 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# crypto library mainly by some_updates

# pbkdf2.py pbkdf2 code taken from pbkdf2.py
# pbkdf2.py Copyright © 2004 Matt Johnston <matt @ ucc asn au>
# pbkdf2.py Copyright © 2009 Daniel Holth <[email protected]>
# pbkdf2.py This code may be freely used and modified for any purpose.

import hmac
from struct import pack
import hashlib
import aescbc

class Pukall_Cipher(object):
    def __init__(self):
        self.key = None

    def PC1(self, key, src, decryption=True):
        sum1 = 0;
        sum2 = 0;
        keyXorVal = 0;
        if len(key)!=16:
            raise Exception("PC1: Bad key length")
        wkey = []
        for i in range(8):
            wkey.append(key[i*2]<<8 | key[i*2+1])
        dst = bytearray(len(src))
        for i in range(len(src)):
            temp1 = 0;
            byteXorVal = 0;
            for j in range(8):
                temp1 ^= wkey[j]
                sum2  = (sum2+j)*20021 + sum1
                sum1  = (temp1*346)&0xFFFF
                sum2  = (sum2+sum1)&0xFFFF
                temp1 = (temp1*20021+1)&0xFFFF
                byteXorVal ^= temp1 ^ sum2
            curByte = src[i]
            if not decryption:
                keyXorVal = curByte * 257;
            curByte = ((curByte ^ (byteXorVal >> 8)) ^ byteXorVal) & 0xFF
            if decryption:
                keyXorVal = curByte * 257;
            for j in range(8):
                wkey[j] ^= keyXorVal;
            dst[i] = curByte
        return bytes(dst)

class Topaz_Cipher(object):
    def __init__(self):
        self._ctx = None

    def ctx_init(self, key):
        ctx1 = 0x0CAFFE19E
        if isinstance(key, str):
            key = key.encode('latin-1')
        for keyByte in key:
            ctx2 = ctx1
            ctx1 = ((((ctx1 >>2) * (ctx1 >>7))&0xFFFFFFFF) ^ (keyByte * keyByte * 0x0F902007)& 0xFFFFFFFF )
        self._ctx = [ctx1, ctx2]
        return [ctx1,ctx2]

    def decrypt(self, data,  ctx=None):
        if ctx == None:
            ctx = self._ctx
        ctx1 = ctx[0]
        ctx2 = ctx[1]
        plainText = ""
        if isinstance(data, str):
            data = data.encode('latin-1')
        for dataByte in data:
            m = (dataByte ^ ((ctx1 >> 3) &0xFF) ^ ((ctx2<<3) & 0xFF)) &0xFF
            ctx2 = ctx1
            ctx1 = (((ctx1 >> 2) * (ctx1 >> 7)) &0xFFFFFFFF) ^((m * m * 0x0F902007) &0xFFFFFFFF)
            plainText += chr(m)
        return plainText

class AES_CBC(object):
    def __init__(self):
        self._key = None
        self._iv = None
        self.aes = None

    def set_decrypt_key(self, userkey, iv):
        self._key = userkey
        self._iv = iv
        self.aes = aescbc.AES_CBC(userkey, aescbc.noPadding(), len(userkey))

    def decrypt(self, data):
        iv = self._iv
        cleartext = self.aes.decrypt(iv + data)
        return cleartext


class KeyIVGen(object):
    # this only exists in openssl so we will use pure python implementation instead
    # PKCS5_PBKDF2_HMAC_SHA1 = F(c_int, 'PKCS5_PBKDF2_HMAC_SHA1',
    #                             [c_char_p, c_ulong, c_char_p, c_ulong, c_ulong, c_ulong, c_char_p])
    def pbkdf2(self, passwd, salt, iter, keylen):

        def xorbytes( a, b ):
            if len(a) != len(b):
                raise Exception("xorbytes(): lengths differ")
            return bytes([x ^ y for x, y in zip(a, b)])

        def prf( h, data ):
            hm = h.copy()
            hm.update( data )
            return hm.digest()

        def pbkdf2_F( h, salt, itercount, blocknum ):
            U = prf( h, salt + pack('>i',blocknum ) )
            T = U
            for i in range(2, itercount+1):
                U = prf( h, U )
                T = xorbytes( T, U )
            return T

        sha = hashlib.sha1
        digest_size = sha().digest_size
        # l - number of output blocks to produce
        l = keylen // digest_size
        if keylen % digest_size != 0:
            l += 1
        h = hmac.new( passwd, None, sha )
        T = b""
        for i in range(1, l+1):
            T += pbkdf2_F( h, salt, iter, i )
        return T[0: keylen]