157 lines
		
	
	
		
			No EOL
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			No EOL
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| '''
 | |
|     Onionr - P2P Anonymous Storage Network
 | |
| 
 | |
|     Contains abstractions for interacting with users of Onionr
 | |
| '''
 | |
| '''
 | |
|     This program is free software: you can redistribute it and/or modify
 | |
|     it under the terms of the GNU 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 <https://www.gnu.org/licenses/>.
 | |
| '''
 | |
| import onionrblockapi, logger, onionrexceptions, json, sqlite3
 | |
| class OnionrUser:
 | |
|     def __init__(self, coreInst, publicKey):
 | |
|         self.trust = 0
 | |
|         self._core = coreInst
 | |
|         self.publicKey = publicKey
 | |
| 
 | |
|         self.trust = self._core.getPeerInfo(self.publicKey, 'trust')
 | |
|         return
 | |
|     
 | |
|     def setTrust(self, newTrust):
 | |
|         '''Set the peers trust. 0 = not trusted, 1 = friend, 2 = ultimate'''
 | |
|         self._core.setPeerInfo(self.publicKey, 'trust', newTrust)
 | |
| 
 | |
|     def isFriend(self):
 | |
|         if self._core.getPeerInfo(self.publicKey, 'trust') == 1:
 | |
|             return True
 | |
|         return False
 | |
|     
 | |
|     def getName(self):
 | |
|         retData = 'anonymous'
 | |
|         name = self._core.getPeerInfo(self.publicKey, 'name')
 | |
|         try:
 | |
|             if len(name) > 0:
 | |
|                 retData = name
 | |
|         except ValueError:
 | |
|             pass
 | |
|         return retData
 | |
| 
 | |
|     def encrypt(self, data):
 | |
|         encrypted = coreInst._crypto.pubKeyEncrypt(data, self.publicKey, encodedData=True)
 | |
|         return encrypted
 | |
|     
 | |
|     def decrypt(self, data, anonymous=True):
 | |
|         decrypted = coreInst._crypto.pubKeyDecrypt(data, self.publicKey, encodedData=True)
 | |
|         return decrypted
 | |
|     
 | |
|     def forwardEncrypt(self, data):
 | |
|         self.generateForwardKey()
 | |
|         retData = ''
 | |
|         forwardKey = self._getLatestForwardKey()
 | |
|         if self._core._utils.validatePubKey(forwardKey):
 | |
|             encrypted = self._core._crypto.pubKeyEncrypt(data, forwardKey, encodedData=True)
 | |
|         else:
 | |
|             raise onionrexceptions.InvalidPubkey("No valid forward key available for this user")
 | |
|         return (data, forwardKey)
 | |
|     
 | |
|     def forwardDecrypt(self, encrypted):
 | |
|         retData = ''
 | |
|         for key in self
 | |
|         return
 | |
| 
 | |
|     def _getLatestForwardKey(self):
 | |
|         # Get the latest forward secrecy key for a peer
 | |
|         key = ""
 | |
|         conn = sqlite3.connect(self._core.peerDB, timeout=10)
 | |
|         c = conn.cursor()
 | |
| 
 | |
|         for row in c.execute("SELECT forwardKey FROM forwardKeys WHERE peerKey = ? AND date=(SELECT max(date) FROM forwardKeys)", (self.publicKey,)):
 | |
|             key = row[0]
 | |
|             break
 | |
| 
 | |
|         conn.commit()
 | |
|         conn.close()
 | |
|         return key
 | |
|     
 | |
|     def _getForwardKeys(self):
 | |
|         conn = sqlite3.connect(self._core.peerDB, timeout=10)
 | |
|         c = conn.cursor()
 | |
|         keyList = []
 | |
|         for row in c.execute("SELECT forwardKey FROM forwardKeys WHERE peerKey = ?", (self.publicKey,)):
 | |
|             key = row[0]
 | |
|             keyList.append(key)
 | |
| 
 | |
|         conn.commit()
 | |
|         conn.close()
 | |
| 
 | |
|         return list(keyList)
 | |
| 
 | |
|     def generateForwardKey(self, expire=432000):
 | |
| 
 | |
|         # Generate a forward secrecy key for the peer
 | |
|         conn = sqlite3.connect(self._core.forwardKeysFile, timeout=10)
 | |
|         c = conn.cursor()
 | |
|         # Prepare the insert
 | |
|         time = self._core._utils.getEpoch()
 | |
|         newKeys = self._core._crypto.generatePubKey()
 | |
|         newPub = newKeys[0]
 | |
|         newPriv = newKeys[1]
 | |
| 
 | |
|         time = self._core._utils.getEpoch()
 | |
|         command = (self.publicKey, newPub, newPriv, time, expire)
 | |
| 
 | |
|         c.execute("INSERT INTO myForwardKeys VALUES(?, ?, ?, ?);", command)
 | |
| 
 | |
|         conn.commit()
 | |
|         conn.close()
 | |
|         return newPub
 | |
| 
 | |
|     def getGeneratedForwardKeys(self, peer):
 | |
|         # Fetch the keys we generated for the peer, that are still around
 | |
|         conn = sqlite3.connect(self._core.peerDB, timeout=10)
 | |
|         c = conn.cursor()
 | |
|         command = (peer,)
 | |
|         keyList = [] # list of tuples containing pub, private for peer
 | |
|         for result in c.execute("SELECT * FROM myForwardKeys where peer=?", command):
 | |
|             keyList.append((result[1], result[2]))
 | |
|         return keyList
 | |
| 
 | |
|     def addForwardKey(self, newKey):
 | |
|         if not self._core._utils.validatePubKey(newKey):
 | |
|             raise onionrexceptions.InvalidPubkey
 | |
|         # Add a forward secrecy key for the peer
 | |
|         conn = sqlite3.connect(self._core.peerDB, timeout=10)
 | |
|         c = conn.cursor()
 | |
|         # Prepare the insert
 | |
|         time = self._core._utils.getEpoch()
 | |
|         command = (self.publicKey, newKey, time)
 | |
| 
 | |
|         c.execute("INSERT INTO forwardKeys VALUES(?, ?, ?);", command)
 | |
| 
 | |
|         conn.commit()
 | |
|         conn.close()
 | |
|         return
 | |
|     
 | |
|     def findAndSetID(self):
 | |
|         '''Find any info about the user from existing blocks and cache it to their DB entry'''
 | |
|         infoBlocks = []
 | |
|         for bHash in self._core.getBlocksByType('userInfo'):
 | |
|             block = onionrblockapi.Block(bHash, core=self._core)
 | |
|             if block.signer == self.publicKey:
 | |
|                 if block.verifySig():
 | |
|                     newName = block.getMetadata('name')
 | |
|                     if newName.isalnum():
 | |
|                         logger.info('%s is now using the name %s.' % (self.publicKey, self._core._utils.escapeAnsi(newName)))
 | |
|                         self._core.setPeerInfo(self.publicKey, 'name', newName)
 | |
|             else:
 | |
|                 raise onionrexceptions.InvalidPubkey |