Пример #1
0
    def encrypt(self, plain_text: bytes) -> Tuple[bytes, int]:
        """
        Encrypts plain bytes according to the current association and connection.
        Returns the ciphered text and the invocation counter used with the ciphered text.
        It also increases the internal client invocation counter to make sure a new
        invocation counter is used at every encryption call.
        """
        if not self.global_encryption_key:
            raise ProtectionError(
                "Unable to encrypt plain text. Missing global_encryption_key")
        if not self.global_authentication_key:
            raise ProtectionError(
                "Unable to encrypt plain text. Missing global_authentication_key"
            )

        invocation_counter = self.client_invocation_counter

        ciphered_text = security.encrypt(
            self.security_control,
            system_title=self.client_system_title,
            invocation_counter=invocation_counter,
            key=self.global_encryption_key,
            auth_key=self.global_authentication_key,
            plain_text=plain_text,
        )

        # updated the client_invocation_counter
        self.client_invocation_counter += 1

        return ciphered_text, invocation_counter
Пример #2
0
def test_encrypt():
    key = b"SUCHINSECUREKIND"
    auth_key = key

    text = b"SUPER_SECRET_TEXT"

    ctext = encrypt(
        key=key,
        auth_key=auth_key,
        invocation_counter=1,
        security_control=SecurityControlField(
            security_suite=0, authenticated=True, encrypted=True
        ),
        system_title=b"12345678",
        plain_text=text,
    )

    print(ctext)

    out = decrypt(
        key=key,
        auth_key=auth_key,
        invocation_counter=1,
        security_control=SecurityControlField(
            security_suite=0, authenticated=True, encrypted=True
        ),
        system_title=b"12345678",
        cipher_text=ctext,
    )

    assert text == out
def test_hls_fails(connection_with_hls: DlmsConnection):
    # Force state into awaiting response
    connection_with_hls.state.current_state = state.AWAITING_HLS_CLIENT_CHALLENGE_RESULT
    connection_with_hls.meter_system_title = b"12345678"
    connection_with_hls.meter_invocation_counter = 1
    failing_action_response = xdlms.ActionResponseNormal(
        status=enumerations.ActionResultStatus.OTHER_REASON
    )
    ciphered = security.encrypt(
        security_control=connection_with_hls.security_control,
        system_title=connection_with_hls.meter_system_title,
        auth_key=connection_with_hls.global_authentication_key,
        key=connection_with_hls.global_encryption_key,
        invocation_counter=2,
        plain_text=failing_action_response.to_bytes(),
    )
    ciphered_action_response = xdlms.GeneralGlobalCipher(
        security_control=connection_with_hls.security_control,
        system_title=connection_with_hls.meter_system_title,
        invocation_counter=2,
        ciphered_text=ciphered,
    )
    connection_with_hls.receive_data(ciphered_action_response.to_bytes())
    connection_with_hls.next_event()
    assert connection_with_hls.state.current_state == state.NO_ASSOCIATION
Пример #4
0
    def encrypt(self, plain_text: bytes):
        """
        Encrypts plain bytes according to the current association and connection.
        """
        if not self.global_encryption_key:
            raise ProtectionError(
                "Unable to encrypt plain text. Missing global_encryption_key")
        if not self.global_authentication_key:
            raise ProtectionError(
                "Unable to encrypt plain text. Missing global_authentication_key"
            )

        return security.encrypt(
            self.security_control,
            system_title=self.client_system_title,
            invocation_counter=self.client_invocation_counter,
            key=self.global_encryption_key,
            auth_key=self.global_authentication_key,
            plain_text=plain_text,
        )
Пример #5
0
def test_encrypt_authenticated():
    security_control = SecurityControlField(
        security_suite=0, authenticated=True, encrypted=True
    )
    encryption_key = bytes.fromhex("000102030405060708090A0B0C0D0E0F")
    authentication_key = bytes.fromhex("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF")
    system_title = bytes.fromhex("4D4D4D0000BC614E")
    invocation_counter = int.from_bytes(bytes.fromhex("01234567"), "big")
    # Get request attr 2 of clock object.
    plain_data = bytes.fromhex("C0010000080000010000FF0200")

    ciphered_text = bytes.fromhex("411312FF935A47566827C467BC7D825C3BE4A77C3FCC056B6B")

    assert (
        encrypt(
            security_control=security_control,
            key=encryption_key,
            auth_key=authentication_key,
            system_title=system_title,
            invocation_counter=invocation_counter,
            plain_text=plain_data,
        )
        == ciphered_text
    )
Пример #6
0
    def test_encrypt(self):
        apdu = xdlms.InitiateRequest(
            proposed_conformance=xdlms.Conformance(
                general_protection=False,
                general_block_transfer=False,
                delta_value_encoding=False,
                attribute_0_supported_with_set=False,
                priority_management_supported=True,
                attribute_0_supported_with_get=True,
                block_transfer_with_get_or_read=True,
                block_transfer_with_set_or_write=True,
                block_transfer_with_action=True,
                multiple_references=True,
                data_notification=False,
                access=False,
                get=True,
                set=True,
                selective_access=True,
                event_notification=True,
                action=True,
            ),
            proposed_quality_of_service=0,
            client_max_receive_pdu_size=1200,
            proposed_dlms_version_number=6,
            response_allowed=True,
            dedicated_key=b'\x00\x11"3DUfw\x88\x99\xaa\xbb\xcc\xdd\xee\xff',
        )

        encryption_key = bytes.fromhex("000102030405060708090A0B0C0D0E0F")
        authentication_key = bytes.fromhex("D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF")
        system_title = bytes.fromhex("4D4D4D0000BC614E")
        security_control = security.SecurityControlField(
            security_suite=0,
            authenticated=True,
            encrypted=True,
            broadcast_key=False,
            compressed=False,
        )
        invocation_counter = 19088743

        ciphered_apdu = xdlms.GlobalCipherInitiateRequest(
            security_control=security.SecurityControlField(
                security_suite=0,
                authenticated=True,
                encrypted=True,
                broadcast_key=False,
                compressed=False,
            ),
            invocation_counter=19088743,
            ciphered_text=
            b'\x80\x13\x02\xff\x8axt\x13=AL\xed%\xb4%4\xd2\x8d\xb0\x04w `k\x17[\xd5"\x11\xbehA\xdb M9\xeeo\xdb\x8e5hU',
        )

        cipher_text = security.encrypt(
            security_control=security_control,
            system_title=system_title,
            key=encryption_key,
            auth_key=authentication_key,
            invocation_counter=invocation_counter,
            plain_text=apdu.to_bytes(),
        )

        assert cipher_text == ciphered_apdu.ciphered_text