class TackBreakSig(TlsStructure): LENGTH = 128 def __init__(self, data=None): TlsStructure.__init__(self, data) if data is not None and len(data) != TackBreakSig.LENGTH: raise SyntaxError("Break signature is the wrong size. Is %s and should be %s." % (len(data), TackBreakSig.LENGTH)) if data is not None: self.public_key = ECPublicKey(self.getBytes(64)) self.signature = self.getBytes(64) if not self._verifySignature(): raise SyntaxError("Signature verification failure") if self.index != len(data): raise SyntaxError("Excess bytes in TACK_Break_Sig") @classmethod def createFromPem(cls, data): return cls(PEMDecoder(data).getDecoded("TACK BREAK SIG")) @classmethod def createFromPemList(cls, data): """Parse a string containing a sequence of PEM Break Sigs. Raise a SyntaxError if input is malformed. """ breakSigs = [] bList = PEMDecoder(data).getDecodedList("TACK BREAK SIG") for b in bList: breakSigs.append(TackBreakSig(b)) return breakSigs @classmethod def createFromParameters(cls, public_key, private_key): assert(len(public_key) == 64) tackBreakSig = cls() tackBreakSig.public_key = public_key tackBreakSig.signature = private_key.getSignature(bytearray("tack_break_sig", "ascii")) return tackBreakSig def serialize(self): """Return a bytearray containing the TACK_Break_Sig.""" w = TlsStructureWriter(TackBreakSig.LENGTH) w.add(self.public_key.getRawKey(), 64) w.add(self.signature, 64) assert(w.index == len(w.bytes)) return w.getBytes() def serializeAsPem(self): return PEMEncoder(self.serialize()).getEncoded("TACK BREAK SIG") def getTackId(self): return str(self.public_key) def _verifySignature(self): return self.public_key.verify(bytearray("tack_break_sig"), self.signature) def __str__(self): """Return a readable string describing this TACK_Break_Sig. Used by the "TACK view" command to display TACK objects.""" return "Breaks TACK ID = %s\n" % self.getTackId()
class TackBreakSig(TlsStructure): LENGTH = 128 def __init__(self, data=None): TlsStructure.__init__(self, data) if data is not None and len(data) != TackBreakSig.LENGTH: raise SyntaxError( "Break signature is the wrong size. Is %s and should be %s." % (len(data), TackBreakSig.LENGTH)) if data is not None: self.public_key = ECPublicKey(self.getBytes(64)) self.signature = self.getBytes(64) if not self._verifySignature(): raise SyntaxError("Signature verification failure") if self.index != len(data): raise SyntaxError("Excess bytes in TACK_Break_Sig") @classmethod def createFromPem(cls, data): return cls(PEMDecoder(data).getDecoded("TACK BREAK SIG")) @classmethod def createFromPemList(cls, data): """Parse a string containing a sequence of PEM Break Sigs. Raise a SyntaxError if input is malformed. """ breakSigs = [] bList = PEMDecoder(data).getDecodedList("TACK BREAK SIG") for b in bList: breakSigs.append(TackBreakSig(b)) return breakSigs @classmethod def createFromParameters(cls, public_key, private_key): assert (len(public_key) == 64) tackBreakSig = cls() tackBreakSig.public_key = public_key tackBreakSig.signature = private_key.getSignature( bytearray("tack_break_sig", "ascii")) return tackBreakSig def serialize(self): """Return a bytearray containing the TACK_Break_Sig.""" w = TlsStructureWriter(TackBreakSig.LENGTH) w.add(self.public_key.getRawKey(), 64) w.add(self.signature, 64) assert (w.index == len(w.bytes)) return w.getBytes() def serializeAsPem(self): return PEMEncoder(self.serialize()).getEncoded("TACK BREAK SIG") def getTackId(self): return str(self.public_key) def _verifySignature(self): return self.public_key.verify(bytearray("tack_break_sig"), self.signature) def __str__(self): """Return a readable string describing this TACK_Break_Sig. Used by the "TACK view" command to display TACK objects.""" return "Breaks TACK ID = %s\n" % self.getTackId()
class Tack(TlsStructure): LENGTH = 166 def __init__(self, data=None): TlsStructure.__init__(self, data) if data is not None: self.public_key = ECPublicKey(self.getBytes(64)) self.min_generation = self.getInt(1) self.generation = self.getInt(1) self.expiration = self.getInt(4) self.target_hash = self.getBytes(32) self.signature = self.getBytes(64) if not self._verifySignature(): raise SyntaxError("Signature verification failure") if self.index != len(data): raise SyntaxError("Excess bytes in TACK") @classmethod def createFromPem(cls, pem): data = PEMDecoder(pem).getDecoded("TACK") if len(data) != Tack.LENGTH: raise SyntaxError("TACK is the wrong size. %s, should be %s" % (len(data), Tack.LENGTH)) return cls(data) @classmethod def createFromParameters(cls, public_key, private_key, min_generation, generation, expiration, target_hash): assert(len(public_key.getRawKey()) == 64) assert(0 <= min_generation <= 255) assert(0 <= generation <= 255 and generation >= min_generation) assert(0 <= expiration <= 2**32-1) assert(len(target_hash) == 32) tack = cls() tack.public_key = public_key tack.min_generation = min_generation tack.generation = generation tack.expiration = expiration tack.target_hash = target_hash tack.signature = private_key.getSignature(tack._getDataToSign()) return tack def getTackId(self): return str(self.public_key) def serialize(self): writer = TlsStructureWriter(64) writer.add(self.signature, 64) return self._serializePrelude() + writer.getBytes() def serializeAsPem(self): return PEMEncoder(self.serialize()).getEncoded("TACK") def _serializePrelude(self): writer = TlsStructureWriter(Tack.LENGTH - 64) writer.add(self.public_key.getRawKey(), 64) writer.add(self.min_generation, 1) writer.add(self.generation, 1) writer.add(self.expiration, 4) writer.add(self.target_hash, 32) return writer.getBytes() def _getDataToSign(self): return bytearray("tack_sig", "ascii") + self._serializePrelude() def _verifySignature(self): bytesToVerify = self._getDataToSign() return self.public_key.verify(bytesToVerify, self.signature) def __str__(self): """Return a readable string describing this TACK. Used by the "TACK view" command to display TACK objects.""" s =\ """TACK ID = %s min_generation = %d generation = %d expiration = %s target_hash = %s\n""" %\ (self.getTackId(), self.min_generation, self.generation, Time.posixTimeToStr(self.expiration*60), Util.writeBytes(self.target_hash)) return s