diff --git a/server.py b/server.py
index e2ed9250c4cc73dc5d0c09e9638ff0852420190e..75d176788ff89a68859e6859b69952b7e4bb0b03 100644
--- a/server.py
+++ b/server.py
@@ -56,6 +56,7 @@ MIX_REQ_AGE_MAX = 604800 # maximum mix request age before return to sender
 PEER_INFO_INTERVAL = 600 # interval for renewing my peer document
 PEER_SIG_AGE_MAX = 604800 # max age of a peer document signature
 PEER_DETECT_INTERVAL = 120 # interval for fetching peer list
+IDTY_SIG_AGE_MAX = 2592000 # max age of a idty document signature
 CURRENCY = "g1"
 
 def send_response(client, code, resp, dataformat="ubjson"):
@@ -190,6 +191,7 @@ def read_config(cdir, conf_overwrite={}):
 	conf["server"].setdefault("peer_info_interval", PEER_INFO_INTERVAL)
 	conf["server"].setdefault("peer_sig_age_max", PEER_SIG_AGE_MAX)
 	conf["server"].setdefault("peer_detect_interval", PEER_DETECT_INTERVAL)
+	conf["server"].setdefault("idty_sig_age_max", IDTY_SIG_AGE_MAX)
 	conf.setdefault("client", {})
 	conf["client"].setdefault("bma_hosts", BMA_HOSTS)
 	conf["client"].setdefault("proxy", None)
@@ -985,6 +987,8 @@ if __name__ == "__main__":
 		
 		# Generate peer info
 		local_peer = utils.Peer.generate(conf, keys)
+		if local_peer == None:
+			exit()
 		
 		peer_file = open(os.path.expanduser(utils.getargv("-e", "peer_info.ubjson")), "wb")
 		peer_file.write(ubjson.dumpb([local_peer.raw]))
diff --git a/utils.py b/utils.py
index de4e5db1c71834430fe44b3bbb3c5854fb41276c..28b7deb0e00601d66fc833fde016e337b89a51cf 100644
--- a/utils.py
+++ b/utils.py
@@ -132,29 +132,62 @@ def run_async(coro):
 
 #-------- ÄžMixer
 
+def verify_idty_sig(conf, raw, idty_pubkey, peer_pubkey):
+	try:
+		raw = libnacl.sign.Verifier(PublicKey(idty_pubkey).hex_pk()).verify(raw)
+		data = ubjson.loadb(raw)
+		assert data["doctype"] == "gmixer/idtysig" , "Bad doctype"
+		assert data["docver"] == "1" , "Bad docver"
+		assert data["pubkey"] == peer_pubkey , "Bad pubkey"
+		t = time.time()
+		assert data["sigtime"] < t and data["sigtime"] + conf["server"]["idty_sig_age_max"] > t , "Bad sigtime"
+	except (ValueError, IndexError, ubjson.decoder.DecoderException, AssertionError) as e:
+		logprint("Bad idty sig: "+str(e), LOG_TRACE)
+		return False
+	return True
+
 class Peer:
 	VERSION = "1"
 	def __init__(self, conf:dict, raw:bytes):
 		self.rectime = time.time()
 		self.raw = raw
-		data = ubjson.loadb(raw)
+		try:
+			data = ubjson.loadb(raw)
+		except ubjson.decoder.DecoderException:
+			raise AssertionError("Bad wrapper encoding")
+		
+		assert "pubkey" in data and "raw" in data , "Missing values in wrapper"
 		pubkey = data["pubkey"]
-		raw = libnacl.sign.Verifier(PublicKey(pubkey).hex_pk()).verify(data["raw"])
-		data = ubjson.loadb(raw)
-		# TODO try except
+		try:
+			raw = libnacl.sign.Verifier(PublicKey(pubkey).hex_pk()).verify(data["raw"])
+		except ValueError:
+			raise AssertionError("Bad signature")
+		try:
+			data = ubjson.loadb(raw)
+		except ubjson.decoder.DecoderException:
+			raise AssertionError("Bad data encoding")
+		
+		assert "doctype" in data and "docver" in data and "currency" in data and "pubkey" in data and "sigtime" in data and "host" in data and "idty" in data and "idtysig" in data ,\
+		       "Missing values in data"
+		
+		assert data["doctype"] == "gmixer/peer" , "Bad doctype"
+		assert data["docver"] == Peer.VERSION , "Bad docver"
+		assert data["currency"] == conf["currency"] , "Different currency"
+		assert data["pubkey"] == pubkey , "Different pubkey"
+		assert isinstance(data["sigtime"], (int, float)) , "Bad sigtime"
+		assert data["sigtime"] < self.rectime , "Futuristic sigtime"
 		
-		# TODO tests
-		assert data["currency"] == conf["currency"] , "Not the same currency"
 		if conf["idty"]["needed"]:
-			assert run_async(check_idty(conf["client"]["bma_hosts"], data["idty"]))
+			assert run_async(check_idty(conf["client"]["bma_hosts"], data["idty"])) , "Idty is not member"
+			assert verify_idty_sig(conf, data["idtysig"], data["idty"], pubkey) , "Bad idty sig"
 		
 		self.doctype = data["doctype"]
 		self.docver = data["docver"]
 		self.pubkey = data["pubkey"]
-		self.sigtime = data["sigtime"] 
+		self.sigtime = data["sigtime"]
 		self.host = tuple(data["host"]) # socket cannot manage lists
 		self.idty = data["idty"]
-		self.idtysig = data["idtysig"]
+		self.idtysig = data["idtysig"]# TODO check
 		
 		self.hash = hashlib.sha512((self.pubkey+"@"+self.host[0]+":"+str(self.host[1])).encode()).digest()
 		self.keys = PublicKey(self.pubkey)
@@ -165,7 +198,7 @@ class Peer:
 	
 	def generate(conf:dict, keys:SigningKey) -> bytes:
 		data = {
-			"doctype": "peer",
+			"doctype": "gmixer/peer",
 			"docver": Peer.VERSION,
 			"currency": conf["currency"],
 			"pubkey": keys.pubkey,
@@ -182,7 +215,8 @@ class Peer:
 		raw = ubjson.dumpb(data)
 		try:
 			return Peer(conf, raw)
-		except AssertionError:
+		except AssertionError as e:
+			logprint("Gen peer: "+str(e), LOG_ERROR)
 			return None
 
 def load_peers(conf:dict, db_peers:plyvel.DB, peers:dict):
@@ -207,9 +241,6 @@ async def bma_client(bma_endpoints:list):
 			client = None
 	return client
 
-#async def check_idty(client:Client, pubkey:str):
-#	print( await client(bma.wot.lookup, pubkey))
-
 async def check_idty(bma_endpoints:list, pubkey:str):
 	client = await bma_client(bma_endpoints)
 	try: