4

I'm trying to store the private/public keys as UTF-8 strings in a database. The problem is that when I bring them back into code, they are not the correct type. As bytes they print the same, as per the following code:

import nacl.utils
from nacl.public import PrivateKey, SealedBox
from nacl.encoding import Base64Encoder
import base64


prvkbob = PrivateKey.generate()
pubkbob = prvkbob.public_key

prvk_db = prvkbob.encode(Base64Encoder).decode('utf8')
pubk_db = pubkbob.encode(Base64Encoder).decode('utf8')

prvk = base64.b64decode(prvk_db.encode('utf8'))
shdk = base64.b64decode(pubk_db.encode('utf8'))

print(prvkbob)
print(prvk)

print(pubkbob)
print(shdk)

# It works with the original key
sealed_box = SealedBox(prvkbob)

# Error on key returned from database
sealed_box = SealedBox(prvk)

How do I initialize them as PublicKey or PrivateKey objects?

zamarov
  • 165
  • 2
  • 16

2 Answers2

3

I might be a little late to the party, but I ran in to the similar problem where it says:

nacl.exceptions.TypeError: Box must be created from a PrivateKey and a PublicKey

This is easily fixed by instantiation a Public or private key instance using the following lines:

imported_private_key = nacl.public.PrivateKey(bytes_that_are_a_key)
imported_public_key = nacl.public.PublicKey(bytes_that_are_a_key)

I hope it might help you or anyone else with the same problem

2

Since you explicitly decoded keys in utf-8 (.decode('utf8')), you must first encode those in with the very same encoding (as you did). As @DisplayName said, you just then need to instantiate PrivateKey and PublicKey

Since you plan to store the Base64 representations of those keys, you could do the following. Here are keys generated the ways you wanted:

john_private = "OSEuOrw7BDANm2b0lwddBXUxN6OFGBLBDoFbqnkdMNU="
john_public  = "bQNbTjHETLTc/RNJYa1mTDg0fQF70GsuIZFsrb43DQc="

paul_private = "ry860ekZ8T1UDTzvoPSlAVMEOjcVz3ODLYbjXfySns0="
paul_public  = "G8608AL7TE2n3P10OLS8V/8wCaf/mzflCS/5qw/TzG4="

The two functions work with keys and messages stored in Base64

def base64_to_bytes(key:str) -> bytes: 
    return base64.b64decode(key.encode('utf-8'))

def encrypt_for_user(sender_private:str, receiver_public:str, message:str) -> str: 
    sender_private = PrivateKey(base64_to_bytes(sender_private))
    receiver_public = PublicKey(base64_to_bytes(receiver_public))
    sender_box = Box(sender_private, receiver_public)

    return base64.b64encode(sender_box.encrypt(bytes(message, "utf-8"))).decode('utf-8')

def decrypt_for_user(receiver_private:str, sender_public:str, message:str) -> str: 
    receiver_private = PrivateKey(base64_to_bytes(receiver_private))
    sender_public = PublicKey(base64_to_bytes(sender_public))
    receiver_box = Box(receiver_private, sender_public)

    return receiver_box.decrypt(base64.b64decode(message.encode('utf-8'))).decode('utf-8')

John sends a message to Paul:

message = encrypt_for_user(john_private,paul_public,"Hi Paul, 'up?")
print(message)
9BxTezSQVlxPU5evODskj4EIb5hXqIPnkQVuhpY2qoYvcnIaBgUVhkbN8baSytsmF4RSXdI=

Paul decrypts it:

decrypt_for_user(paul_private, john_public, message)
"Hi Paul, 'up?"
zar3bski
  • 2,773
  • 7
  • 25
  • 58