Как выбрать подкласс namedtuple с полем RSAPublicKey - PullRequest
1 голос
/ 25 марта 2019

Я пытаюсь сериализовать объекты, которые подклассируют namedtuple и содержат ссылки на RSAPublicKey объектов.

  • Я создаю подкласс именованного кортежа для создания экземпляров неизменяемого объекта.

  • В одном из полей моего класса содержится ссылка на объект типа RSAPublicKey .

  • Я определяю __setstate __ (self) для сериализации объекта RSAPublicKey для травления.

реализация класса

from collections import namedtuple

class MyClass(namedtuple('MyTuple', ['pub_key', 'foo'])):
    def __getstate__(self):
        return {
            'pub_key': serialize(self.pub_key),
            'foo': self.foo
        }

    def __repr__(self):
        return f'MyClass({serialize(self.pub_key)}, {self.foo})'

используется

import pickle

pr, pu = generate_keys()
my_obj = MyClass(pu, 4)

генерация ключей и сериализация

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

def generate_keys():
    priv = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    return priv, priv.public_key()

def serialize(key):
    return key.public_bytes(
        serialization.Encoding.PEM,
        serialization.PublicFormat.SubjectPublicKeyInfo
    )

Я получаю следующую ошибку.

TypeError                                 Traceback (most recent call last)
<ipython-input-14-cb7f2cfd2a4d> in <module>
      1 with open('save.dat', 'wb') as f:
----> 2     pickle.dump(my_obj, f)

TypeError: can't pickle CompiledFFI objects

Когда я изменяю свой класс на объект подкласса, сериализация работает правильно.

class MyClass():
    def __init__(self, pub_key, foo):
        self.pub_key = pub_key
        self.foo = foo

    def __getstate__(self):
        return {
            'pub_key': serialize(self.pub_key),
            'foo': self.foo
        }

    def __repr__(self):
        return f'MyClass({serialize(self.pub_key)}, {self.foo})'

1 Ответ

0 голосов
/ 25 марта 2019

это будет работать:

from collections import namedtuple

class MyClass(namedtuple('MyTuple', ['pub_key', 'foo'])):
    def __getstate__(self):
        return {
            'pub_key': serialize(self.pub_key),
            'foo': self.foo
        }

    def __repr__(self):
        return f'MyClass({serialize(self.pub_key)}, {self.foo})'




#key generation and serialization

from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

def generate_keys():
    priv = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend()
    )
    return priv, priv.public_key()

def serialize(key):
    return key.public_bytes(
        serialization.Encoding.PEM,
        serialization.PublicFormat.SubjectPublicKeyInfo
    )
import pickle
#dumping
pr, pu = generate_keys()
my_obj = MyClass(pu, 4)

with open('save.dat', 'wb') as f:
    #getting the data from the class
    pickle.dump(my_obj.__getstate__(), f)

это то же самое, но я использую getstate для получения данных, а не весь класс

...