Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/Crypto/Util/Counter.py: 79%

33 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 07:03 +0000

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 

26CTR is a chaining mode for symmetric block encryption or decryption. 

27Messages are divideded into blocks, and the cipher operation takes 

28place on each block using the secret key and a unique *counter block*. 

29 

30The most straightforward way to fulfil the uniqueness property is 

31to start with an initial, random *counter block* value, and increment it as 

32the next block is processed. 

33 

34The block ciphers from `Crypto.Cipher` (when configured in *MODE_CTR* mode) 

35invoke a callable object (the *counter* parameter) to get the next *counter block*. 

36Unfortunately, the Python calling protocol leads to major performance degradations. 

37 

38The counter functions instantiated by this module will be invoked directly 

39by the ciphers in `Crypto.Cipher`. The fact that the Python layer is bypassed 

40lead to more efficient (and faster) execution of CTR cipher modes. 

41 

42An example of usage is the following: 

43 

44 >>> from Crypto.Cipher import AES 

45 >>> from Crypto.Util import Counter 

46 >>> from Crypto import Random 

47 >>> 

48 >>> nonce = Random.get_random_bytes(8) 

49 >>> ctr = Counter.new(64, nonce) 

50 >>> key = b'AES-128 symm key' 

51 >>> plaintext = b'X'*1000000 

52 >>> cipher = AES.new(key, AES.MODE_CTR, counter=ctr) 

53 >>> ciphertext = cipher.encrypt(plaintext) 

54 

55:undocumented: __package__ 

56""" 

57import sys 

58if sys.version_info[0] == 2 and sys.version_info[1] == 1: 

59 from Crypto.Util.py21compat import * 

60from Crypto.Util.py3compat import * 

61 

62from Crypto.pct_warnings import DisableShortcut_DeprecationWarning 

63from Crypto.Util import _counter 

64import struct 

65import warnings 

66 

67 

68# Factory function 

69_deprecated = "deprecated" 

70def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=_deprecated): 

71 """Create a stateful counter block function suitable for CTR encryption modes. 

72 

73 Each call to the function returns the next counter block. 

74 Each counter block is made up by three parts:: 

75 

76 prefix || counter value || postfix 

77 

78 The counter value is incremented by 1 at each call. 

79 

80 :Parameters: 

81 nbits : integer 

82 Length of the desired counter, in bits. It must be a multiple of 8. 

83 prefix : byte string 

84 The constant prefix of the counter block. By default, no prefix is 

85 used. 

86 suffix : byte string 

87 The constant postfix of the counter block. By default, no suffix is 

88 used. 

89 initial_value : integer 

90 The initial value of the counter. Default value is 1. 

91 overflow : integer 

92 This value is currently ignored. 

93 little_endian : boolean 

94 If *True*, the counter number will be encoded in little endian format. 

95 If *False* (default), in big endian format. 

96 allow_wraparound : boolean 

97 If *True*, the counter will automatically restart from zero after 

98 reaching the maximum value (``2**nbits-1``). 

99 If *False* (default), the object will raise an *OverflowError*. 

100 disable_shortcut : deprecated 

101 This option is a no-op for backward compatibility. It will be removed 

102 in a future version. Don't use it. 

103 :Returns: 

104 The counter block function. 

105 """ 

106 

107 # Sanity-check the message size 

108 (nbytes, remainder) = divmod(nbits, 8) 

109 if remainder != 0: 

110 # In the future, we might support arbitrary bit lengths, but for now we don't. 

111 raise ValueError("nbits must be a multiple of 8; got %d" % (nbits,)) 

112 if nbytes < 1: 

113 raise ValueError("nbits too small") 

114 elif nbytes > 0xffff: 

115 raise ValueError("nbits too large") 

116 

117 initval = _encode(initial_value, nbytes, little_endian) 

118 

119 if disable_shortcut is not _deprecated: # exact object comparison 

120 warnings.warn("disable_shortcut has no effect and is deprecated", DisableShortcut_DeprecationWarning) 

121 

122 if little_endian: 

123 return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound) 

124 else: 

125 return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound) 

126 

127def _encode(n, nbytes, little_endian=False): 

128 retval = [] 

129 n = int(n) 

130 for i in range(nbytes): 

131 if little_endian: 

132 retval.append(bchr(n & 0xff)) 

133 else: 

134 retval.insert(0, bchr(n & 0xff)) 

135 n >>= 8 

136 return b("").join(retval) 

137 

138# vim:set ts=4 sw=4 sts=4 expandtab: