Advertisement
creamygoat

Password-based File Encryption (PBKDF2:HMAC-SHA-256:AES-128)

Mar 3rd, 2016
507
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 54.47 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. """
  4.  Password-Encrypt File
  5.  
  6.  Usage:
  7.  
  8.  pef encrypt {password} {plainfile} {outputfile}
  9.  pef decrypt {password} {encryptedfile} {outputfile}
  10.  pef verify {password} {encryptedfile}
  11.  
  12.  If {password} is an empty string, the user will be prompted for a password.
  13.  
  14.  This script is useful for encrypting and decrypting important files to
  15.  be stored in insecure (or untrusted) environments in a way that makes it
  16.  easy to recover the data on a platform with Python3 and default libraries
  17.  installed only. If this script is lost, the data can easily be recovered
  18.  with the aid of cryptographic libraries and analysis of the file headers.
  19.  
  20.  The encryption is AES-128-GCM with a random 96-bit initialisation vector.
  21.  The password-based key derivation function is PBKDF2 with HMAC-SHA-256,
  22.  a 256-bit random salt, 5000 iterations, producing a 128-bit (16 byte) key.
  23.  The appended authentication tag is 128 bits (16 bytes) in length.
  24.  
  25. """
  26.  
  27. #-------------------------------------------------------------------------------
  28. # Imports
  29. #-------------------------------------------------------------------------------
  30.  
  31. import sys
  32. import os
  33. import traceback
  34. import io
  35. import binascii
  36. import getpass
  37.  
  38.  
  39. #-------------------------------------------------------------------------------
  40. # Exceptions
  41. #-------------------------------------------------------------------------------
  42.  
  43.  
  44. class Error (Exception):
  45.   pass
  46.  
  47. class ArgError (Error):
  48.   pass
  49.  
  50. class FileError(Error):
  51.   pass
  52.  
  53. class CmdError(Error):
  54.   pass
  55.  
  56.  
  57. #-------------------------------------------------------------------------------
  58. # Bit fiddling functions
  59. #-------------------------------------------------------------------------------
  60.  
  61.  
  62. def XorAWithB(A, B):
  63.   for i, x in enumerate(B):
  64.     A[i] ^= x
  65.  
  66.  
  67. #-------------------------------------------------------------------------------
  68.  
  69.  
  70. def BytesToIntBE(X):
  71.   """
  72.  Read a big-endian byte array as a native integer.
  73.  """
  74.   Result = 0
  75.   for b in X:
  76.     Result = (Result << 8) + b
  77.   return Result
  78.  
  79.  
  80. #-------------------------------------------------------------------------------
  81.  
  82.  
  83. def IntToBytesBE(x, Length):
  84.   """
  85.  Return a big-endian byte array from a native integer.
  86.  """
  87.   Result = bytearray(Length)
  88.   RIx = Length
  89.   a = x
  90.   while a != 0:
  91.     RIx -= 1
  92.     Result[RIx] = a & 0xFF
  93.     a >>= 8
  94.   return Result
  95.  
  96.  
  97. #-------------------------------------------------------------------------------
  98. # Stream functions
  99. #-------------------------------------------------------------------------------
  100.  
  101.  
  102. class Substream (io.RawIOBase):
  103.  
  104.   def __init__(self, instream, start=None, length=None):
  105.     self._instream = instream
  106.     if instream.seekable():
  107.       pos = instream.tell()
  108.       end = instream.seek(0, io.SEEK_END)
  109.       pos = instream.seek(pos, io.SEEK_SET)
  110.       self._start = pos if start is None else start
  111.       self._length = end - self._start if length is None else length
  112.     else:
  113.       self._start = None
  114.       self._length = length
  115.     self._closed = instream.closed
  116.     self._pos = 0
  117.     pass
  118.   @property
  119.   def closed(self):
  120.     self._closed = self._closed or _instream.closed
  121.     return self.closed
  122.   def close(self):
  123.     self._closed = True
  124.   def readable(self):
  125.     return self._instream.readable() and not self._closed
  126.   def seek(self, offset, whence=io.SEEK_SET):
  127.     if not self._instream.seekable():
  128.       raise FileError("This Substream is not seekable.")
  129.     if whence == io.SEEK_SET:
  130.       x = offset
  131.     elif whence == io.SEEK_CUR:
  132.       x = self._pos + offset
  133.     elif whence == io.SEEK_END:
  134.       x = self._length - offset
  135.     else:
  136.       raise FileError("Invalid seek origin for Substream.")
  137.     self._pos = x
  138.     return self._pos
  139.   def seekable(self):
  140.     return seek._instream.seekable()
  141.   def tell(self):
  142.     if not self._instream.seekable():
  143.       raise FileError("This Substream is not seekable, so no tell().")
  144.     return self._pos
  145.   def writable(self):
  146.     return False
  147.  
  148.   def readinto(self, b):
  149.     l = len(b)
  150.     readsize = min(max(0, self._length - self._pos), l)
  151.     if readsize > 0:
  152.       if self._instream.seekable():
  153.         self._instream.seek(self._start + self._pos, io.SEEK_SET)
  154.       output = self._instream.read(readsize)
  155.       if output is None:
  156.         return None
  157.       readsize = len(output)
  158.       b[:readsize] = output
  159.       self._pos += readsize
  160.     return readsize
  161.  
  162.   def write(self, size):
  163.     raise FileError("Substream is not writable.")
  164.  
  165.  
  166. #-------------------------------------------------------------------------------
  167.  
  168.  
  169. class StreamSansTail (io.RawIOBase):
  170.  
  171.   def __init__(self, InStream, TailLength):
  172.     self.TailLength = TailLength
  173.     self.TailBuffer = b''
  174.     self.InStream = InStream
  175.  
  176.   def readable(self):
  177.     return True
  178.  
  179.   def readinto(self, b):
  180.  
  181.     n = len(b)
  182.     NumBytesNeeded = n + self.TailLength - len(self.TailBuffer)
  183.     if self.InStream is not None:
  184.       if NumBytesNeeded > 0:
  185.         Chunk = self.InStream.read(NumBytesNeeded)
  186.         if Chunk is None:
  187.           self.InStream = None
  188.         self.TailBuffer += Chunk
  189.     NumBytesToOutput = min(n, len(self.TailBuffer) - self.TailLength)
  190.     Output = self.TailBuffer[:NumBytesToOutput]
  191.     self.TailBuffer = self.TailBuffer[NumBytesToOutput:]
  192.     b[:len(Output)] = Output
  193.     return len(Output)
  194.  
  195.   def readtail(self):
  196.     return self.TailBuffer[-self.TailLength:]
  197.  
  198.  
  199. #-------------------------------------------------------------------------------
  200.  
  201.  
  202. def StreamAsBlocks(Stream, BlockSize):
  203.  
  204.   Length = 0
  205.   HaveEOF = False
  206.   Buffer = bytes()
  207.  
  208.   while not HaveEOF:
  209.  
  210.     S = Stream.read(2 * BlockSize - len(Buffer))
  211.  
  212.     if len(S) > 0:
  213.       Length += len(S)
  214.       Buffer += S
  215.     else:
  216.       HaveEOF = True
  217.  
  218.     while len(Buffer) >= BlockSize:
  219.       Block = Buffer[:BlockSize]
  220.       Buffer = Buffer[BlockSize:]
  221.       yield Block
  222.  
  223.   if len(Buffer) > 0:
  224.     yield Buffer
  225.  
  226.  
  227. #-------------------------------------------------------------------------------
  228.  
  229.  
  230. def IterableToStream(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE):
  231.  
  232.   class IterStream (io.RawIOBase):
  233.  
  234.     def __init__(self):
  235.       self.inbuf = b''
  236.  
  237.     def readable(self):
  238.       return True
  239.  
  240.     def readinto(self, b):
  241.  
  242.       try:
  243.  
  244.         chunk = self.inbuf or next(iterable)
  245.         n = len(b)
  246.         output = chunk[:n]
  247.         self.inbuf = chunk[n:]
  248.         b[:len(output)] = output
  249.  
  250.         return len(output)
  251.  
  252.       except StopIteration:
  253.  
  254.         return 0
  255.  
  256.   return io.BufferedReader(IterStream(), buffer_size=buffer_size)
  257.  
  258.  
  259. #-------------------------------------------------------------------------------
  260. # AES
  261. #-------------------------------------------------------------------------------
  262.  
  263.  
  264. SBox = bytes([
  265.   0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
  266.   0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
  267.   0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
  268.   0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
  269.   0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
  270.   0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
  271.   0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
  272.   0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
  273.   0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
  274.   0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
  275.   0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
  276.   0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
  277.   0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
  278.   0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
  279.   0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
  280.   0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
  281.   0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
  282.   0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
  283.   0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
  284.   0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
  285.   0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
  286.   0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
  287.   0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
  288.   0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
  289.   0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
  290.   0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
  291.   0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
  292.   0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
  293.   0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
  294.   0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
  295.   0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
  296.   0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
  297. ])
  298.  
  299. RoundConstantBytes = bytes([
  300.   0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
  301.   0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a
  302. ])
  303.  
  304.  
  305. InvSBox = bytes([
  306.   0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
  307.   0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
  308.   0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
  309.   0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
  310.   0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
  311.   0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
  312.   0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
  313.   0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
  314.   0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
  315.   0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
  316.   0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
  317.   0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
  318.   0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
  319.   0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
  320.   0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
  321.   0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
  322.   0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
  323.   0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
  324.   0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
  325.   0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
  326.   0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
  327.   0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
  328.   0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
  329.   0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
  330.   0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
  331.   0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
  332.   0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
  333.   0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
  334.   0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
  335.   0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
  336.   0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
  337.   0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
  338. ])
  339.  
  340. GMul0E = bytes([
  341.   0x00, 0x0E, 0x1C, 0x12, 0x38, 0x36, 0x24, 0x2A,
  342.   0x70, 0x7E, 0x6C, 0x62, 0x48, 0x46, 0x54, 0x5A,
  343.   0xE0, 0xEE, 0xFC, 0xF2, 0xD8, 0xD6, 0xC4, 0xCA,
  344.   0x90, 0x9E, 0x8C, 0x82, 0xA8, 0xA6, 0xB4, 0xBA,
  345.   0xDB, 0xD5, 0xC7, 0xC9, 0xE3, 0xED, 0xFF, 0xF1,
  346.   0xAB, 0xA5, 0xB7, 0xB9, 0x93, 0x9D, 0x8F, 0x81,
  347.   0x3B, 0x35, 0x27, 0x29, 0x03, 0x0D, 0x1F, 0x11,
  348.   0x4B, 0x45, 0x57, 0x59, 0x73, 0x7D, 0x6F, 0x61,
  349.   0xAD, 0xA3, 0xB1, 0xBF, 0x95, 0x9B, 0x89, 0x87,
  350.   0xDD, 0xD3, 0xC1, 0xCF, 0xE5, 0xEB, 0xF9, 0xF7,
  351.   0x4D, 0x43, 0x51, 0x5F, 0x75, 0x7B, 0x69, 0x67,
  352.   0x3D, 0x33, 0x21, 0x2F, 0x05, 0x0B, 0x19, 0x17,
  353.   0x76, 0x78, 0x6A, 0x64, 0x4E, 0x40, 0x52, 0x5C,
  354.   0x06, 0x08, 0x1A, 0x14, 0x3E, 0x30, 0x22, 0x2C,
  355.   0x96, 0x98, 0x8A, 0x84, 0xAE, 0xA0, 0xB2, 0xBC,
  356.   0xE6, 0xE8, 0xFA, 0xF4, 0xDE, 0xD0, 0xC2, 0xCC,
  357.   0x41, 0x4F, 0x5D, 0x53, 0x79, 0x77, 0x65, 0x6B,
  358.   0x31, 0x3F, 0x2D, 0x23, 0x09, 0x07, 0x15, 0x1B,
  359.   0xA1, 0xAF, 0xBD, 0xB3, 0x99, 0x97, 0x85, 0x8B,
  360.   0xD1, 0xDF, 0xCD, 0xC3, 0xE9, 0xE7, 0xF5, 0xFB,
  361.   0x9A, 0x94, 0x86, 0x88, 0xA2, 0xAC, 0xBE, 0xB0,
  362.   0xEA, 0xE4, 0xF6, 0xF8, 0xD2, 0xDC, 0xCE, 0xC0,
  363.   0x7A, 0x74, 0x66, 0x68, 0x42, 0x4C, 0x5E, 0x50,
  364.   0x0A, 0x04, 0x16, 0x18, 0x32, 0x3C, 0x2E, 0x20,
  365.   0xEC, 0xE2, 0xF0, 0xFE, 0xD4, 0xDA, 0xC8, 0xC6,
  366.   0x9C, 0x92, 0x80, 0x8E, 0xA4, 0xAA, 0xB8, 0xB6,
  367.   0x0C, 0x02, 0x10, 0x1E, 0x34, 0x3A, 0x28, 0x26,
  368.   0x7C, 0x72, 0x60, 0x6E, 0x44, 0x4A, 0x58, 0x56,
  369.   0x37, 0x39, 0x2B, 0x25, 0x0F, 0x01, 0x13, 0x1D,
  370.   0x47, 0x49, 0x5B, 0x55, 0x7F, 0x71, 0x63, 0x6D,
  371.   0xD7, 0xD9, 0xCB, 0xC5, 0xEF, 0xE1, 0xF3, 0xFD,
  372.   0xA7, 0xA9, 0xBB, 0xB5, 0x9F, 0x91, 0x83, 0x8D
  373. ])
  374.  
  375. GMul09 = bytes([
  376.   0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F,
  377.   0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77,
  378.   0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF,
  379.   0xD8, 0xD1, 0xCA, 0xC3, 0xFC, 0xF5, 0xEE, 0xE7,
  380.   0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04,
  381.   0x73, 0x7A, 0x61, 0x68, 0x57, 0x5E, 0x45, 0x4C,
  382.   0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94,
  383.   0xE3, 0xEA, 0xF1, 0xF8, 0xC7, 0xCE, 0xD5, 0xDC,
  384.   0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49,
  385.   0x3E, 0x37, 0x2C, 0x25, 0x1A, 0x13, 0x08, 0x01,
  386.   0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9,
  387.   0xAE, 0xA7, 0xBC, 0xB5, 0x8A, 0x83, 0x98, 0x91,
  388.   0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72,
  389.   0x05, 0x0C, 0x17, 0x1E, 0x21, 0x28, 0x33, 0x3A,
  390.   0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2,
  391.   0x95, 0x9C, 0x87, 0x8E, 0xB1, 0xB8, 0xA3, 0xAA,
  392.   0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3,
  393.   0xA4, 0xAD, 0xB6, 0xBF, 0x80, 0x89, 0x92, 0x9B,
  394.   0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43,
  395.   0x34, 0x3D, 0x26, 0x2F, 0x10, 0x19, 0x02, 0x0B,
  396.   0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8,
  397.   0x9F, 0x96, 0x8D, 0x84, 0xBB, 0xB2, 0xA9, 0xA0,
  398.   0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78,
  399.   0x0F, 0x06, 0x1D, 0x14, 0x2B, 0x22, 0x39, 0x30,
  400.   0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5,
  401.   0xD2, 0xDB, 0xC0, 0xC9, 0xF6, 0xFF, 0xE4, 0xED,
  402.   0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35,
  403.   0x42, 0x4B, 0x50, 0x59, 0x66, 0x6F, 0x74, 0x7D,
  404.   0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E,
  405.   0xE9, 0xE0, 0xFB, 0xF2, 0xCD, 0xC4, 0xDF, 0xD6,
  406.   0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E,
  407.   0x79, 0x70, 0x6B, 0x62, 0x5D, 0x54, 0x4F, 0x46
  408. ])
  409.  
  410. GMul0D = bytes([
  411.   0x00, 0x0D, 0x1A, 0x17, 0x34, 0x39, 0x2E, 0x23,
  412.   0x68, 0x65, 0x72, 0x7F, 0x5C, 0x51, 0x46, 0x4B,
  413.   0xD0, 0xDD, 0xCA, 0xC7, 0xE4, 0xE9, 0xFE, 0xF3,
  414.   0xB8, 0xB5, 0xA2, 0xAF, 0x8C, 0x81, 0x96, 0x9B,
  415.   0xBB, 0xB6, 0xA1, 0xAC, 0x8F, 0x82, 0x95, 0x98,
  416.   0xD3, 0xDE, 0xC9, 0xC4, 0xE7, 0xEA, 0xFD, 0xF0,
  417.   0x6B, 0x66, 0x71, 0x7C, 0x5F, 0x52, 0x45, 0x48,
  418.   0x03, 0x0E, 0x19, 0x14, 0x37, 0x3A, 0x2D, 0x20,
  419.   0x6D, 0x60, 0x77, 0x7A, 0x59, 0x54, 0x43, 0x4E,
  420.   0x05, 0x08, 0x1F, 0x12, 0x31, 0x3C, 0x2B, 0x26,
  421.   0xBD, 0xB0, 0xA7, 0xAA, 0x89, 0x84, 0x93, 0x9E,
  422.   0xD5, 0xD8, 0xCF, 0xC2, 0xE1, 0xEC, 0xFB, 0xF6,
  423.   0xD6, 0xDB, 0xCC, 0xC1, 0xE2, 0xEF, 0xF8, 0xF5,
  424.   0xBE, 0xB3, 0xA4, 0xA9, 0x8A, 0x87, 0x90, 0x9D,
  425.   0x06, 0x0B, 0x1C, 0x11, 0x32, 0x3F, 0x28, 0x25,
  426.   0x6E, 0x63, 0x74, 0x79, 0x5A, 0x57, 0x40, 0x4D,
  427.   0xDA, 0xD7, 0xC0, 0xCD, 0xEE, 0xE3, 0xF4, 0xF9,
  428.   0xB2, 0xBF, 0xA8, 0xA5, 0x86, 0x8B, 0x9C, 0x91,
  429.   0x0A, 0x07, 0x10, 0x1D, 0x3E, 0x33, 0x24, 0x29,
  430.   0x62, 0x6F, 0x78, 0x75, 0x56, 0x5B, 0x4C, 0x41,
  431.   0x61, 0x6C, 0x7B, 0x76, 0x55, 0x58, 0x4F, 0x42,
  432.   0x09, 0x04, 0x13, 0x1E, 0x3D, 0x30, 0x27, 0x2A,
  433.   0xB1, 0xBC, 0xAB, 0xA6, 0x85, 0x88, 0x9F, 0x92,
  434.   0xD9, 0xD4, 0xC3, 0xCE, 0xED, 0xE0, 0xF7, 0xFA,
  435.   0xB7, 0xBA, 0xAD, 0xA0, 0x83, 0x8E, 0x99, 0x94,
  436.   0xDF, 0xD2, 0xC5, 0xC8, 0xEB, 0xE6, 0xF1, 0xFC,
  437.   0x67, 0x6A, 0x7D, 0x70, 0x53, 0x5E, 0x49, 0x44,
  438.   0x0F, 0x02, 0x15, 0x18, 0x3B, 0x36, 0x21, 0x2C,
  439.   0x0C, 0x01, 0x16, 0x1B, 0x38, 0x35, 0x22, 0x2F,
  440.   0x64, 0x69, 0x7E, 0x73, 0x50, 0x5D, 0x4A, 0x47,
  441.   0xDC, 0xD1, 0xC6, 0xCB, 0xE8, 0xE5, 0xF2, 0xFF,
  442.   0xB4, 0xB9, 0xAE, 0xA3, 0x80, 0x8D, 0x9A, 0x97
  443. ])
  444.  
  445. GMul0B = bytes([
  446.   0x00, 0x0B, 0x16, 0x1D, 0x2C, 0x27, 0x3A, 0x31,
  447.   0x58, 0x53, 0x4E, 0x45, 0x74, 0x7F, 0x62, 0x69,
  448.   0xB0, 0xBB, 0xA6, 0xAD, 0x9C, 0x97, 0x8A, 0x81,
  449.   0xE8, 0xE3, 0xFE, 0xF5, 0xC4, 0xCF, 0xD2, 0xD9,
  450.   0x7B, 0x70, 0x6D, 0x66, 0x57, 0x5C, 0x41, 0x4A,
  451.   0x23, 0x28, 0x35, 0x3E, 0x0F, 0x04, 0x19, 0x12,
  452.   0xCB, 0xC0, 0xDD, 0xD6, 0xE7, 0xEC, 0xF1, 0xFA,
  453.   0x93, 0x98, 0x85, 0x8E, 0xBF, 0xB4, 0xA9, 0xA2,
  454.   0xF6, 0xFD, 0xE0, 0xEB, 0xDA, 0xD1, 0xCC, 0xC7,
  455.   0xAE, 0xA5, 0xB8, 0xB3, 0x82, 0x89, 0x94, 0x9F,
  456.   0x46, 0x4D, 0x50, 0x5B, 0x6A, 0x61, 0x7C, 0x77,
  457.   0x1E, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2F,
  458.   0x8D, 0x86, 0x9B, 0x90, 0xA1, 0xAA, 0xB7, 0xBC,
  459.   0xD5, 0xDE, 0xC3, 0xC8, 0xF9, 0xF2, 0xEF, 0xE4,
  460.   0x3D, 0x36, 0x2B, 0x20, 0x11, 0x1A, 0x07, 0x0C,
  461.   0x65, 0x6E, 0x73, 0x78, 0x49, 0x42, 0x5F, 0x54,
  462.   0xF7, 0xFC, 0xE1, 0xEA, 0xDB, 0xD0, 0xCD, 0xC6,
  463.   0xAF, 0xA4, 0xB9, 0xB2, 0x83, 0x88, 0x95, 0x9E,
  464.   0x47, 0x4C, 0x51, 0x5A, 0x6B, 0x60, 0x7D, 0x76,
  465.   0x1F, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2E,
  466.   0x8C, 0x87, 0x9A, 0x91, 0xA0, 0xAB, 0xB6, 0xBD,
  467.   0xD4, 0xDF, 0xC2, 0xC9, 0xF8, 0xF3, 0xEE, 0xE5,
  468.   0x3C, 0x37, 0x2A, 0x21, 0x10, 0x1B, 0x06, 0x0D,
  469.   0x64, 0x6F, 0x72, 0x79, 0x48, 0x43, 0x5E, 0x55,
  470.   0x01, 0x0A, 0x17, 0x1C, 0x2D, 0x26, 0x3B, 0x30,
  471.   0x59, 0x52, 0x4F, 0x44, 0x75, 0x7E, 0x63, 0x68,
  472.   0xB1, 0xBA, 0xA7, 0xAC, 0x9D, 0x96, 0x8B, 0x80,
  473.   0xE9, 0xE2, 0xFF, 0xF4, 0xC5, 0xCE, 0xD3, 0xD8,
  474.   0x7A, 0x71, 0x6C, 0x67, 0x56, 0x5D, 0x40, 0x4B,
  475.   0x22, 0x29, 0x34, 0x3F, 0x0E, 0x05, 0x18, 0x13,
  476.   0xCA, 0xC1, 0xDC, 0xD7, 0xE6, 0xED, 0xF0, 0xFB,
  477.   0x92, 0x99, 0x84, 0x8F, 0xBE, 0xB5, 0xA8, 0xA3
  478. ])
  479.  
  480.  
  481. #-------------------------------------------------------------------------------
  482.  
  483.  
  484. def SubstituteAndShift(State):
  485.   State[0] = SBox[State[0]]
  486.   State[4] = SBox[State[4]]
  487.   State[8] = SBox[State[8]]
  488.   State[12] = SBox[State[12]]
  489.   a = State[1]
  490.   State[1] = SBox[State[5]]
  491.   State[5] = SBox[State[9]]
  492.   State[9] = SBox[State[13]]
  493.   State[13] = SBox[a]
  494.   a = State[2]
  495.   State[2] = SBox[State[10]]
  496.   State[10] = SBox[a]
  497.   a = State[6]
  498.   State[6] = SBox[State[14]]
  499.   State[14] = SBox[a]
  500.   a = State[15]
  501.   State[15] = SBox[State[11]]
  502.   State[11] = SBox[State[7]]
  503.   State[7] = SBox[State[3]]
  504.   State[3] = SBox[a]
  505.  
  506.  
  507. #-------------------------------------------------------------------------------
  508.  
  509.  
  510. def InvSubstituteAndShift(State):
  511.   State[0] = InvSBox[State[0]]
  512.   State[4] = InvSBox[State[4]]
  513.   State[8] = InvSBox[State[8]]
  514.   State[12] = InvSBox[State[12]]
  515.   a = State[13]
  516.   State[13] = InvSBox[State[9]]
  517.   State[9] = InvSBox[State[5]]
  518.   State[5] = InvSBox[State[1]]
  519.   State[1] = InvSBox[a]
  520.   a = State[2]
  521.   State[2] = InvSBox[State[10]]
  522.   State[10] = InvSBox[a]
  523.   a = State[6]
  524.   State[6] = InvSBox[State[14]]
  525.   State[14] = InvSBox[a]
  526.   a = State[3]
  527.   State[3] = InvSBox[State[7]]
  528.   State[7] = InvSBox[State[11]]
  529.   State[11] = InvSBox[State[15]]
  530.   State[15] = InvSBox[a]
  531.  
  532.  
  533. #-------------------------------------------------------------------------------
  534.  
  535.  
  536. def MixColumns(State):
  537.  
  538.   def gmul2(x):
  539.     return x << 1 if x < 128 else ((x << 1) & 255) ^ 0x1b
  540.  
  541.   def gmul3(x):
  542.     return ((x << 1) ^ x) if x < 128 else ((x << 1) & 255) ^ x ^ 0x1b
  543.  
  544.   def MixColumn(State, c):
  545.     Offset = 4 * c
  546.     a = State[Offset + 0]
  547.     b = State[Offset + 1]
  548.     c = State[Offset + 2]
  549.     d = State[Offset + 3]
  550.     State[Offset + 0] = gmul2(a) ^ gmul3(b) ^ c ^ d
  551.     State[Offset + 1] = a ^ gmul2(b) ^ gmul3(c) ^ d
  552.     State[Offset + 2] = a ^ b ^ gmul2(c) ^ gmul3(d)
  553.     State[Offset + 3] = gmul3(a) ^ b ^ c ^ gmul2(d)
  554.  
  555.   for i in range(4):
  556.     MixColumn(State, i)
  557.  
  558.  
  559. #-------------------------------------------------------------------------------
  560.  
  561.  
  562. def InvMixColumns(State):
  563.  
  564.   def gmulE(x):
  565.     return GMul0E[x]
  566.  
  567.   def gmul9(x):
  568.     return GMul09[x]
  569.  
  570.   def gmulD(x):
  571.     return GMul0D[x]
  572.  
  573.   def gmulB(x):
  574.     return GMul0B[x]
  575.  
  576.   def MixColumn(State, c):
  577.     Offset = 4 * c
  578.     a = State[Offset + 0]
  579.     b = State[Offset + 1]
  580.     c = State[Offset + 2]
  581.     d = State[Offset + 3]
  582.     State[Offset + 0] = gmulE(a) ^ gmulB(b) ^ gmulD(c) ^ gmul9(d)
  583.     State[Offset + 1] = gmul9(a) ^ gmulE(b) ^ gmulB(c) ^ gmulD(d)
  584.     State[Offset + 2] = gmulD(a) ^ gmul9(b) ^ gmulE(c) ^ gmulB(d)
  585.     State[Offset + 3] = gmulB(a) ^ gmulD(b) ^ gmul9(c) ^ gmulE(d)
  586.  
  587.   for i in range(4):
  588.     MixColumn(State, i)
  589.  
  590.  
  591. #-------------------------------------------------------------------------------
  592.  
  593.  
  594. def AdvanceRoundKey(Key, NextRoundNumber):
  595.   a = RoundConstantBytes[NextRoundNumber]
  596.   a ^= SBox[Key[13]]
  597.   b = SBox[Key[14]]
  598.   c = SBox[Key[15]]
  599.   d = SBox[Key[12]]
  600.   Offset = 0
  601.   for j in range(4):
  602.     a ^= Key[Offset + 0]
  603.     b ^= Key[Offset + 1]
  604.     c ^= Key[Offset + 2]
  605.     d ^= Key[Offset + 3]
  606.     Key[Offset + 0] = a
  607.     Key[Offset + 1] = b
  608.     Key[Offset + 2] = c
  609.     Key[Offset + 3] = d
  610.     Offset += 4
  611.  
  612.  
  613. #-------------------------------------------------------------------------------
  614.  
  615.  
  616. def AddRoundKey(Key, State):
  617.   for i in range(16):
  618.     State[i] ^= Key[i]
  619.  
  620.  
  621. #-------------------------------------------------------------------------------
  622.  
  623.  
  624. def AESEncryptBlock(Key, Block):
  625.   Result = bytearray(Block)
  626.   W = bytearray(Key)
  627.   AddRoundKey(W, Result)
  628.   for i in range(1, 11):
  629.     AdvanceRoundKey(W, i)
  630.     SubstituteAndShift(Result)
  631.     if i < 10:
  632.       MixColumns(Result)
  633.     AddRoundKey(W, Result)
  634.   return Result
  635.  
  636.  
  637. #-------------------------------------------------------------------------------
  638.  
  639.  
  640. def AESDecryptBlock(Key, Block):
  641.   Result = bytearray(Block)
  642.   W = bytearray(Key)
  643.   for j in range(1, 11):
  644.     AdvanceRoundKey(W, j)
  645.   AddRoundKey(W, Result)
  646.   for i in range(10, 0, -1):
  647.     W = bytearray(Key)
  648.     for j in range(1, i):
  649.       AdvanceRoundKey(W, j)
  650.     InvSubstituteAndShift(Result)
  651.     AddRoundKey(W, Result)
  652.     if i > 1:
  653.       InvMixColumns(Result)
  654.   return Result
  655.  
  656.  
  657. #-------------------------------------------------------------------------------
  658.  
  659.  
  660. def NextRoundKey(KeyN, RoundNPlus1):
  661.   r = bytearray(KeyN)
  662.   g = [SBox[x] for x in KeyN[13:16] + KeyN[12:13]]
  663.   g[0] ^= RoundConstantBytes[RoundNPlus1]
  664.   for i in range(4):
  665.     r[i] = KeyN[i] ^ g[i]
  666.     d = i
  667.     for j in range(3):
  668.       r[d + 4] = r[d] ^ KeyN[d + 4]
  669.       d += 4
  670.   return r
  671.  
  672.  
  673. #-------------------------------------------------------------------------------
  674.  
  675.  
  676. def AESECBEncryptMessage(Key, Message):
  677.   Result = bytearray(len(Message))
  678.   Addr = 0
  679.   while Addr < len(Message):
  680.     M = bytearray(Message[Addr : Addr + 16])
  681.     M.extend(bytearray(16 - len(M)))
  682.     E = AESEncryptBlock(Key, M)
  683.     Result[Addr : Addr + 16] = E
  684.     Addr += 16
  685.   return Result
  686.  
  687.  
  688. #-------------------------------------------------------------------------------
  689.  
  690.  
  691. def AESECBDecryptMessage(Key, Message, Length=None):
  692.   if Length is None:
  693.     Length = len(Message)
  694.   Result = bytearray(Length)
  695.   Addr = 0
  696.   while Addr + 16 <= len(Message):
  697.     M = bytearray(Message[Addr : Addr + 16])
  698.     D = AESDecryptBlock(Key, M)
  699.     DLength = min(16, Length - Addr)
  700.     D = D[:DLength]
  701.     Result[Addr : Addr + DLength] = D
  702.     Addr += 16
  703.   return Result
  704.  
  705.  
  706. #-------------------------------------------------------------------------------
  707.  
  708.  
  709. def CMACSubKeys(Key):
  710.   """
  711.  Generate subkeys K1 and K2 for use on the final block.
  712.  
  713.  K1 is used on a whole final block. K2 is used on a short final block which
  714.  has been padded with a bit 1 and a run of zero or more bit 0s.
  715.  """
  716.   def NextSubKey(Key):
  717.     Result = bytearray(16)
  718.     c = 0
  719.     for i in reversed(range(len(Result))):
  720.       e = (Key[i] << 1) | c
  721.       c = e >> 8
  722.       Result[i] = e & 255
  723.     if c:
  724.       Result[15] ^= 0x87
  725.     return Result
  726.   X = AESEncryptBlock(Key, bytearray(16))
  727.   K1 = NextSubKey(X)
  728.   K2 = NextSubKey(K1)
  729.   return K1, K2
  730.  
  731.  
  732. #-------------------------------------------------------------------------------
  733.  
  734.  
  735. def AESCMAC(Message, Key, Debug=False):
  736.   K1, K2 = CMACSubKeys(Key)
  737.   T = bytearray(16)
  738.   BlockEndIx = 16
  739.   while BlockEndIx < len(Message):
  740.     Mi = bytearray(Message[BlockEndIx - 16 : BlockEndIx])
  741.     XorAWithB(T, Mi)
  742.     T = AESEncryptBlock(Key, T)
  743.     BlockEndIx += 16
  744.   if BlockEndIx == len(Message):
  745.     Mi = bytearray(Message[BlockEndIx - 16 : BlockEndIx])
  746.     XorAWithB(T, Mi)
  747.     XorAWithB(T, K1)
  748.     T = AESEncryptBlock(Key, T)
  749.   else:
  750.     Mi = bytearray(Message[BlockEndIx - 16:])
  751.     PaddingLength = 16 - len(Mi)
  752.     Mi.extend(bytearray([0x80]))
  753.     Mi.extend(bytearray(PaddingLength - 1))
  754.     XorAWithB(T, Mi)
  755.     XorAWithB(T, K2)
  756.     T = AESEncryptBlock(Key, T)
  757.   return T
  758.  
  759.  
  760. #-------------------------------------------------------------------------------
  761. # GCM functions
  762. #-------------------------------------------------------------------------------
  763.  
  764.  
  765. def GaloisMultInt128(X, Y):
  766.   """
  767.  Multiply X and Y using Galois multiplation in GF(2^8).
  768.  
  769.  X and Y are integers rather than byte arrays.
  770.  """
  771.   R = 0b11100001 << 120
  772.   Z = 0
  773.   V = Y
  774.   Mask = 1 << 127
  775.   for i in range(128):
  776.     if X & Mask:
  777.       Z ^= V
  778.     if V & 1:
  779.       V = (V >> 1) ^ R
  780.     else:
  781.       V >>= 1
  782.     Mask >>= 1
  783.   return Z
  784.  
  785.  
  786. #-------------------------------------------------------------------------------
  787. # AES in GCM mode
  788. #-------------------------------------------------------------------------------
  789.  
  790.  
  791. class AESGCMCipher (object):
  792.  
  793.   def __init__(self, Key, IV):
  794.  
  795.     self.CipherFn = AESEncryptBlock
  796.     NumTagBits = 128 # May be 128, 120, 112, 104, 96, 64 or 32
  797.     self.NumTagBytes = (NumTagBits + 7) >> 3
  798.  
  799.     self.Key = bytes(Key)
  800.     self.IV = bytes(IV)
  801.     self.AuthTag = None
  802.  
  803.   def IncrementalGHash(self, H, Y, Block):
  804.     # H is the hash subkey as a 128-bit integer and
  805.     # Y is the hash accumulator as a 128-bit integer.
  806.     # Block is an array of 16 bytes.
  807.     X = BytesToIntBE(Block)
  808.     NextY = GaloisMultInt128(Y ^ X, H)
  809.     return NextY
  810.  
  811.   def IntGHash(H, Data):
  812.     Y = 0
  813.     for Addr in range(0, len(Data) - 15, 16):
  814.       Y = IncrementalGHash(H, Y, Data[Addr : Addr + 16])
  815.     return Y
  816.  
  817.   def OutputBytes(self, AADStream, MsgStream, Mode):
  818.  
  819.     # Mode is 1 for encryption, 2 for decryption and 3 for verification.
  820.  
  821.     def Inc32BE(X):
  822.       c = (X[-4] << 24) + (X[-3] << 16) + (X[-2] << 8) + X[-1] + 1
  823.       X[-4:] = [(c >> 24) & 0xFF, (c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF]
  824.  
  825.     H = BytesToIntBE(self.CipherFn(self.Key, bytes(16)))
  826.  
  827.     if len(self.IV) == 12: # 96 bits
  828.       J0 = self.IV + b"\x00\x00\x00\x01"
  829.     else:
  830.       # Pad (our copy of) IV to a multiple of 128 bits (16 bytes),
  831.       # then 64 bits (8 bytes) of zeros, followed by the length of
  832.       # IV in bits as a 64 bit big-endian integer.
  833.       p = (16 - len(self.IV)) & 15
  834.       IV1 = self.IV + bytes(p + 8) + IntToBytesBE(len(IV) * 8, 8)
  835.       J0 = IntToBytesBE(IntGHash(H, IV1), 16)
  836.  
  837.     AADLength = 0
  838.     Y = 0
  839.  
  840.     if AADStream is not None:
  841.       for Block in StreamAsBlocks(AADStream, 16):
  842.         A = Block
  843.         if len(A) > 0:
  844.           AADLength += len(A)
  845.           if len(A) < 16:
  846.             A = A + bytes(16 - len(A))
  847.           Y = self.IncrementalGHash(H, Y, A)
  848.  
  849.     MsgLength = 0
  850.     CB = bytearray(J0)
  851.  
  852.     if MsgStream is not None:
  853.       for Block in StreamAsBlocks(MsgStream, 16):
  854.         A = bytearray(Block)
  855.         if len(A) > 0:
  856.           MsgLength += len(A)
  857.           Inc32BE(CB)
  858.           B = self.CipherFn(self.Key, CB)
  859.           if Mode == 1:
  860.             XorAWithB(A, B[:len(A)])
  861.             Y = self.IncrementalGHash(H, Y, A + bytes(16 - len(A)))
  862.           else:
  863.             Y = self.IncrementalGHash(H, Y, A + bytes(16 - len(A)))
  864.             XorAWithB(A, B[:len(A)])
  865.           if Mode != 3:
  866.             yield A
  867.  
  868.     A = IntToBytesBE(AADLength * 8, 8) + IntToBytesBE(MsgLength * 8, 8)
  869.     Y = self.IncrementalGHash(H, Y, A)
  870.     A = self.CipherFn(self.Key, J0)
  871.     XorAWithB(A, IntToBytesBE(Y, 16))
  872.     self.AuthTag = bytes(A[:self.NumTagBytes])
  873.  
  874.     if Mode == 3:
  875.       yield self.AuthTag
  876.  
  877.   def Encrypt(self, AADStream, PlainStream):
  878.     self.AuthTag = None
  879.     B = self.OutputBytes(AADStream, PlainStream, 1)
  880.     S = IterableToStream(B)
  881.     return S
  882.  
  883.   def Decrypt(self, AADStream, CipherStream):
  884.     self.AuthTag = None
  885.     B = self.OutputBytes(AADStream, CipherStream, 2)
  886.     S = IterableToStream(B)
  887.     return S
  888.  
  889.   def Verify(self, AADStream, CipherStream, AuthTag):
  890.     self.AuthTag = None
  891.     B = self.OutputBytes(AADStream, CipherStream, 3)
  892.     T = next(B)
  893.     IsValid = T == AuthTag
  894.     return IsValid
  895.  
  896.   def GMAC(self, AADStream):
  897.     self.AuthTag = None
  898.     B = self.OutputBytes(AADStream, None, 3)
  899.     G = next(B)
  900.     return G
  901.  
  902.  
  903. #-------------------------------------------------------------------------------
  904. # Hash functions
  905. #-------------------------------------------------------------------------------
  906.  
  907.  
  908. def SHA_256(Message):
  909.   """
  910.  Compute the SHA-256 hash of a message.
  911.  """
  912.  
  913.   WMask = 0xFFFFFFFF
  914.  
  915.   def PaddedMsgBlocks(Message):
  916.     # The padding is such that the padded message is always a multiple of
  917.     # 512 bits (64 bytes) and the padding contains a bit one followed by
  918.     # zero or more bit zeros, terminated by a 64-bit (8 byte) big-endian
  919.     # representation of the unpadded message length in bits.
  920.     Addr = 0
  921.     while Addr + 64 <= len(Message):
  922.       yield bytes(Message[Addr : Addr + 64])
  923.       Addr += 64
  924.     Appendix = (b'\x80' + bytes((56 - len(Message) - 1) & 63) +
  925.         IntToBytesBE(len(Message) * 8, 8))
  926.     FinalBlockOrTwo = bytes(Message[Addr:]) + Appendix
  927.     yield FinalBlockOrTwo[:64]
  928.     if len(FinalBlockOrTwo) > 64:
  929.       yield FinalBlockOrTwo[64:]
  930.  
  931.   def rr(x, n):
  932.     return ((x >> n) | (x << (32 - n))) & WMask
  933.  
  934.   # Hash values, initialised to the first 32 bits of the fractional parts of
  935.   # the square roots of the first eight primes, {2, 3, 5, 7, 11, 13, 17, 19}
  936.   H = [
  937.     0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  938.     0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
  939.   ]
  940.  
  941.   # Round constants (first 32 bits of the fractional parts of the cube roots
  942.   # of the first sixty-four primes)
  943.   K = (
  944.     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  945.     0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  946.     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  947.     0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  948.     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  949.     0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  950.     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  951.     0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  952.     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  953.     0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  954.     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  955.     0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  956.     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  957.     0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  958.     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  959.     0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  960.   )
  961.  
  962.   # Message schedule of 64 words of 32 bits each.
  963.   W = list([None] * 64)
  964.  
  965.   for B in PaddedMsgBlocks(Message):
  966.  
  967.     # Stuff the message block into the first 16 entries.
  968.     for i in range(16):
  969.       j = i << 2
  970.       W[i] = (B[j] << 24) + (B[j + 1] << 16) + (B[j + 2] << 8) + B[j + 3]
  971.  
  972.     # Fill the rest of the schedule with big and little sigma
  973.     for i in range(16, 64):
  974.       x = W[i - 15]
  975.       s0 = rr(x, 7) ^ rr(x, 18) ^ (x >> 3)
  976.       x = W[i - 2]
  977.       s1 = rr(x, 17) ^ rr(x, 19) ^ (x >> 10)
  978.       W[i] = (W[i - 16] + s0 + W[i - 7] + s1) & WMask
  979.  
  980.     # Initialise the working variables.
  981.     a, b, c, d, e, f, g, h = H[0], H[1], H[2], H[3], H[4], H[5], H[6], H[7]
  982.  
  983.     # Compression
  984.     for i in range(64):
  985.       S1 = rr(e, 6) ^ rr(e, 11) ^ rr(e, 25)
  986.       Ch = (e & f) ^ (~e & g)
  987.       T1 = h + S1 + Ch + K[i] + W[i]
  988.       S0 = rr(a, 2) ^ rr(a, 13) ^ rr(a, 22)
  989.       Maj = (a & b) ^ (a & c) ^ (b & c)
  990.       T2 = S0 + Maj
  991.       h, g, f, e = g, f, e, (d + T1) & WMask
  992.       d, c, b, a = c, b, a, (T1 + T2) & WMask
  993.  
  994.     # Arithmetically add the working variables to the 32-bit hash values.
  995.     for i, x in enumerate((a, b, c, d, e, f, g, h)):
  996.       H[i] = (H[i] + x) & WMask
  997.  
  998.   Result = bytearray()
  999.   for x in H:
  1000.     Result.extend(IntToBytesBE(x, 4))
  1001.  
  1002.   return bytes(Result)
  1003.  
  1004.  
  1005. #-------------------------------------------------------------------------------
  1006.  
  1007.  
  1008. def HMAC_SHA_256(Key, Message):
  1009.   """
  1010.  Compute a keyed-hash message authentication code.
  1011.  """
  1012.  
  1013.   # The block size for SHA-256 is 512 bits (64 bytes).
  1014.   BlockSizeInBytes = 64
  1015.  
  1016.   # Procrastinate.
  1017.   if len(Key) > BlockSizeInBytes:
  1018.     KeyToUse = SHA_256(Key)
  1019.   else:
  1020.     KeyToUse = bytes(Key) + bytes(BlockSizeInBytes - len(Key))
  1021.  
  1022.   InnerKeyPad = bytearray(b'\x36' * BlockSizeInBytes)
  1023.   XorAWithB(InnerKeyPad, KeyToUse)
  1024.   OuterKeyPad = bytearray(b'\x5C' * BlockSizeInBytes)
  1025.   XorAWithB(OuterKeyPad, KeyToUse)
  1026.  
  1027.   Result = SHA_256(OuterKeyPad + SHA_256(InnerKeyPad + bytes(Message)))
  1028.  
  1029.   # The hash size is 256 bit (32 bytes).
  1030.   return Result
  1031.  
  1032.  
  1033. #-------------------------------------------------------------------------------
  1034.  
  1035.  
  1036. def PBKDF2(PRF, Password, Salt, Count, DerivedKeyLength):
  1037.   """
  1038.  Derive an encryption key from a password.
  1039.  """
  1040.  
  1041.   HashLength = len(PRF(b"", b""))
  1042.  
  1043.   def F(P, S, Count, i):
  1044.     U = PRF(P, S + IntToBytesBE(i, 4))
  1045.     Result = bytearray(U)
  1046.     for j in range(2, Count + 1):
  1047.       U = PRF(P, U)
  1048.       XorAWithB(Result, U)
  1049.     return Result
  1050.  
  1051.   if DerivedKeyLength >= (1 << 32):
  1052.     raise Exception("The derived key length is too long!")
  1053.   if DerivedKeyLength < 1:
  1054.     raise Exception("The derived key length must be at least 1 byte.")
  1055.   if Count < 1:
  1056.     raise Exception("The PBKDF2 interation count must be at least 1.")
  1057.  
  1058.   Result = bytes()
  1059.   P = bytes(Password)
  1060.   S = bytes(Salt)
  1061.  
  1062.   i = 1
  1063.   DKLengthRemaining = DerivedKeyLength
  1064.  
  1065.   while len(Result) < DerivedKeyLength:
  1066.     Ti = F(P, S, Count, i)
  1067.     if DKLengthRemaining < HashLength:
  1068.       Ti = Ti[:DKLengthRemaining]
  1069.     Result = Result + Ti
  1070.     DKLengthRemaining -= HashLength
  1071.     i += 1
  1072.  
  1073.   return Result
  1074.  
  1075.  
  1076. #-------------------------------------------------------------------------------
  1077. # File encryption
  1078. #-------------------------------------------------------------------------------
  1079.  
  1080.  
  1081. def Encrypt(Password, AAD, PlainStream, OutputStream):
  1082.  
  1083.   IV = os.urandom(12)
  1084.   Salt = os.urandom(32)
  1085.   NumIterations = 5000
  1086.   Key = PBKDF2(HMAC_SHA_256, Password.encode("utf8"), Salt, NumIterations, 16)
  1087.  
  1088.   AADLength = 0 if AAD is None else len(AAD)
  1089.  
  1090.   HdrLines = [
  1091.     "#ENCRYPTED#",
  1092.     "[File]",
  1093.     "HDRSIZE=",
  1094.     "AADSIZE={}".format(AADLength),
  1095.     "FORMAT=CONCATENATED ACT",
  1096.     "VERSION=1.0",
  1097.     "[Password]",
  1098.     "KDF=PBKDF2",
  1099.     "PRF=HMAC-SHA-256",
  1100.     "ITERATIONS={}".format(NumIterations),
  1101.     "SALT={}".format(binascii.hexlify(Salt).decode("utf8")),
  1102.     "[Cipher]",
  1103.     "CIPHER=AES-128",
  1104.     "MODE=GCM",
  1105.     "IV=" + binascii.hexlify(IV).decode("utf8")
  1106.   ]
  1107.  
  1108.   L0 = sum((len(Line.encode("utf8")) + 1 for Line in HdrLines)) + 1
  1109.   L = L0
  1110.   LastL = -1
  1111.   while L != LastL:
  1112.     LastL = L
  1113.     L = L0 + len(str(LastL))
  1114.   HdrLines[HdrLines.index("HDRSIZE=")] += str(L)
  1115.  
  1116.   Hdr = chr(10).join(HdrLines + [chr(0)]).encode("utf8")
  1117.  
  1118.   Cipher = AESGCMCipher(Key, IV)
  1119.   AADStream = None if AAD is None or AAD == b"" else io.BytesIO(AAD)
  1120.   S = Cipher.Encrypt(AADStream, PlainStream)
  1121.  
  1122.   OutputStream.write(Hdr)
  1123.   if AAD is not None:
  1124.     OutputStream.write(AAD)
  1125.  
  1126.   HaveEOF = False
  1127.   while not HaveEOF:
  1128.     Chunk = S.read(65536)
  1129.     if len(Chunk) > 0:
  1130.       OutputStream.write(Chunk)
  1131.     else:
  1132.       HaveEOF = True
  1133.   S.close()
  1134.   OutputStream.write(Cipher.AuthTag)
  1135.  
  1136.  
  1137. #-------------------------------------------------------------------------------
  1138.  
  1139.  
  1140. def Decrypt(Password, InputStream, OutputStream):
  1141.  
  1142.   Result = None
  1143.   HdrBytesRead = 0
  1144.   MagicLine = b"#ENCRYPTED#\x0A"
  1145.  
  1146.   Magic = InputStream.read(len(MagicLine))
  1147.   if Magic != MagicLine:
  1148.     raise FileError("The encrypted file is in an unrecognised format.")
  1149.   HdrBytesRead += len(MagicLine)
  1150.  
  1151.   Assertions = {
  1152.     "FILE": {
  1153.       "FORMAT": "CONCATENATED ACT",
  1154.       "VERSION": "1.0",
  1155.       "HDRSIZE": None,
  1156.       "AADSIZE": None
  1157.     },
  1158.     "PASSWORD": {
  1159.       "KDF": "PBKDF2",
  1160.       "PRF": "HMAC-SHA-256",
  1161.       "ITERATIONS": None,
  1162.       "SALT": None
  1163.     },
  1164.     "CIPHER": {
  1165.       "CIPHER": "AES-128",
  1166.       "MODE": "GCM",
  1167.       "IV": None
  1168.     }
  1169.   }
  1170.  
  1171.   Sections = {
  1172.     "FILE": {},
  1173.     "PASSWORD": {},
  1174.     "CIPHER": {},
  1175.     "OTHER": {},
  1176.   }
  1177.   Section = Sections["OTHER"]
  1178.   IsInHeader = True
  1179.  
  1180.   while IsInHeader:
  1181.  
  1182.     LineBytes = bytearray()
  1183.     IsEOL = False
  1184.     while not IsEOL:
  1185.       Ch = InputStream.read(1)
  1186.       HdrBytesRead += 1
  1187.       if Ch == b'\x0A':
  1188.         IsEOL = True
  1189.       elif Ch == b'\x00':
  1190.         IsEOL = True
  1191.         IsInHeader = False
  1192.       else:
  1193.         LineBytes.append(ord(Ch))
  1194.  
  1195.     Line = LineBytes.decode("utf8").strip()
  1196.  
  1197.     if Line[:1] + Line[-1:] == "[]":
  1198.  
  1199.       SectionName = Line[1:-1].upper()
  1200.       if SectionName in Sections:
  1201.         Section = Sections[SectionName]
  1202.       else:
  1203.         Section = Sections["OTHER"]
  1204.  
  1205.     elif '=' in Line:
  1206.  
  1207.       K, V = Line.split('=', 1)
  1208.       K = K.strip().upper()
  1209.       V = V.strip()
  1210.       Section[K] = V
  1211.  
  1212.   for ASectionName, ASection in Assertions.items():
  1213.     if ASectionName in Sections:
  1214.       Section = Sections[ASectionName]
  1215.       for AK, AV in ASection.items():
  1216.         if AK in Section:
  1217.           if AV is not None:
  1218.             V = Section[AK]
  1219.             if V != AV:
  1220.               raise FileError(("Section {} requires {} to be " +
  1221.                   "set to {}.").format(ASectionName, AK, AV))
  1222.         else:
  1223.           if AV is not None:
  1224.             raise FileError(("Section {} requires " +
  1225.                 "{}={}.").format(ASectionName, AK, AV))
  1226.           else:
  1227.             raise FileError(("Section {} requires {} to be " +
  1228.                 "defined.").format(ASectionName, AK))
  1229.     else:
  1230.       raise FileError(("INTERNAL: Required section {} " +
  1231.           "is missiong.").format(ASectionName))
  1232.  
  1233.   HLStr = Sections["FILE"]["HDRSIZE"]
  1234.   try:
  1235.     HdrLength = int(HLStr)
  1236.   except (ValueError) as E:
  1237.     raise FileError("Bad HDRSIZE: " + str(E))
  1238.   if HdrBytesRead != HdrLength:
  1239.     raise FileError("HDRSIZE not consistent with measured length: " + str(E))
  1240.  
  1241.   ALStr = Sections["FILE"]["AADSIZE"]
  1242.   try:
  1243.     AADLength = int(ALStr)
  1244.   except (ValueError) as E:
  1245.     raise FileError("Bad AADSIZE: " + str(E))
  1246.   if not (0 <= AADLength <= (1 << 30)):
  1247.     raise FileError("AADSIZE is given as {}, " +
  1248.         "an outrageous value.".format(AADLength))
  1249.  
  1250.   NIStr = Sections["PASSWORD"]["ITERATIONS"]
  1251.   try:
  1252.     NumIterations = int(NIStr)
  1253.   except (binascii.Error) as E:
  1254.     raise FileError("Bad ITERATIONS: " + str(E))
  1255.  
  1256.   SaltStr = Sections["PASSWORD"]["SALT"]
  1257.   try:
  1258.     Salt = binascii.unhexlify(SaltStr.encode("utf8"))
  1259.   except (binascii.Error) as E:
  1260.     raise FileError("Bad SALT: " + str(E))
  1261.  
  1262.   IVStr = Sections["CIPHER"]["IV"]
  1263.   try:
  1264.     IV = binascii.unhexlify(IVStr.encode("utf8"))
  1265.   except (binascii.Error) as E:
  1266.     raise FileError("Bad IV: " + str(E))
  1267.  
  1268.   if OutputStream is not None:
  1269.     try:
  1270.       OutputStream.seek(0)
  1271.       OutputStream.write(b"?")
  1272.       OutputStream.seek(0)
  1273.       OutputStream.truncate()
  1274.     except (Exception) as E:
  1275.       raise FileError('Unable to write to output file: ' + E)
  1276.  
  1277.   AADStart = HdrLength
  1278.   TagLength = 16 # 128 bits
  1279.   CipherStart = AADStart + AADLength
  1280.  
  1281.   AADStream = Substream(InputStream, AADStart, AADLength)
  1282.   CipherAndTagStream = Substream(InputStream, CipherStart)
  1283.   CipherStreamTB = StreamSansTail(CipherAndTagStream, TagLength)
  1284.  
  1285.   Key = PBKDF2(HMAC_SHA_256, Password.encode("utf8"), Salt, NumIterations, 16)
  1286.  
  1287.   Cipher = AESGCMCipher(Key, IV)
  1288.   CStream = Cipher.Decrypt(AADStream, CipherStreamTB)
  1289.   HaveEOF = False
  1290.   while not HaveEOF:
  1291.     Chunk = CStream.read(65536)
  1292.     if len(Chunk) > 0:
  1293.       if OutputStream is not None:
  1294.         OutputStream.write(Chunk)
  1295.     else:
  1296.       HaveEOF = True
  1297.   CStream.close()
  1298.  
  1299.   Tag = CipherStreamTB.readtail()
  1300.  
  1301.   if Tag != Cipher.AuthTag:
  1302.     if OutputStream is not None:
  1303.       OutputStream.seek(0)
  1304.       OutputStream.truncate()
  1305.     return None
  1306.   else:
  1307.     AADStream.seek(0)
  1308.     return AADStream
  1309.  
  1310.  
  1311. #-------------------------------------------------------------------------------
  1312. # Diagnostics
  1313. #-------------------------------------------------------------------------------
  1314.  
  1315.  
  1316. def PrintMessage(Message, Name):
  1317.   def SafeChr(Code):
  1318.     return chr(Code) if 32 <= Code <= 126 else '.'
  1319.   print(("State:" if Name is None else Name) + ":")
  1320.   if Message is not None:
  1321.     M = bytearray(Message)
  1322.     for i in range((len(M) + 15) >> 4):
  1323.       Addr = 16 * i
  1324.       Row = M[Addr : Addr + 16]
  1325.       LWs = [Row[4 * j : 4 * (j + 1)] for j in range(4) if 4 * j < len(Row)]
  1326.       RowHex = ".".join(["".join(["{:02x}".format(x) for x in L]) for L in LWs])
  1327.       RowChr = "".join(SafeChr(x) for x in Row)
  1328.       print("  {:04x}: {:35} {:16}".format(Addr, RowHex, RowChr))
  1329.     print("  {:04x}:".format((len(M))))
  1330.   else:
  1331.     print("  [None]")
  1332.  
  1333.  
  1334. #-------------------------------------------------------------------------------
  1335.  
  1336.  
  1337. def Test():
  1338.  
  1339.   XBytes = binascii.unhexlify
  1340.  
  1341.   def HexBStr(M):
  1342.     if len(M) > 0:
  1343.       return binascii.hexlify(M).decode("utf8")
  1344.     else:
  1345.       return "(empty string)"
  1346.  
  1347.   def MatchStr(M, Ref):
  1348.     if M == Ref:
  1349.       return "\x1b[32;1mOK\x1b[39;22m"
  1350.     else:
  1351.       return "\x1b[31;1mFAIL\x1b[39;22m"
  1352.  
  1353.   def HexLines(Block, Name=None, NameFieldWidth=None):
  1354.     Lines = []
  1355.     fw = NameFieldWidth if NameFieldWidth is not None else 0
  1356.     if Name is not None and len(Name) > 0:
  1357.       L = Name + ":"
  1358.       if NameFieldWidth is None:
  1359.         L = L + " "
  1360.       L = "{:<{}}".format(L, fw)
  1361.     else:
  1362.       L = " " * fw
  1363.     Blanks = " " * len(L)
  1364.     w = 16
  1365.     p = 0
  1366.     if len(Block) > 0:
  1367.       while p < len(Block):
  1368.         B = HexBStr(Block[p : p + w])
  1369.         Padding = " " * (2 * w - len(B))
  1370.         Lines.append(L + B + Padding)
  1371.         L = Blanks
  1372.         p += w
  1373.     else:
  1374.       B = HexBStr(Block[p : p + w])
  1375.       Padding = " " * (2 * w - len(B))
  1376.       Lines.append(L + B + Padding)
  1377.     return Lines
  1378.  
  1379.   def PrintBlock(Block, Name=None, NameFieldWidth=None):
  1380.     print("\n".join(HexLines(Block, Name, NameFieldWidth)))
  1381.  
  1382.   def PrintAndCheckBlock(Block, Ref, Name=None, NameFieldWidth=None):
  1383.     Lines = HexLines(Block, Name, NameFieldWidth)
  1384.     Lines[-1] += " " + MatchStr(Block, Ref)
  1385.     print("\n".join(Lines))
  1386.     if Block != Ref:
  1387.       Lines = HexLines(Ref, Name, NameFieldWidth)
  1388.       Lines[0] = "\x1b[36m" + Lines[0]
  1389.       Lines[-1] += " Ref\x1b[39;22m"
  1390.       print("\n".join(Lines))
  1391.  
  1392.   print("AES-128\n")
  1393.   # Example from FIPS PUBS 197
  1394.   # C.1: AES-128 (Nk=4, Nr=10)
  1395.   M = XBytes("00112233445566778899aabbccddeeff")
  1396.   K = XBytes("000102030405060708090a0b0c0d0e0f")
  1397.   RefC = XBytes("69c4e0d86a7b0430d8cdb78070b4c55a")
  1398.   w = 12
  1399.   PrintBlock(K, "Key", w)
  1400.   PrintBlock(M, "Message", w)
  1401.   C = AESEncryptBlock(K, M)
  1402.   PrintAndCheckBlock(C, RefC, "Encrypted", w)
  1403.   R = AESDecryptBlock(K, RefC)
  1404.   PrintAndCheckBlock(R, M, "Decrypted", w)
  1405.  
  1406.   print("\nCMAC Subkeys\n")
  1407.   # Example from NIST Special Publication 800-38B
  1408.   # D.1: AES-128, Subkey Generation
  1409.   K = XBytes("2b7e151628aed2a6abf7158809cf4f3c")
  1410.   RefZ = XBytes("7df76b0c1ab899b33e42f047b91b546f")
  1411.   RefK1 = XBytes("fbeed618357133667c85e08f7236a8de")
  1412.   RefK2 = XBytes("f7ddac306ae266ccf90bc11ee46d513b")
  1413.   w = 12
  1414.   PrintBlock(K, "Key", w)
  1415.   Z = AESEncryptBlock(K, b"\x00" * 16)
  1416.   PrintAndCheckBlock(Z, RefZ, "CIPH_K(0)", w)
  1417.   K1, K2 = CMACSubKeys(K)
  1418.   PrintAndCheckBlock(K1, RefK1, "K1", w)
  1419.   PrintAndCheckBlock(K2, RefK2, "K2", w)
  1420.  
  1421.   print("\nAES-128 CMAC\n")
  1422.   # Example from NIST Special Publication 800-38B
  1423.   # D.1: AES-128, Examples 1 to 4
  1424.   K = XBytes("2b7e151628aed2a6abf7158809cf4f3c")
  1425.   w = 8
  1426.   PrintBlock(K, "Key", w)
  1427.   Examples = [
  1428.     ("0", XBytes(""),
  1429.         XBytes("bb1d6929e95937287fa37d129b756746")),
  1430.     ("128", XBytes("6bc1bee22e409f96e93d7e117393172a"),
  1431.         XBytes("070a16b46b4d4144f79bdd9dd04a287c")),
  1432.     ("320", XBytes("6bc1bee22e409f96e93d7e117393172a"
  1433.                    "ae2d8a571e03ac9c9eb76fac45af8e51"
  1434.                    "30c81c46a35ce411"),
  1435.         XBytes("dfa66747de9ae63030ca32611497c827")),
  1436.     ("512", XBytes("6bc1bee22e409f96e93d7e117393172a"
  1437.                    "ae2d8a571e03ac9c9eb76fac45af8e51"
  1438.                    "30c81c46a35ce411e5fbc1191a0a52ef"
  1439.                    "f69f2445df4f9b17ad2b417be66c3710"),
  1440.         XBytes("51f0bebf7e3b9d92fc49741779363cfe"))
  1441.   ]
  1442.   for StrName, M, RefT in Examples:
  1443.     PrintBlock(M, "M" + StrName, w)
  1444.     T = AESCMAC(M, K)
  1445.     PrintAndCheckBlock(T, RefT, "T" + StrName, w)
  1446.  
  1447.   print("\nAES-128 GCM\n ")
  1448.   # Example from MACsec GCM-AES Test Vectors (April 11, 2011)
  1449.   # 2.4.1: 54-byte Packet Encryption Using GCM-AES-128
  1450.   K = XBytes("071B113B0CA743FECCCF3D051F737382")
  1451.   IV = XBytes("F0761E8DCD3D000176D457ED")
  1452.   A = XBytes("E20106D7CD0DF0761E8DCD3D88E54C2A76D457ED")
  1453.   P = XBytes("08000F101112131415161718191A1B1C"
  1454.              "1D1E1F202122232425262728292A2B2C"
  1455.              "2D2E2F30313233340004")
  1456.   RefC = XBytes("13B4C72B389DC5018E72A171DD85A5D3"
  1457.                 "752274D3A019FBCAED09A425CD9B2E1C"
  1458.                 "9B72EEE7C9DE7D52B3F3")
  1459.   RefT = XBytes("D6A5284F4A6D3FE22A5D6C2B960494C3")
  1460.   w = 8
  1461.   PrintBlock(K, "K", w)
  1462.   PrintBlock(IV, "IV", w)
  1463.   PrintBlock(A, "A", w)
  1464.   PrintBlock(P, "P", w)
  1465.   Cipher = AESGCMCipher(K, IV)
  1466.   # Encrypt
  1467.   AADStream = io.BytesIO(A)
  1468.   PlainStream = io.BytesIO(P)
  1469.   S = Cipher.Encrypt(AADStream, PlainStream)
  1470.   OutputStream = io.BytesIO()
  1471.   HaveEOF = False
  1472.   while not HaveEOF:
  1473.     Chunk = S.read(65536)
  1474.     if len(Chunk) > 0:
  1475.       OutputStream.write(Chunk)
  1476.     else:
  1477.       HaveEOF = True
  1478.   S.close()
  1479.   OutputStream.seek(0)
  1480.   C = OutputStream.read()
  1481.   OutputStream.close()
  1482.   T = Cipher.AuthTag
  1483.   PrintAndCheckBlock(C, RefC, "C", w)
  1484.   PrintAndCheckBlock(T, RefT, "T", w)
  1485.   # Decrypt
  1486.   AADStream.seek(0)
  1487.   CipherStream = io.BytesIO(RefC)
  1488.   S = Cipher.Decrypt(AADStream, CipherStream)
  1489.   OutputStream = io.BytesIO()
  1490.   HaveEOF = False
  1491.   while not HaveEOF:
  1492.     Chunk = S.read(65536)
  1493.     if len(Chunk) > 0:
  1494.       OutputStream.write(Chunk)
  1495.     else:
  1496.       HaveEOF = True
  1497.   S.close()
  1498.   OutputStream.seek(0)
  1499.   R = OutputStream.read()
  1500.   OutputStream.close()
  1501.   T = Cipher.AuthTag
  1502.   PrintAndCheckBlock(R, P, "P'", w)
  1503.   PrintAndCheckBlock(T, RefT, "T'", w)
  1504.   # Verify
  1505.   AADStream.seek(0)
  1506.   CipherStream.seek(0)
  1507.   IsOK = Cipher.Verify(AADStream, CipherStream, RefT)
  1508.   print("Cipher.Verify() returned {}.".format(IsOK))
  1509.  
  1510.   print("\nAES-128 GMAC\n ")
  1511.   # Example from MACsec GCM-AES Test Vectors (April 11, 2011)
  1512.   # 2.1.1: 54-byte Packet Authentication Using GCM-AES-128
  1513.   K = XBytes("AD7A2BD03EAC835A6F620FDCB506B345")
  1514.   IV = XBytes("12153524C0895E81B2C28465")
  1515.   A = XBytes("D609B1F056637A0D46DF998D88E5222A"
  1516.              "B2C2846512153524C0895E8108000F10"
  1517.              "1112131415161718191A1B1C1D1E1F20"
  1518.              "2122232425262728292A2B2C2D2E2F30"
  1519.              "313233340001")
  1520.   RefG = XBytes("F09478A9B09007D06F46E9B6A1DA25DD")
  1521.   w = 8
  1522.   PrintBlock(K, "K", w)
  1523.   PrintBlock(IV, "IV", w)
  1524.   PrintBlock(A, "A", w)
  1525.   AADStream = io.BytesIO(A)
  1526.   Cipher = AESGCMCipher(K, IV)
  1527.   G = Cipher.GMAC(AADStream)
  1528.   PrintAndCheckBlock(G, RefG, "GMAC", w)
  1529.  
  1530.   print("\nSHA-256\n ")
  1531.   w = 8
  1532.   Examples = [
  1533.     ("0", XBytes(""),
  1534.         XBytes("e3b0c44298fc1c149afbf4c8996fb924"
  1535.                "27ae41e4649b934ca495991b7852b855")),
  1536.     ("abc", b"abc",
  1537.         XBytes("BA7816BF8F01CFEA414140DE5DAE2223"
  1538.                "B00361A396177A9CB410FF61F20015AD"))
  1539.   ]
  1540.   for StrName, M, RefH in Examples:
  1541.     PrintBlock(M, "M" + StrName, w)
  1542.     H = SHA_256(M)
  1543.     PrintAndCheckBlock(H, RefH, "H" + StrName, w)
  1544.  
  1545.   print("\nHMAC-SHA-256\n ")
  1546.   w = 8
  1547.   Examples = [
  1548.     ("0", b"", b"",
  1549.         XBytes("b613679a0814d9ec772f95d778c35fc5"
  1550.                "ff1697c493715653c6c712144292c5ad")),
  1551.     ("qbf", b"key", b"The quick brown fox jumps over the lazy dog",
  1552.         XBytes("f7bc83f430538424b13298e6aa6fb143"
  1553.                "ef4d59a14946175997479dbc2d1a3cd8"))
  1554.   ]
  1555.   for StrName, K, M, RefH in Examples:
  1556.     PrintBlock(K, "K" + StrName, w)
  1557.     PrintBlock(M, "M" + StrName, w)
  1558.     H = HMAC_SHA_256(K, M)
  1559.     PrintAndCheckBlock(H, RefH, "H" + StrName, w)
  1560.  
  1561.   print("PBKDF2")
  1562.   w = 10
  1563.  #PBKDF2(PRF, Password, Salt, Count, DerivedKeyLength)
  1564.   Examples = [
  1565.     ("1", b"password", b"salt", 1, 32,
  1566.         XBytes("120fb6cffcf8b32c43e7225256c4f837"
  1567.                "a86548c92ccc35480805987cb70be17b")),
  1568.     ("2", b"passwordPASSWORDpassword",
  1569.         b"saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 40,
  1570.         XBytes("348c89dbcbd32b2f32d814b8116e84cf"
  1571.                "2b17347ebc1800181c4e2a1fb8dd53e1"
  1572.                "c635518c7dac47e9"))
  1573.   ]
  1574.   for StrName, P, S, c, dkLen, RefDK in Examples:
  1575.     PrintBlock(P, "P" + StrName, w)
  1576.     PrintBlock(S, "S" + StrName, w)
  1577.     print("{:<{}}{}".format("c" + StrName + ":", w, c))
  1578.     print("{:<{}}{}".format("dkLen" + StrName + ":", w, dkLen))
  1579.     DK = PBKDF2(HMAC_SHA_256, P, S, c, dkLen)
  1580.     PrintAndCheckBlock(DK, RefDK, "DK" + StrName, w)
  1581.  
  1582.   # Encryption example
  1583.   #
  1584.   # Password = "boojum"
  1585.   # KDF = PBKDF2
  1586.   # PRF = HMAC-SHA-256
  1587.   # Iterations = 5000
  1588.   # Salt = 40c8298595ff6e6d876fae82f0a498b167194c89bad4695fb35428ccb6b8da9d
  1589.   #
  1590.   # Cipher = AES-128
  1591.   # Mode = GCM
  1592.   # IV = 8c3b8c4f4af83514139351ad
  1593.   #
  1594.   # AAD = (empty string)
  1595.   #
  1596.   # plain.txt:
  1597.   # 0000: 22 4a 75 73 74 20 74 68  65 20 70 6c 61 63 65 20  |"Just the place |
  1598.   # 0010: 66 6f 72 20 61 20 53 6e  61 72 6b 21 22 20 74 68  |for a Snark!" th|
  1599.   # 0020: 65 20 42 65 6c 6c 6d 61  6e 20 63 72 69 65 64 2c  |e Bellman cried,|
  1600.   # 0030: 0a 41 73 20 68 65 20 6c  61 6e 64 65 64 20 68 69  |.As he landed hi|
  1601.   # 0040: 73 20 63 72 65 77 20 77  69 74 68 20 63 61 72 65  |s crew with care|
  1602.   # 0050: 3b 0a 53 75 70 70 6f 72  74 69 6e 67 20 65 61 63  |;.Supporting eac|
  1603.   # 0060: 68 20 6d 61 6e 20 6f 6e  20 74 68 65 20 74 6f 70  |h man on the top|
  1604.   # 0070: 20 6f 66 20 74 68 65 20  74 69 64 65 0a 42 79 20  | of the tide.By |
  1605.   # 0080: 61 20 66 69 6e 67 65 72  20 65 6e 74 77 69 6e 65  |a finger entwine|
  1606.   # 0090: 64 20 69 6e 20 68 69 73  20 68 61 69 72 2e 0a     |d in his hair..|
  1607.   # 009f:
  1608.   #
  1609.   # encrypted.bin
  1610.   # 0000: 23 45 4e 43 52 59 50 54  45 44 23 0a 5b 46 69 6c  |#ENCRYPTED#.[Fil|
  1611.   # 0010: 65 5d 0a 48 44 52 53 49  5a 45 3d 32 36 34 0a 41  |e].HDRSIZE=264.A|
  1612.   # 0020: 41 44 53 49 5a 45 3d 30  0a 46 4f 52 4d 41 54 3d  |ADSIZE=0.FORMAT=|
  1613.   # 0030: 43 4f 4e 43 41 54 45 4e  41 54 45 44 20 41 43 54  |CONCATENATED ACT|
  1614.   # 0040: 0a 56 45 52 53 49 4f 4e  3d 31 2e 30 0a 5b 50 61  |.VERSION=1.0.[Pa|
  1615.   # 0050: 73 73 77 6f 72 64 5d 0a  4b 44 46 3d 50 42 4b 44  |ssword].KDF=PBKD|
  1616.   # 0060: 46 32 0a 50 52 46 3d 48  4d 41 43 2d 53 48 41 2d  |F2.PRF=HMAC-SHA-|
  1617.   # 0070: 32 35 36 0a 49 54 45 52  41 54 49 4f 4e 53 3d 35  |256.ITERATIONS=5|
  1618.   # 0080: 30 30 30 0a 53 41 4c 54  3d 34 30 63 38 32 39 38  |000.SALT=40c8298|
  1619.   # 0090: 35 39 35 66 66 36 65 36  64 38 37 36 66 61 65 38  |595ff6e6d876fae8|
  1620.   # 00a0: 32 66 30 61 34 39 38 62  31 36 37 31 39 34 63 38  |2f0a498b167194c8|
  1621.   # 00b0: 39 62 61 64 34 36 39 35  66 62 33 35 34 32 38 63  |9bad4695fb35428c|
  1622.   # 00c0: 63 62 36 62 38 64 61 39  64 0a 5b 43 69 70 68 65  |cb6b8da9d.[Ciphe|
  1623.   # 00d0: 72 5d 0a 43 49 50 48 45  52 3d 41 45 53 2d 31 32  |r].CIPHER=AES-12|
  1624.   # 00e0: 38 0a 4d 4f 44 45 3d 47  43 4d 0a 49 56 3d 38 63  |8.MODE=GCM.IV=8c|
  1625.   # 00f0: 33 62 38 63 34 66 34 61  66 38 33 35 31 34 31 33  |3b8c4f4af8351413|
  1626.   # 0100: 39 33 35 31 61 64 0a 00  3a 9f 9f e8 2c e3 53 81  |9351ad..:...,.S.|
  1627.   # 0110: 4f cf 2b 47 82 88 c3 4d  c3 1d 78 59 5b ab 36 83  |O.+G...M..xY[.6.|
  1628.   # 0120: 94 b3 74 5e bd 70 ea ee  ab 41 f1 fd e0 ce 93 36  |..t^.p...A.....6|
  1629.   # 0130: dd b0 b0 48 49 84 7b b4  bf 43 2c 23 34 35 48 aa  |...HI.{..C,#45H.|
  1630.   # 0140: 5d b3 54 5a d2 84 d0 8b  e2 d7 93 ae 18 0d ec 1d  |].TZ............|
  1631.   # 0150: ae 0a 12 05 6a 7c 3d 40  73 5a 9f 78 eb 52 db 04  |....j|=@sZ.x.R..|
  1632.   # 0160: 50 ec 7c b5 21 31 7f 03  73 8e 99 40 08 93 5e 14  |P.|.!1..s..@..^.|
  1633.   # 0170: 12 ef c2 72 f8 8a f3 54  3a e9 49 ce 27 e8 9c 52  |...r...T:.I.'..R|
  1634.   # 0180: d6 02 a4 45 77 ca d4 c5  fd 1c dc 00 c7 e1 47 b6  |...Ew.........G.|
  1635.   # 0190: 5c 20 bb 25 75 0b 61 7e  5e db 78 d0 0c f1 08 b1  |\ .%u.a~^.x.....|
  1636.   # 01a0: b3 5c 15 60 65 c5 1a 9a  8a 85 73 71 66 23 0f 54  |.\.`e.....sqf#.T|
  1637.   # 01b0: dd 5b 88 f5 50 57 db                              |.[..PW.|
  1638.   # 01b7:
  1639.   #
  1640.   # Tag = 9a8a85737166230f54dd5b88f55057db
  1641.  
  1642.   print("Done")
  1643.  
  1644.  
  1645. #-------------------------------------------------------------------------------
  1646. # Main
  1647. #-------------------------------------------------------------------------------
  1648.  
  1649.  
  1650. def main(Args):
  1651.  
  1652.   """
  1653.  Usage:
  1654.  
  1655.  pef encrypt {password} {plainfile} {outputfile}
  1656.  pef decrypt {password} {encryptedfile} {outputfile}
  1657.  pef verify {password} {file}
  1658.  
  1659.  If {password} is an empty string, the user will be prompted for a password.
  1660.  """
  1661.  
  1662.   Result = 0
  1663.   ErrMsg = ""
  1664.   InFile = None
  1665.   OutFile = None
  1666.  
  1667.   CmdName = os.path.basename(sys.argv[0])
  1668.  
  1669.   try:
  1670.  
  1671.     CmdArg = None if len(Args) < 2 else Args[1]
  1672.     KeyArg = None if len(Args) < 3 else Args[2]
  1673.     CmdArgLC = None if CmdArg is None else CmdArg.lower()
  1674.     Cmd = None
  1675.  
  1676.     if CmdArgLC in ("encrypt", "decrypt", "verify"):
  1677.       Cmd = CmdArgLC
  1678.     else:
  1679.       if CmdArg is None:
  1680.         raise ArgError('Command argument required: ' +
  1681.             '"encrypt", "decrypt" or "verify".')
  1682.       else:
  1683.         raise ArgError('Unknown command "' + CmdArg + '".')
  1684.  
  1685.     if Cmd == 'encrypt':
  1686.  
  1687.       if len(Args) != 5:
  1688.         raise ArgError(
  1689.             'Expected arguments: encrypt {password} ' +
  1690.             '{plainfile} {outputfile}')
  1691.  
  1692.       Password, InFileName, OutFileName = Args[2:]
  1693.       Password = Password or getpass.getpass()
  1694.  
  1695.       InFile = open(InFileName, "rb")
  1696.       OutFile = open(OutFileName, "wb")
  1697.  
  1698.       AADStr = ""
  1699.       AAD = (AADStr).encode("utf8")
  1700.  
  1701.       Encrypt(Password, AAD, InFile, OutFile)
  1702.  
  1703.     elif Cmd == 'decrypt':
  1704.  
  1705.       if len(Args) != 5:
  1706.         raise ArgError(
  1707.             'Expected arguments: decrypt {password} ' +
  1708.             '{encryptedfile} {outputfile}')
  1709.  
  1710.       Password, InFileName, OutFileName = Args[2:]
  1711.       Password = Password or getpass.getpass()
  1712.  
  1713.       OFExistedAlready = os.path.isfile(OutFileName)
  1714.       InFile = open(InFileName, "rb")
  1715.       OutFile = open(OutFileName, "wb")
  1716.       AAD = Decrypt(Password, InFile, OutFile)
  1717.       if AAD is None:
  1718.         if not OFExistedAlready:
  1719.           os.remove(OutFileName)
  1720.         raise FileError('Authenticity check failed.')
  1721.  
  1722.     elif Cmd == 'verify':
  1723.  
  1724.       Password, InFileName = Args[2:]
  1725.       Password = Password or getpass.getpass()
  1726.  
  1727.       InFile = open(InFileName, "rb")
  1728.       AAD = Decrypt(Password, InFile, None)
  1729.       if AAD is None:
  1730.         raise FileError('Authenticity check failed.')
  1731.       else:
  1732.         print("OK")
  1733.  
  1734.     else:
  1735.  
  1736.       raise ArgError('INTERNAL: Command."' + Cmd + '" not handled.')
  1737.  
  1738.   except (ArgError) as E:
  1739.  
  1740.     ErrMsg = "error: " + str(E)
  1741.     Result = 2
  1742.  
  1743.   except (FileError) as E:
  1744.  
  1745.     ErrMsg = str(E)
  1746.     Result = 3
  1747.  
  1748.   except (Exception) as E:
  1749.  
  1750.     exc_type, exc_value, exc_traceback = sys.exc_info()
  1751.     ErrLines = traceback.format_exc().splitlines()
  1752.     ErrMsg = "Unhandled exception:\n" + "\n".join(ErrLines)
  1753.     Result = 1
  1754.  
  1755.   finally:
  1756.  
  1757.     if InFile is not None:
  1758.       InFile.close()
  1759.  
  1760.     if OutFile is not None:
  1761.       OutFile.close()
  1762.  
  1763.   if ErrMsg != "":
  1764.     print(CmdName + ": " + ErrMsg, file=sys.stderr)
  1765.  
  1766.   return Result
  1767.  
  1768.  
  1769. #-------------------------------------------------------------------------------
  1770.  
  1771.  
  1772. if __name__ == '__main__':
  1773.   sys.exit(main(sys.argv))
  1774.  
  1775.  
  1776. #-------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement