Counter.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # -*- coding: ascii -*-
  2. #
  3. # Util/Counter.py : Fast counter for use with CTR-mode ciphers
  4. #
  5. # Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
  6. #
  7. # ===================================================================
  8. # The contents of this file are dedicated to the public domain. To
  9. # the extent that dedication to the public domain is not available,
  10. # everyone is granted a worldwide, perpetual, royalty-free,
  11. # non-exclusive license to exercise all rights associated with the
  12. # contents of this file for any purpose whatsoever.
  13. # No rights are reserved.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. # SOFTWARE.
  23. # ===================================================================
  24. """Fast counter functions for CTR cipher modes.
  25. CTR is a chaining mode for symmetric block encryption or decryption.
  26. Messages are divideded into blocks, and the cipher operation takes
  27. place on each block using the secret key and a unique *counter block*.
  28. The most straightforward way to fulfil the uniqueness property is
  29. to start with an initial, random *counter block* value, and increment it as
  30. the next block is processed.
  31. The block ciphers from `Crypto.Cipher` (when configured in *MODE_CTR* mode)
  32. invoke a callable object (the *counter* parameter) to get the next *counter block*.
  33. Unfortunately, the Python calling protocol leads to major performance degradations.
  34. The counter functions instantiated by this module will be invoked directly
  35. by the ciphers in `Crypto.Cipher`. The fact that the Python layer is bypassed
  36. lead to more efficient (and faster) execution of CTR cipher modes.
  37. An example of usage is the following:
  38. >>> from Crypto.Cipher import AES
  39. >>> from Crypto.Util import Counter
  40. >>>
  41. >>> pt = b'\x00'*1000000
  42. >>> ctr = Counter.new(128)
  43. >>> cipher = AES.new(b'\x00'*16, AES.MODE_CTR, counter=ctr)
  44. >>> ct = cipher.encrypt(pt)
  45. :undocumented: __package__
  46. """
  47. import sys
  48. if sys.version_info[0] == 2 and sys.version_info[1] == 1:
  49. from Crypto.Util.py21compat import *
  50. from Crypto.Util.py3compat import *
  51. from Crypto.Util import _counter
  52. import struct
  53. # Factory function
  54. def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=False):
  55. """Create a stateful counter block function suitable for CTR encryption modes.
  56. Each call to the function returns the next counter block.
  57. Each counter block is made up by three parts::
  58. prefix || counter value || postfix
  59. The counter value is incremented by one at each call.
  60. :Parameters:
  61. nbits : integer
  62. Length of the desired counter, in bits. It must be a multiple of 8.
  63. prefix : byte string
  64. The constant prefix of the counter block. By default, no prefix is
  65. used.
  66. suffix : byte string
  67. The constant postfix of the counter block. By default, no suffix is
  68. used.
  69. initial_value : integer
  70. The initial value of the counter. Default value is 1.
  71. little_endian : boolean
  72. If True, the counter number will be encoded in little endian format.
  73. If False (default), in big endian format.
  74. allow_wraparound : boolean
  75. If True, the function will raise an *OverflowError* exception as soon
  76. as the counter wraps around. If False (default), the counter will
  77. simply restart from zero.
  78. disable_shortcut : boolean
  79. If True, do not make ciphers from `Crypto.Cipher` bypass the Python
  80. layer when invoking the counter block function.
  81. If False (default), bypass the Python layer.
  82. :Returns:
  83. The counter block function.
  84. """
  85. # Sanity-check the message size
  86. (nbytes, remainder) = divmod(nbits, 8)
  87. if remainder != 0:
  88. # In the future, we might support arbitrary bit lengths, but for now we don't.
  89. raise ValueError("nbits must be a multiple of 8; got %d" % (nbits,))
  90. if nbytes < 1:
  91. raise ValueError("nbits too small")
  92. elif nbytes > 0xffff:
  93. raise ValueError("nbits too large")
  94. initval = _encode(initial_value, nbytes, little_endian)
  95. if little_endian:
  96. return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
  97. else:
  98. return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
  99. def _encode(n, nbytes, little_endian=False):
  100. retval = []
  101. n = long(n)
  102. for i in range(nbytes):
  103. if little_endian:
  104. retval.append(bchr(n & 0xff))
  105. else:
  106. retval.insert(0, bchr(n & 0xff))
  107. n >>= 8
  108. return b("").join(retval)
  109. # vim:set ts=4 sw=4 sts=4 expandtab: