class OrderManager: def __init__(self): self.user_manager = UserManager() def get_all_orders_for_collector(self, collector_id=None): if not collector_id: return None collector = self.user_manager.get_user_by_id(user_id=collector_id) if collector: orders_pickups = OrderPickup.objects.filter(collector=collector) return orders_pickups else: return None def get_order_by_id(self, order_id=None): if not order_id: return None if Order.objects.filter(id=order_id).exists(): return Order.objects.get(id=order_id) else: return None def get_payable_by_order(self, order=None): if not order: return None transactions = Transaction.objects.filter(order=order) payable = order.total if transactions: payable = order.total - sum([txn.amt for txn in transactions]) return payable
class EncryptionManager: def __init__(self): self.public_exponent = 65537 self.key_size = 512 self.user_manager = UserManager() self.otp_length = 4 def generate_key_pair_for_user(self, user_id): private_key = rsa.generate_private_key( public_exponent=self.public_exponent, key_size=self.key_size, backend=default_backend()) public_key = private_key.public_key() user = self.user_manager.get_user_by_id(user_id=user_id) print(type(user)) if user: user.privkey = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption()).decode() user.pubkey = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo).decode( ) user.save() def get_private_key_by_user_id(self, user_id): # user = self.user_manager.get_user_by_id(user_id=user_id) # if not user.privkey: # self.generate_key_pair_for_user(user_id=user.id) # user = self.user_manager.get_user_by_id(user_id=user_id) with open(settings.PRIVKEY, "rb") as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=None, backend=default_backend()) return private_key def get_public_key_by_user_id(self, user_id): private_key = self.get_private_key_by_user_id(user_id) return private_key.public_key() def get_encrypted_cipher(self, user_id, data): public_key = self.get_public_key_by_user_id(user_id) ciphertext = public_key.encrypt( data.encode(), padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None)) return ciphertext def get_decrypt_cipher(self, user_id, ciphertext): private_key = self.get_private_key_by_user_id(user_id) plaintext = private_key.decrypt( ciphertext, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None)) return plaintext def get_otp_string(self): otp = "" for _ in range(self.otp_length): otp += str(random.randint(1, 9)) return otp def get_signature(self, data, user_id): private_key = self.get_private_key_by_user_id(user_id) signature = private_key.sign( data.encode(), padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA1()) return signature def get_encoded_signature(self, signature): return b64encode(signature) def get_decoded_signature(self, signature): return b64decode(signature) def is_data_verified(self, data, signature, user_id): public_key = self.get_public_key_by_user_id(user_id) print(type(signature)) try: public_key.verify( signature, data.encode(), padding.PSS(mgf=padding.MGF1(hashes.SHA1()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA1()) return True except Exception as e: print(e) return False
class OrdersView(View): def __init__(self): super().__init__() self.order_manager = OrderManager() self.encryption_manager = EncryptionManager() self.otp_manager = OTPManager() self.user_manager = UserManager() def get(self, request, order_id=None): login_id = request.session.get('login_id', None) if not login_id: redirect(reverse('home')) if not order_id: pickups = self.order_manager.get_all_orders_for_collector(login_id) context = {"pickups": pickups if pickups else []} return render(request, "orders.html", context) if order_id: order = self.order_manager.get_order_by_id(order_id=order_id) if order: payable = self.order_manager.get_payable_by_order(order) context = {"order": order, "payable": payable} return render(request, "order.html", context) else: return redirect(reverse('orders')) def post(self, request, order_id=None): login_id = request.session.get('login_id', None) if not login_id: redirect(reverse('home')) if order_id: if request.POST.get('action') == 'start_transaction': payable = request.POST.get('payable') if not payable: return redirect(reverse('orders')) context = { "payable": int(payable), "order_id": order_id, "user_id": login_id } return render(request, "transact.html", context) if request.POST.get('action') == 'start_verification': order_id = request.POST.get('order_id') payable = request.POST.get('payable') user_id = request.POST.get('user_id') if order_id and payable and user_id: data = f"{order_id}.{payable}.{user_id}" print(data) ciphertext = self.encryption_manager.get_encrypted_cipher( user_id=int(user_id), data=data) plaintext = self.encryption_manager.get_decrypt_cipher( user_id=user_id, ciphertext=ciphertext) otp = self.encryption_manager.get_otp_string() data = f"{plaintext.decode()}.{otp}" signature = self.encryption_manager.get_signature( data=data, user_id=user_id) print(f'generated: {signature}') otp_message = f"Your OTP is - {otp}. Payable amount is Rs.{payable}" self.otp_manager.send_otp( data=otp_message, to=[self.user_manager.get_user_by_id(user_id).phone]) print(f'otp_message: {otp_message}') context = { "order_id": order_id, "payable": payable, "user_id": user_id, "cipher": b64encode(ciphertext).decode(), "signature": b64encode(signature).decode() } return render(request, "verify.html", context) else: return redirect(reverse('orders')) if request.POST.get('action') == 'start_otp_validation': otp = request.POST.get('otp') order_id = request.POST.get('order_id') payable = request.POST.get('payable') user_id = request.POST.get('user_id') signature = request.POST.get('signature') print(f'Received: {b64decode(signature)}') data = f"{order_id}.{payable}.{user_id}.{otp}" is_verified = self.encryption_manager.is_data_verified( data=data, signature=b64decode(signature), user_id=user_id) if is_verified: return render(request, "success.html") else: return redirect(reverse('orders'))