text: # Copyright (c) 2002-2012 IronPort Systems and Cisco Systems
  #
  # Permission is hereby granted, free of charge, to any person obtaining a copy
  # of this software and associated documentation files (the "Software"), to deal
  # in the Software without restriction, including without limitation the rights
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  # copies of the Software, and to permit persons to whom the Software is
  # furnished to do so, subject to the following conditions:
  #
  # The above copyright notice and this permission notice shall be included in
  # all copies or substantial portions of the Software.
  #
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  # SOFTWARE.
  
  #
  # ssh.keys.dss
  #
  # Encapsulates the DSS key.
  
  import public_private_key
  import hashlib
  from coro.ssh.util import packet, random
  from Crypto.PublicKey import DSA
  from Crypto.Util import number
  
  class SSH_DSS(public_private_key.SSH_Public_Private_Key):
  
      # Features of this key type.
      supports_signature = 1
      supports_encryption = 0
      name = 'ssh-dss'
      # why not store these as attributes?
      # p, q, g, y
      private_key = (0L, 0L, 0L, 0L, 0L)
      # p, q, g, y, x
      public_key = (0L, 0L, 0L, 0L)
  
      def set_public_key(self, public_key):
          dss, p, q, g, y = packet.unpack_payload(DSS_PUBLIC_KEY_PAYLOAD, public_key)
          if dss != 'ssh-dss':
              raise ValueError(dss)
          self.public_key = (p, q, g, y)
  
      set_public_key.__doc__ = public_private_key.SSH_Public_Private_Key.set_public_key.__doc__
  
      def set_private_key(self, private_key):
          dss, p, q, g, y, x = packet.unpack_payload(DSS_PRIVATE_KEY_PAYLOAD, private_key)
          if dss != 'ssh-dss':
              raise ValueError(dss)
          self.private_key = (p, q, g, y, x)
  
      set_private_key.__doc__ = public_private_key.SSH_Public_Private_Key.set_private_key.__doc__
  
      def get_public_key_blob(self):
          if self.public_key != (0, 0, 0, 0):
              p, q, g, y = self.public_key
          else:
              p, q, g, y, x = self.private_key
          return packet.pack_payload(DSS_PUBLIC_KEY_PAYLOAD,
                                     ('ssh-dss',
                                      p, q, g, y))
  
      get_public_key_blob.__doc__ = public_private_key.SSH_Public_Private_Key.get_public_key_blob.__doc__
  
      def get_private_key_blob(self):
          p, q, g, y, x = self.private_key
          return packet.pack_payload(DSS_PRIVATE_KEY_PAYLOAD,
                                     ('ssh-dss',
                                      p, q, g, y, x))
  
      get_private_key_blob.__doc__ = public_private_key.SSH_Public_Private_Key.get_private_key_blob.__doc__
  
      def create (self, size=1024):
          key = DSA.generate (size)
          self.private_key = (key.p, key.q, key.g, key.y, key.x)
          self.public_key = (key.p, key.q, key.g, key.y)
  
      def sign(self, message):
          p, q, g, y, x = self.private_key
          dsa_obj = DSA.construct((y, g, p, q, x))
          message_hash = hashlib.sha1(message).digest()
          # Get a random number that is greater than 2 and less than q.
          random_number = random.get_random_number_from_range(2, q)
          random_data = number.long_to_bytes(random_number)
          r, s = dsa_obj.sign(message_hash, random_data)
          signature = number.long_to_bytes(r, 20) + number.long_to_bytes(s, 20)
          return packet.pack_payload(DSS_SIG_PAYLOAD,
                                     ('ssh-dss',
                                      signature))
  
      sign.__doc__ = public_private_key.SSH_Public_Private_Key.sign.__doc__
  
      def verify(self, message, signature):
          p, q, g, y = self.public_key
          dss, blob = packet.unpack_payload(DSS_SIG_PAYLOAD, signature)
          if dss != 'ssh-dss':
              raise ValueError(dss)
          # blob is the concatenation of r and s
          # r and s are 160-bit (20-byte) integers in network-byte-order
          assert(len(blob) == 40)
          r = number.bytes_to_long(blob[:20])
          s = number.bytes_to_long(blob[20:])
          dsa_obj = DSA.construct((y, g, p, q))
          hash_of_message = hashlib.sha1(message).digest()
          return dsa_obj.verify(hash_of_message, (r, s))
  
      verify.__doc__ = public_private_key.SSH_Public_Private_Key.verify.__doc__
  
  DSS_PUBLIC_KEY_PAYLOAD = (packet.STRING,  # "ssh-dss"
                            packet.MPINT,   # p
                            packet.MPINT,   # q
                            packet.MPINT,   # g
                            packet.MPINT    # y
                            )
  
  DSS_PRIVATE_KEY_PAYLOAD = (packet.STRING,  # "ssh-dss"
                             packet.MPINT,   # p
                             packet.MPINT,   # q
                             packet.MPINT,   # g
                             packet.MPINT,   # y
                             packet.MPINT,   # x
                             )
  
  
  DSS_SIG_PAYLOAD = (packet.STRING,  # "ssh-dss"
                     packet.STRING   # signature_key_blob
                     )
  