# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2014 Regents of the University of California.
# Author: Adeola Bannis <thecodemaiden@gmail.com>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# A copy of the GNU General Public License is in the file COPYING.
from pyndn.encoding import WireFormat
from pyndn.util import Blob
from pyndn.digest_sha256_signature import DigestSha256Signature
from pyndn import Data, KeyLocatorType, Interest, Name
from hashlib import sha256
from random import SystemRandom
from time import time as timestamp

import hmac

class HmacHelper(object):
    def __init__(self, raw_key, wireFormat=None):
        super(HmacHelper, self).__init__()
        self.key = sha256(raw_key).digest()
        self.random = SystemRandom()
        if wireFormat is None:
            self.wireFormat = WireFormat.getDefaultWireFormat()
        else:
            self.wireFormat = wireFormat

    @classmethod
    def generatePin(cls):
        """
        Generate a pin to be entered into another device.
        Restricting this to 8 bytes (16 hex chars) for now.
        """
        pin = bytearray(8)
        random = SystemRandom()
        for i in range(8):
            pin[i] = random.randint(0,0xff)
        return str(pin).encode('hex')
    
    @classmethod
    def extractInterestSignature(cls, interest, wireFormat=None):
        if wireFormat is None:
            wireFormat = WireFormat.getDefaultWireFormat()

        try:
            signature = wireFormat.decodeSignatureInfoAndValue(
                            interest.getName().get(-2).getValue().buf(),
                            interest.getName().get(-1).getValue().buf())
        except:
            signature = None

        return signature

    def signData(self, data, keyName=None, wireFormat=None):
        data.setSignature(DigestSha256Signature())
        s = data.getSignature()

        #s.getKeyLocator().setType(KeyLocatorType.KEYNAME)
        #s.getKeyLocator().setKeyName(keyName)

        if wireFormat is None:
            wireFormat = WireFormat.getDefaultWireFormat()
        encoded = data.wireEncode(wireFormat)
        signer = hmac.new(self.key, bytearray(encoded.toSignedBuffer()), sha256)
        s.setSignature(Blob(signer.digest()))
        data.wireEncode(wireFormat)
     
    def verifyData(self, data, wireFormat=None):
        # clear out old signature so encoding does not include it
        if wireFormat is None:
            wireFormat = WireFormat.getDefaultWireFormat()
        encoded = data.wireEncode(wireFormat)
        hasher = hmac.new(self.key, bytearray(encoded.toSignedBuffer()), sha256)
        sigBytes = data.getSignature().getSignature()
        return sigBytes.toRawStr() == hasher.digest()

    def signInterest(self, interest, keyName=None, wireFormat=None):
        # Adds the nonce and timestamp here, because there is no
        # 'makeCommandInterest' call for this yet
        nonceValue = bytearray(8)
        for i in range(8):
            nonceValue[i] = self.random.randint(0,0xff)
        timestampValue = bytearray(8)
        ts = int(timestamp()*1000)
        for i in range(8):
            byte = ts & 0xff
            timestampValue[-(i+1)] = byte
            ts = ts >> 8

        if wireFormat is None:
            wireFormat = WireFormat.getDefaultWireFormat()

        s = DigestSha256Signature()
        #s.getKeyLocator().setType(KeyLocatorType.KEYNAME)
        #s.getKeyLocator().setKeyName(keyName)

        interestName = interest.getName()
        interestName.append(nonceValue).append(timestampValue)
        interestName.append(wireFormat.encodeSignatureInfo(s))
        interestName.append(Name.Component())

        encoding = interest.wireEncode(wireFormat)
        signer = hmac.new(self.key, encoding.toSignedBuffer(), sha256)

        s.setSignature(Blob(signer.digest()))
        interest.setName(interestName.getPrefix(-1).append(
            wireFormat.encodeSignatureValue(s)))


    def verifyInterest(self, interest, wireFormat=None):
        if wireFormat is None:
            wireFormat = WireFormat.getDefaultWireFormat()

        signature = self.extractInterestSignature(interest, wireFormat)
        encoding = interest.wireEncode(wireFormat)
        hasher = hmac.new(self.key, encoding.toSignedBuffer(), sha256)
        return signature.getSignature().toRawStr() == hasher.digest()

