blob: 15d8c4757d1c8eefe91eb5c26708f83c0a6f3f8d [file] [log] [blame]
# -*- 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()