github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/third_party/pypy/_md5.py (about)

     1  #!/usr/bin/env python
     2  # -*- coding: iso-8859-1 -*-
     3  
     4  # Note that PyPy contains also a built-in module 'md5' which will hide
     5  # this one if compiled in.
     6  
     7  """A sample implementation of MD5 in pure Python.
     8  
     9  This is an implementation of the MD5 hash function, as specified by
    10  RFC 1321, in pure Python. It was implemented using Bruce Schneier's
    11  excellent book "Applied Cryptography", 2nd ed., 1996.
    12  
    13  Surely this is not meant to compete with the existing implementation
    14  of the Python standard library (written in C). Rather, it should be
    15  seen as a Python complement that is more readable than C and can be
    16  used more conveniently for learning and experimenting purposes in
    17  the field of cryptography.
    18  
    19  This module tries very hard to follow the API of the existing Python
    20  standard library's "md5" module, but although it seems to work fine,
    21  it has not been extensively tested! (But note that there is a test
    22  module, test_md5py.py, that compares this Python implementation with
    23  the C one of the Python standard library.
    24  
    25  BEWARE: this comes with no guarantee whatsoever about fitness and/or
    26  other properties! Specifically, do not use this in any production
    27  code! License is Python License!
    28  
    29  Special thanks to Aurelian Coman who fixed some nasty bugs!
    30  
    31  Dinu C. Gherman
    32  """
    33  
    34  
    35  __date__ = '2004-11-17'
    36  __version__ = 0.91  # Modernised by J. Hall�n and L. Creighton for Pypy
    37  
    38  __metaclass__ = type  # or genrpy won't work
    39  
    40  import _struct as struct
    41  import copy
    42  
    43  
    44  # ======================================================================
    45  # Bit-Manipulation helpers
    46  # ======================================================================
    47  
    48  def _bytelist2long(list):
    49    "Transform a list of characters into a list of longs."
    50  
    51    imax = len(list) // 4
    52    hl = [0] * imax
    53  
    54    j = 0
    55    i = 0
    56    while i < imax:
    57      b0 = ord(list[j])
    58      b1 = ord(list[j + 1]) << 8
    59      b2 = ord(list[j + 2]) << 16
    60      b3 = ord(list[j + 3]) << 24
    61      hl[i] = b0 | b1 | b2 | b3
    62      i = i + 1
    63      j = j + 4
    64  
    65    return hl
    66  
    67  
    68  def _rotateLeft(x, n):
    69    "Rotate x (32 bit) left n bits circularly."
    70  
    71    return (x << n) | (x >> (32 - n))
    72  
    73  
    74  # ======================================================================
    75  # The real MD5 meat...
    76  #
    77  #   Implemented after "Applied Cryptography", 2nd ed., 1996,
    78  #   pp. 436-441 by Bruce Schneier.
    79  # ======================================================================
    80  
    81  # F, G, H and I are basic MD5 functions.
    82  
    83  def F(x, y, z):
    84    return (x & y) | ((~x) & z)
    85  
    86  
    87  def G(x, y, z):
    88    return (x & z) | (y & (~z))
    89  
    90  
    91  def H(x, y, z):
    92    return x ^ y ^ z
    93  
    94  
    95  def I(x, y, z):
    96    return y ^ (x | (~z))
    97  
    98  
    99  def XX(func, a, b, c, d, x, s, ac):
   100    """Wrapper for call distribution to functions F, G, H and I.
   101  
   102    This replaces functions FF, GG, HH and II from "Appl. Crypto."
   103    Rotation is separate from addition to prevent recomputation
   104    (now summed-up in one function).
   105    """
   106  
   107    res = 0
   108    res = res + a + func(b, c, d)
   109    res = res + x
   110    res = res + ac
   111    res = res & 0xffffffff
   112    res = _rotateLeft(res, s)
   113    res = res & 0xffffffff
   114    res = res + b
   115  
   116    return res & 0xffffffff
   117  
   118  
   119  class MD5Type(object):
   120    "An implementation of the MD5 hash function in pure Python."
   121  
   122    digest_size = digestsize = 16
   123    block_size = 64
   124  
   125    def __init__(self):
   126      "Initialisation."
   127  
   128      # Initial message length in bits(!).
   129      self.length = 0
   130      self.count = [0, 0]
   131  
   132      # Initial empty message as a sequence of bytes (8 bit characters).
   133      self.input = []
   134  
   135      # Call a separate init function, that can be used repeatedly
   136      # to start from scratch on the same object.
   137      self.init()
   138  
   139    def init(self):
   140      "Initialize the message-digest and set all fields to zero.code"
   141  
   142      self.length = 0
   143      self.count = [0, 0]
   144      self.input = []
   145  
   146      # Load magic initialization constants.
   147      self.A = 0x67452301
   148      self.B = 0xefcdab89
   149      self.C = 0x98badcfe
   150      self.D = 0x10325476
   151  
   152    def _transform(self, inp):
   153      """Basic MD5 step transforming the digest based on the input.
   154  
   155      Note that if the Mysterious Constants are arranged backwards
   156      in little-endian order and decrypted with the DES they produce
   157      OCCULT MESSAGES!
   158      """
   159  
   160      a, b, c, d = A, B, C, D = self.A, self.B, self.C, self.D
   161  
   162      # Round 1.
   163  
   164      S11, S12, S13, S14 = 7, 12, 17, 22
   165  
   166      a = XX(F, a, b, c, d, inp[0], S11, 0xD76AA478)  # 1
   167      d = XX(F, d, a, b, c, inp[1], S12, 0xE8C7B756)  # 2
   168      c = XX(F, c, d, a, b, inp[2], S13, 0x242070DB)  # 3
   169      b = XX(F, b, c, d, a, inp[3], S14, 0xC1BDCEEE)  # 4
   170      a = XX(F, a, b, c, d, inp[4], S11, 0xF57C0FAF)  # 5
   171      d = XX(F, d, a, b, c, inp[5], S12, 0x4787C62A)  # 6
   172      c = XX(F, c, d, a, b, inp[6], S13, 0xA8304613)  # 7
   173      b = XX(F, b, c, d, a, inp[7], S14, 0xFD469501)  # 8
   174      a = XX(F, a, b, c, d, inp[8], S11, 0x698098D8)  # 9
   175      d = XX(F, d, a, b, c, inp[9], S12, 0x8B44F7AF)  # 10
   176      c = XX(F, c, d, a, b, inp[10], S13, 0xFFFF5BB1)  # 11
   177      b = XX(F, b, c, d, a, inp[11], S14, 0x895CD7BE)  # 12
   178      a = XX(F, a, b, c, d, inp[12], S11, 0x6B901122)  # 13
   179      d = XX(F, d, a, b, c, inp[13], S12, 0xFD987193)  # 14
   180      c = XX(F, c, d, a, b, inp[14], S13, 0xA679438E)  # 15
   181      b = XX(F, b, c, d, a, inp[15], S14, 0x49B40821)  # 16
   182  
   183      # Round 2.
   184  
   185      S21, S22, S23, S24 = 5, 9, 14, 20
   186  
   187      a = XX(G, a, b, c, d, inp[1], S21, 0xF61E2562)  # 17
   188      d = XX(G, d, a, b, c, inp[6], S22, 0xC040B340)  # 18
   189      c = XX(G, c, d, a, b, inp[11], S23, 0x265E5A51)  # 19
   190      b = XX(G, b, c, d, a, inp[0], S24, 0xE9B6C7AA)  # 20
   191      a = XX(G, a, b, c, d, inp[5], S21, 0xD62F105D)  # 21
   192      d = XX(G, d, a, b, c, inp[10], S22, 0x02441453)  # 22
   193      c = XX(G, c, d, a, b, inp[15], S23, 0xD8A1E681)  # 23
   194      b = XX(G, b, c, d, a, inp[4], S24, 0xE7D3FBC8)  # 24
   195      a = XX(G, a, b, c, d, inp[9], S21, 0x21E1CDE6)  # 25
   196      d = XX(G, d, a, b, c, inp[14], S22, 0xC33707D6)  # 26
   197      c = XX(G, c, d, a, b, inp[3], S23, 0xF4D50D87)  # 27
   198      b = XX(G, b, c, d, a, inp[8], S24, 0x455A14ED)  # 28
   199      a = XX(G, a, b, c, d, inp[13], S21, 0xA9E3E905)  # 29
   200      d = XX(G, d, a, b, c, inp[2], S22, 0xFCEFA3F8)  # 30
   201      c = XX(G, c, d, a, b, inp[7], S23, 0x676F02D9)  # 31
   202      b = XX(G, b, c, d, a, inp[12], S24, 0x8D2A4C8A)  # 32
   203  
   204      # Round 3.
   205  
   206      S31, S32, S33, S34 = 4, 11, 16, 23
   207  
   208      a = XX(H, a, b, c, d, inp[5], S31, 0xFFFA3942)  # 33
   209      d = XX(H, d, a, b, c, inp[8], S32, 0x8771F681)  # 34
   210      c = XX(H, c, d, a, b, inp[11], S33, 0x6D9D6122)  # 35
   211      b = XX(H, b, c, d, a, inp[14], S34, 0xFDE5380C)  # 36
   212      a = XX(H, a, b, c, d, inp[1], S31, 0xA4BEEA44)  # 37
   213      d = XX(H, d, a, b, c, inp[4], S32, 0x4BDECFA9)  # 38
   214      c = XX(H, c, d, a, b, inp[7], S33, 0xF6BB4B60)  # 39
   215      b = XX(H, b, c, d, a, inp[10], S34, 0xBEBFBC70)  # 40
   216      a = XX(H, a, b, c, d, inp[13], S31, 0x289B7EC6)  # 41
   217      d = XX(H, d, a, b, c, inp[0], S32, 0xEAA127FA)  # 42
   218      c = XX(H, c, d, a, b, inp[3], S33, 0xD4EF3085)  # 43
   219      b = XX(H, b, c, d, a, inp[6], S34, 0x04881D05)  # 44
   220      a = XX(H, a, b, c, d, inp[9], S31, 0xD9D4D039)  # 45
   221      d = XX(H, d, a, b, c, inp[12], S32, 0xE6DB99E5)  # 46
   222      c = XX(H, c, d, a, b, inp[15], S33, 0x1FA27CF8)  # 47
   223      b = XX(H, b, c, d, a, inp[2], S34, 0xC4AC5665)  # 48
   224  
   225      # Round 4.
   226  
   227      S41, S42, S43, S44 = 6, 10, 15, 21
   228  
   229      a = XX(I, a, b, c, d, inp[0], S41, 0xF4292244)  # 49
   230      d = XX(I, d, a, b, c, inp[7], S42, 0x432AFF97)  # 50
   231      c = XX(I, c, d, a, b, inp[14], S43, 0xAB9423A7)  # 51
   232      b = XX(I, b, c, d, a, inp[5], S44, 0xFC93A039)  # 52
   233      a = XX(I, a, b, c, d, inp[12], S41, 0x655B59C3)  # 53
   234      d = XX(I, d, a, b, c, inp[3], S42, 0x8F0CCC92)  # 54
   235      c = XX(I, c, d, a, b, inp[10], S43, 0xFFEFF47D)  # 55
   236      b = XX(I, b, c, d, a, inp[1], S44, 0x85845DD1)  # 56
   237      a = XX(I, a, b, c, d, inp[8], S41, 0x6FA87E4F)  # 57
   238      d = XX(I, d, a, b, c, inp[15], S42, 0xFE2CE6E0)  # 58
   239      c = XX(I, c, d, a, b, inp[6], S43, 0xA3014314)  # 59
   240      b = XX(I, b, c, d, a, inp[13], S44, 0x4E0811A1)  # 60
   241      a = XX(I, a, b, c, d, inp[4], S41, 0xF7537E82)  # 61
   242      d = XX(I, d, a, b, c, inp[11], S42, 0xBD3AF235)  # 62
   243      c = XX(I, c, d, a, b, inp[2], S43, 0x2AD7D2BB)  # 63
   244      b = XX(I, b, c, d, a, inp[9], S44, 0xEB86D391)  # 64
   245  
   246      A = (A + a) & 0xffffffff
   247      B = (B + b) & 0xffffffff
   248      C = (C + c) & 0xffffffff
   249      D = (D + d) & 0xffffffff
   250  
   251      self.A, self.B, self.C, self.D = A, B, C, D
   252  
   253    # Down from here all methods follow the Python Standard Library
   254    # API of the md5 module.
   255  
   256    def update(self, inBuf):
   257      """Add to the current message.
   258  
   259      Update the md5 object with the string arg. Repeated calls
   260      are equivalent to a single call with the concatenation of all
   261      the arguments, i.e. m.update(a); m.update(b) is equivalent
   262      to m.update(a+b).
   263  
   264      The hash is immediately calculated for all full blocks. The final
   265      calculation is made in digest(). This allows us to keep an
   266      intermediate value for the hash, so that we only need to make
   267      minimal recalculation if we call update() to add moredata to
   268      the hashed string.
   269      """
   270  
   271      leninBuf = len(inBuf)
   272  
   273      # Compute number of bytes mod 64.
   274      index = (self.count[0] >> 3) & 0x3F
   275  
   276      # Update number of bits.
   277      self.count[0] = self.count[0] + (leninBuf << 3)
   278      if self.count[0] < (leninBuf << 3):
   279        self.count[1] = self.count[1] + 1
   280      self.count[1] = self.count[1] + (leninBuf >> 29)
   281  
   282      partLen = 64 - index
   283  
   284      if leninBuf >= partLen:
   285        self.input[index:] = list(inBuf[:partLen])
   286        self._transform(_bytelist2long(self.input))
   287        i = partLen
   288        while i + 63 < leninBuf:
   289          self._transform(_bytelist2long(list(inBuf[i:i + 64])))
   290          i = i + 64
   291        else:
   292          self.input = list(inBuf[i:leninBuf])
   293      else:
   294        i = 0
   295        self.input = self.input + list(inBuf)
   296  
   297    def digest(self):
   298      """Terminate the message-digest computation and return digest.
   299  
   300      Return the digest of the strings passed to the update()
   301      method so far. This is a 16-byte string which may contain
   302      non-ASCII characters, including null bytes.
   303      """
   304  
   305      A = self.A
   306      B = self.B
   307      C = self.C
   308      D = self.D
   309      input = [] + self.input
   310      count = [] + self.count
   311  
   312      index = (self.count[0] >> 3) & 0x3f
   313  
   314      if index < 56:
   315        padLen = 56 - index
   316      else:
   317        padLen = 120 - index
   318  
   319      padding = [b'\200'] + [b'\000'] * 63
   320      self.update(padding[:padLen])
   321  
   322      # Append length (before padding).
   323      bits = _bytelist2long(self.input[:56]) + count
   324  
   325      self._transform(bits)
   326  
   327      # Store state in digest.
   328      digest = struct.pack("<IIII", self.A, self.B, self.C, self.D)
   329  
   330      self.A = A
   331      self.B = B
   332      self.C = C
   333      self.D = D
   334      self.input = input
   335      self.count = count
   336  
   337      return digest
   338  
   339    def hexdigest(self):
   340      """Terminate and return digest in HEX form.
   341  
   342      Like digest() except the digest is returned as a string of
   343      length 32, containing only hexadecimal digits. This may be
   344      used to exchange the value safely in email or other non-
   345      binary environments.
   346      """
   347  
   348      return ''.join([('0' + hex(ord(c))[2:])[-2:] for c in self.digest()])
   349  
   350    def copy(self):
   351      """Return a clone object.
   352  
   353      Return a copy ('clone') of the md5 object. This can be used
   354      to efficiently compute the digests of strings that share
   355      a common initial substring.
   356      """
   357      if 0:  # set this to 1 to make the flow space crash
   358        return copy.deepcopy(self)
   359      clone = self.__class__()
   360      clone.length = self.length
   361      clone.count = [] + self.count[:]
   362      clone.input = [] + self.input
   363      clone.A = self.A
   364      clone.B = self.B
   365      clone.C = self.C
   366      clone.D = self.D
   367      return clone
   368  
   369  
   370  # ======================================================================
   371  # Mimic Python top-level functions from standard library API
   372  # for consistency with the _md5 module of the standard library.
   373  # ======================================================================
   374  
   375  digest_size = 16
   376  
   377  
   378  def new(arg=None):
   379    """Return a new md5 crypto object.
   380    If arg is present, the method call update(arg) is made.
   381    """
   382  
   383    crypto = MD5Type()
   384    if arg:
   385      crypto.update(arg)
   386  
   387    return crypto