DeachSword / CHRLINE

LINE Chrome API
BSD 3-Clause "New" or "Revised" License
143 stars 80 forks source link

bug:decryptE2EEMessageV2? #23

Closed zbx911 closed 2 years ago

zbx911 commented 2 years ago

fetchOps [{1: 51, 2: 1641860644463, 3: 26, 4: 0, 10: '0', 20: {1: 'u33667fda0fe9ad8eadab99a204e2e47d', 2: 'uab852961b13bf960819ce2ae6c09f4e0', 3: 0, 4: '15398606256757', 5: 1641860644460, 14: False, 15: 0, 18: {'e2eeVersion': '2'}, 19: 0, 20: [b'$\xca\xa2\xad\x7f\x9b]\\xb7\x1e\x80Y?\xc4\x0f\x06', b'\xc9\xc9\x87\x7fG|"$\x99\x91b\xdf\x86]V\xb5\xbc\xab{\xaf\xab\xc4*z\x86\xed\x16aD\x8aZ\xc4\xc5_', b'\x00\x00\x00\x00\x00\x00\x00\x13G\xd8S\xb9', '\x006=P', '\x006m\x1a'], 27: []}}, {1: -1, 3: 0, 4: -1}] Traceback (most recent call last): File "F:/line/line_caller/line_talking/line_talking_main.py", line 158, in click_start_bot_btn print("RECEIVE_MESSAGE",opContent.get(1),cl.decryptE2EETextMessage(opContent)) File "F:\line\line_caller\CHRLINE_src\e2ee.py", line 217, in decryptE2EETextMessage decrypted = self.decryptE2EEMessageV2( File "F:\line\line_caller\CHRLINE_src\e2ee.py", line 250, in decryptE2EEMessageV2 decrypted = aesgcm.decrypt(sign, message, aad) File "D:\Anaconda3_x64_2021_11\lib\site-packages\cryptography\hazmat\primitives\ciphers\aead.py", line 202, in decrypt return aead._decrypt(backend, self, nonce, data, associated_data, 16) File "D:\Anaconda3_x64_2021_11\lib\site-packages\cryptography\hazmat\backends\openssl\aead.py", line 163, in _decrypt raise InvalidTag cryptography.exceptions.InvalidTag

zbx911 commented 2 years ago
import os
import time

from CHRLINE_src import *
from CHRLINE_src.hooks import HooksTracer
from CHRLINE_src import CHRLINE

from Account_token import accounts
import axolotl_curve25519 as Curve25519
no = 3
authTokenOrEmail = ""

# authTokenOrEmail = "xxxxx@qq.com"
# password = "asd00000"

# authTokenOrEmail=None
version = accounts[no].get("version").get("version")
# authTokenOrEmail = accounts[no].get("user").get("accessToken")

os_version = accounts[no].get("device").get("osVersion")

cl = CHRLINE(authTokenOrEmail=authTokenOrEmail,
            # password=password,
             device="ANDROID",#DESKTOPWIN
             version=version,
             os_version=os_version,
             debug=True)
cl.initAll()

def createSqrSecretKeys():
    private_key = Curve25519.generatePrivateKey(os.urandom(32))
    public_key = Curve25519.generatePublicKey(private_key)

    return private_key, public_key

# negotiateE2EEPublicKey:{1: 1, 2: 3554698, 4: b'\xcdoYm<\x8d\xc3k\xd5\xaf\xbf\xfb\xc86\x9a\xee)dzX|si<\xea\xad\x96u\x0e\x13\xf3\x10', 5: 0}
# removeE2EEPublicKey:None
# 00000000: 82 21 00 15 72 65 67 69  73 74 65 72 45 32 45 45  .!..registerE2EE
# 00000010: 50 75 62 6C 69 63 4B 65  79 15 A4 1F 1C 15 02 15  PublicKey.......
# 00000020: 01 28 20 07 A5 37 E0 4C  2A 6F 24 31 EE 9D BC 5F  .( ..7.L*o$1..._
# 00000030: FD FD 0E DB 31 2E 73 4C  9C 3C 45 82 90 26 AF 39  ....1.sL.<E..&.9
# 00000040: 18 C9 6C 16 00 00 00                              ..l....
# registerE2EEPublicKey:{1: 1, 2: 3554700, 4: b'\x07\xa57\xe0L*o$1\xee\x9d\xbc_\xfd\xfd\x0e\xdb1.sL\x9c<E\x82\x90&\xaf9\x18\xc9l', 5: 1641128401803}
# saveE2EESelfKeyData:True
# from:u0abc2582d3d9ba69c6eb5bf73c7cb2bd to u33667fda0fe9ad8eadab99a204e2e47d: {1: 'u0abc2582d3d9ba69c6eb5bf73c7cb2bd', 4: '15352212038606', 5: 1641128402145, 14: True, 15: 0, 19: 0, 20: [b'\t|\xccRV\xcf\x00\x96s]\xe6\xca\x9d5$\xf1', b'{\xc4\xcaN\x8cLBc\xd0\xd2\x99m\xcc\x07\xdb\xf1\xab\xb8a\x13\xcd2\x11\x15\xc5\xa0\x96\xd8\x9a\x1e\xec}\xd7|\xf8\x0e$\x96\xab\x1b\x91\xe5n\x98\xaf\xa0\x9a', b'>\xfb%l*p\x8f\xa75\x8aSQx\x17\xcdG', b'\x006=\x8c', '\x006=P'], 27: []}

pks = cl.getE2EEPublicKeys()

for n, pk in enumerate(pks):
    # E2EEPublicKey: {1: 1, 2: 3530386, 4: b'x\x85\xb8wu\x83i\x91]9(F\x99\xb8K\x06_\xe21;\xf5|n\xc3u\xa6)\x96\xf2\xf7VE', 5: 1639669615090}
    print(f"no.{n} E2EEPublicKey:", pk)
    r = cl.removeE2EEPublicKey(pk[1], pk[2], pk[4]) # 删除 E2EEPublicKey

private_key, public_key = createSqrSecretKeys()
print("pub:", public_key.hex())

r = cl.registerE2EEPublicKey(keyData=public_key)
print(f"registerE2EEPublicKey:{r}")

r = cl.saveE2EESelfKeyData(cl.mid, public_key, private_key, r[2], r[1])
print(f"saveE2EESelfKeyData:{r}")

# cids= cl.getAllContactIds()
# print("AllContactIds",cids)
# for cid in cids:
#     try:
#         r = cl.getRecentMessages(cid)
#         print("cid",cid,"RecentMessages",r)
#         r = cl.getRecentMessagesV2(cid)
#         print("cid",cid,"RecentMessagesV2",r)
#     except Exception as ex:
#         print(f"RecentMessagesV2 error:{ex}")

tracer = HooksTracer(
    cl, # main account
    prefixes=["bao:"], # cmd prefixes
    # db="test_hook", # database name, if None will use main account's mid
    # accounts=[cl8] # sub accounts
)

ADMINS = [] # admin's mids
for _admin in ADMINS:
    tracer.addPermission(_admin, 'admin') # add permission to db

class EventHook:

    @tracer.Event
    def onReady():
        print('Ready!')

class OpHook(object):

    @tracer.Operation(25)
    def sendMessage(self, op, cl):
        msg = op[20]
        pass

    @tracer.Operation(26)
    def recvMessage(self, op, cl):
        msg = op[20]
        print("recvMessage",op)
        #if msg[1] == cl8.mid:
        #    return # pass if is bot message
        self.trace(msg, self.HooksType["Content"], cl)

    @tracer.Operation(124)
    def recvChatInvite(self, op, cl):
        gid = op[10]
        inviter = op[11]
        mid = op[12]
        if mid == cl.mid:
            # someone invited the bot
            cl.acceptChatInvitation(gid) # join
            cl.sendCompactMessage(gid, 'hello! Korone is my waifu >w<')

    @tracer.Operation(127)
    def deleteSelfFromChat(self, op, cl):
        gid = op[10]
        if gid in cl.groups:
            cl.groups.remove(gid) # update local cache data

    @tracer.Operation(129)
    def joinChat(self, op, cl):
        gid = op[10]
        if gid not in cl.groups:
            cl.groups.append(gid) # update local cache data

    @tracer.Operation(133)
    def recvDeleteOtherFromChat(self, op, cl):
        gid = op[10]
        kicker = op[11]
        mid = op[12]
        if mid == cl.mid:
            # someone kick the bot
            if gid in cl.groups:
                cl.groups.remove(gid) # update local cache data

    @tracer.Before(tracer.HooksType["Operation"])
    def __before(self, op, cl):
        # handle all op
        # u can do something here for the same operation when multiple accounts
        pass

    @tracer.After(tracer.HooksType["Operation"])
    def __after(self, op, cl):
        # handle not tracked op
        opType = op[3]
        if opType not in [0, 48]:
            print(f"[{op[3]}]{op}")

class ContentHook(object):

    @tracer.Content(0)
    def TextMessage(self, msg, cl):
        text = msg.get(10)
        print("TextMessage",text)
        self.trace(msg, self.HooksType['Command'], cl)

    @tracer.Content(1)
    def ImageMessage(self, msg, cl):
        id = msg[4]
        metadata = msg[18]

class NormalCmd(object):

    @tracer.Command(ignoreCase=True)
    def hi(self, msg, cl):
        '''Debug.'''
        cl.replyMessage(msg, "Hi!")

    @tracer.Command(ignoreCase=True, inpart=True)
    def test(self, msg, cl):
        '''Test.'''
        cl.replyMessage(msg, "this is test!")

    @tracer.Command(alt=["指令"], ignoreCase=True)
    def help(self, msg, cl):
        '''cmd list'''
        cl.replyMessage(msg, self.genHelp(self.getPrefix(msg[10])))

    @tracer.Command(alt=["sp"], ignoreCase=True)
    def speed(self, msg, cl):
        '''測速用'''
        a = time.time()
        cl.replyMessage(msg, 'okok...')
        b = time.time() - a
        cl.replyMessage(msg, f'speed: {b}s')

    @tracer.Command(permissions=["admin"], ignoreCase=True)
    def checkOp(self, msg, cl):
        '''Admin Only.'''
        cl.replyMessage(msg, f'u is Admin!')

    @tracer.Command(ignoreCase=True)
    def getOp(self, msg, cl):
        '''get Admin!'''
        reply = "You are already an admin!"
        if self.addPermission(msg[1], 'admin'):
            reply = "You are now admin!"
        cl.replyMessage(msg, reply)

    @tracer.Command(ignoreCase=True)
    def bye(self, msg, cl):
        '''byebye'''
        cl.deleteSelfFromChat(msg[2])

tracer.run()

===========================================


Exception in thread Thread-5:
Traceback (most recent call last):
  File "D:\Anaconda3_x64_2021_11\lib\threading.py", line 973, in _bootstrap_inner
    self.run()
  File "D:\Anaconda3_x64_2021_11\lib\threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "F:\line\line_caller\CHRLINE_src\hooks.py", line 59, in trace
    if _func(self, data, cl):
  File "F:\line\line_caller\CHRLINE_src\hksc\types.py", line 21, in __check
    func(self, args[0], args[1])
  File "F:/line/line_caller/1.test_bot.py", line 110, in recvMessage
    self.trace(msg, self.HooksType["Content"], cl)
  File "F:\line\line_caller\CHRLINE_src\hooks.py", line 59, in trace
    if _func(self, data, cl):
  File "F:\line\line_caller\CHRLINE_src\hksc\types.py", line 33, in __check
    func(self, args[0], args[1])
  File "F:/line/line_caller/1.test_bot.py", line 163, in TextMessage
    self.trace(msg, self.HooksType['Command'], cl)
  File "F:\line\line_caller\CHRLINE_src\hooks.py", line 59, in trace
    if _func(self, data, cl):
  File "F:\line\line_caller\CHRLINE_src\hksc\types.py", line 81, in __check
    text = cl.decryptE2EETextMessage(msg, msg.get('opType', 26) == 25)
  File "F:\line\line_caller\CHRLINE_src\e2ee.py", line 202, in decryptE2EETextMessage
    pubK = self.getE2EELocalPublicKey(
  File "F:\line\line_caller\CHRLINE_src\e2ee.py", line 35, in getE2EELocalPublicKey
    raise Exception(f'E2EE key id-{keyId} not found on {mid}')
Exception: E2EE key id-3554640 not found on uab852961b13bf960819ce2ae6c09f4e0
WEDeach commented 2 years ago

Hello @zbx911 ,

can u check the public keys of the current account (getE2EEPublicKeys)?

I would like to know:

  1. does it only have the key with Id 3554640?
  2. does the key_3554640.json exist in your ./e2eeKeys folder?

btw, as i said on https://github.com/DeachSword/CHRLINE/issues/15#issuecomment-1007908902 u just need to remove the key to avoid E2EE no need to register it again

zbx911 commented 2 years ago

private_key, public_key = createSqrSecretKeys() print("pub:", public_key.hex())

r = cl.registerE2EEPublicKey(keyData=public_key) print(f"registerE2EEPublicKey:{r}")

r = cl.saveE2EESelfKeyData(cl.mid, public_key, private_key, r[2], r[1]) print(f"saveE2EESelfKeyData:{r}")

zbx911 commented 2 years ago

Hello @zbx911 ,

can u check the public keys of the current account (getE2EEPublicKeys)?

I would like to know:

1. does it only have the key with Id 3554640?

2. does the `key_3554640.json` exist in your ./e2eeKeys folder?

btw, as i said on #15 (comment) u just need to remove the key to avoid E2EE no need to register it again

Operation {1: 70, 2: 1641982197565, 3: 26, 4: 0, 10: '0', 20: {1: 'u33667fda0fe9ad8eadab99a204e2e47d', 2: 'uab852961b13bf960819ce2ae6c09f4e0', 3: 0, 4: '15406883257100', 5: 1641982197562, 14: False, 15: 0, 18: {'e2eeVersion': '2'}, 19: 0, 20: [b'-\xf1\x8e\x12F\xf3\xe4\xcd\xad!8z\x84\xe6a}', b'\xd1\xd3\x90\x8e[\xa4\x94\xf7\xc7$\x01\\xaf\x08\xcbf\x1c\x1fm\xb6\xa7x\xeb\xd3#\xae\x88\xb21', b'\x00\x00\x00\x00\x00\x00\x00\x03UV\xe0o', '\x006=P', '\x006u\x1e'], 27: []}} Operation {1: 70, 2: 1641982197565, 3: 26, 4: 0, 10: '0', 20: {1: 'u33667fda0fe9ad8eadab99a204e2e47d', 2: 'uab852961b13bf960819ce2ae6c09f4e0', 3: 0, 4: '15406883257100', 5: 1641982197562, 14: False, 15: 0, 18: {'e2eeVersion': '2'}, 19: 0, 20: [b'-\xf1\x8e\x12F\xf3\xe4\xcd\xad!8z\x84\xe6a}', b'\xd1\xd3\x90\x8e[\xa4\x94\xf7\xc7$\x01\\\xaf\x08\xcbf\x1c\x1fm\xb6\xa7x\xeb\xd3#\xae\x88\xb21', b'\x00\x00\x00\x00\x00\x00\x00\x03UV\xe0o', '\x006=P', '\x006u\x1e'], 27: [], 'opType': 26, 'isE2EE': False}} recvMessage {1: 70, 2: 1641982197565, 3: 26, 4: 0, 10: '0', 20: {1: 'u33667fda0fe9ad8eadab99a204e2e47d', 2: 'uab852961b13bf960819ce2ae6c09f4e0', 3: 0, 4: '15406883257100', 5: 1641982197562, 14: False, 15: 0, 18: {'e2eeVersion': '2'}, 19: 0, 20: [b'-\xf1\x8e\x12F\xf3\xe4\xcd\xad!8z\x84\xe6a}', b'\xd1\xd3\x90\x8e[\xa4\x94\xf7\xc7$\x01\\xaf\x08\xcbf\x1c\x1fm\xb6`\xa7x\xeb\xd3#\xae\x88\xb21', b'\x00\x00\x00\x00\x00\x00\x00\x03UV\xe0o', '\x006=P', '\x006u\x1e'], 27: [], 'opType': 26, 'isE2EE': False}} senderKeyId: 3554640 True receiverKeyId: 3568926 True Operation {1: -1, 3: 0, 4: -1} Operation {1: -1, 3: 0, 4: -1} Operation {1: -1, 3: 0, 4: -1} Operation {1: -1, 3: 0, 4: -1} Operation {1: -1, 3: 0, 4: -1} Operation {1: -1, 3: 0, 4: -1} Exception in thread Thread-7: Traceback (most recent call last): File "D:\Anaconda3_x64_2021_11\lib\threading.py", line 973, in _bootstrap_inner self.run() File "D:\Anaconda3_x64_2021_11\lib\threading.py", line 910, in run self._target(*self._args, **self._kwargs) File "F:\line\line_caller\CHRLINE_src\hooks.py", line 59, in trace if _func(self, data, cl): File "F:\line\line_caller\CHRLINE_src\hksc\types.py", line 21, in check func(self, args[0], args[1]) File "F:/line/line_caller/1.test_bot.py", line 111, in recvMessage self.trace(msg, self.HooksType["Content"], cl) File "F:\line\line_caller\CHRLINE_src\hooks.py", line 59, in trace if _func(self, data, cl): File "F:\line\line_caller\CHRLINE_src\hksc\types.py", line 33, in __check func(self, args[0], args[1]) File "F:/line/line_caller/1.test_bot.py", line 163, in TextMessage self.trace(msg, self.HooksType['Command'], cl) File "F:\line\line_caller\CHRLINE_src\hooks.py", line 59, in trace if _func(self, data, cl): File "F:\line\line_caller\CHRLINE_src\hksc\types.py", line 82, in check text = cl.decryptE2EETextMessage2(msg, msg.get('opType', 26) == 25) File "F:\line\line_caller\CHRLINE_src\e2ee.py", line 210, in decryptE2EETextMessage2 decrypted = self.decryptE2EEMessageV2( File "F:\line\line_caller\CHRLINE_src\e2ee.py", line 295, in decryptE2EEMessageV2 decrypted = aesgcm.decrypt(sign, message, aad) File "D:\Anaconda3_x64_2021_11\lib\site-packages\cryptography\hazmat\primitives\ciphers\aead.py", line 202, in decrypt return aead._decrypt(backend, self, nonce, data, associated_data, 16) File "D:\Anaconda3_x64_2021_11\lib\site-packages\cryptography\hazmat\backends\openssl\aead.py", line 163, in _decrypt raise InvalidTag cryptography.exceptions.InvalidTag

can u test bot.py example?decryptE2EETextMessage2 had error!!!!

WEDeach commented 2 years ago

Hi @zbx911 ,

decryptE2EETextMessage2 works for me and you haven't answered my questions so I can't help