e11sync

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

anonymize_ip.py (3901B) - Raw


      1 # https://raw.githubusercontent.com/samuelmeuli/anonymize-ip/7f4faedf64643bd3de3607ab8905c1b1a3f8841a/anonymizeip/anonymize_ip.py
      2 
      3 from ipaddress import ip_address
      4 
      5 
      6 def anonymize_ip(
      7     address,
      8     ipv4_mask="255.255.255.0",
      9     ipv6_mask="ffff:ffff:ffff:ffff:0000:0000:0000:0000"
     10 ):
     11     """
     12     Anonymize the provided IPv4 or IPv6 address by setting parts of the
     13     address to 0
     14 
     15     :param str|int address: IP address to be anonymized
     16     :param str ipv4_mask: Mask that defines which parts of an IPv4 address are
     17     set to 0 (default: "255.255.255.0")
     18     :param str ipv6_mask: Mask that defines which parts of an IPv6 address are
     19     set to 0 (default: "ffff:ffff:ffff:ffff:0000:0000:0000:0000")
     20     :return: Anonymized IP address
     21     :rtype: str
     22     """
     23 
     24     # IP address to be anonymized
     25     address_packed = ip_address(address).packed
     26     address_len = len(address_packed)
     27 
     28     if address_len == 4:
     29         # IPv4
     30         ipv4_mask_packed = ip_address(ipv4_mask).packed
     31         __validate_ipv4_mask(ipv4_mask_packed)
     32         return __apply_mask(address_packed, ipv4_mask_packed, 4)
     33     elif address_len == 16:
     34         # IPv6
     35         ipv6_mask_packed = ip_address(ipv6_mask).packed
     36         __validate_ipv6_mask(ipv6_mask_packed)
     37         return __apply_mask(address_packed, ipv6_mask_packed, 16)
     38     else:
     39         # Invalid address
     40         raise ValueError("Address does not consist of 4 (IPv4) or 16 (IPv6) "
     41                          "octets")
     42 
     43 
     44 def __apply_mask(address_packed, mask_packed, nr_bytes):
     45     """
     46     Perform a bitwise AND operation on all corresponding bytes between the
     47     mask and the provided address. Mask parts set to 0 will become 0 in the
     48     anonymized IP address as well
     49 
     50     :param bytes address_packed: Binary representation of the IP address to
     51     be anonymized
     52     :param bytes mask_packed: Binary representation of the corresponding IP
     53     address mask
     54     :param int nr_bytes: Number of bytes in the address (4 for IPv4, 16 for
     55     IPv6)
     56     :return: Anonymized IP address
     57     :rtype: str
     58     """
     59 
     60     anon_packed = bytearray()
     61     for i in range(0, nr_bytes):
     62         anon_packed.append(mask_packed[i] & address_packed[i])
     63     return str(ip_address(bytes(anon_packed)))
     64 
     65 
     66 def __validate_ipv4_mask(mask_packed):
     67     # Test that mask only contains valid numbers
     68     for byte in mask_packed:
     69         if byte != 0 and byte != 255:
     70             raise ValueError("ipv4_mask must only contain numbers 0 or 255")
     71 
     72     # Test that IP address does not get anonymized completely
     73     if mask_packed == b'\x00\x00\x00\x00':
     74         raise ValueError("ipv4_mask cannot be set to \"0.0.0.0\" (all "
     75                          "anonymized addresses will be 0.0.0.0)")
     76 
     77     # Test that IP address is changed by anonymization
     78     if mask_packed == b'\xff\xff\xff\xff':
     79         raise ValueError("ipv4_mask cannot be set to \"255.255.255.255\" "
     80                          "(addresses will not be anonymized)")
     81 
     82 
     83 def __validate_ipv6_mask(mask_packed):
     84     # Test that mask only contains valid numbers
     85     for byte in mask_packed:
     86         if byte != 0 and byte != 255:
     87             raise ValueError("ipv6_mask must only contain numbers 0 or ffff")
     88 
     89     # Test that IP address does not get anonymized completely
     90     if (
     91         mask_packed ==
     92         b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
     93     ):
     94         raise ValueError("ipv6_mask cannot be set to "
     95                          "\"0000:0000:0000:0000:0000:0000:0000:0000\" (all "
     96                          "anonymized addresses will be 0.0.0.0)")
     97 
     98     # Test that IP address is changed by anonymization
     99     if (
    100         mask_packed ==
    101         b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
    102     ):
    103         raise ValueError("ipv6_mask cannot be set to "
    104                          "\"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\" "
    105                          "(addresses will not be anonymized)")