【问题标题】:How to pickle namedtuple subclass with RSAPublicKey field如何使用 RSAPublicKey 字段腌制 namedtuple 子类
【发布时间】:2019-08-15 14:28:28
【问题描述】:

我正在尝试序列化子类 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})'

【问题讨论】:

  • 加载也不是微不足道的,因为类的不可变特性。我最终创建了 save_to_file 和 load_from_file 方法,它们完成了所有需要的步骤:序列化密钥、酸洗、使用 pickle 从文件加载、加载密钥对象、创建容器类的新不可变实例。

标签: python python-3.x pickle namedtuple python-cryptography


【解决方案1】:

这将起作用:

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 来获取数据而不是整个班级

【讨论】:

  • 它有效。这是预期的行为吗?我以为pickle只是调用_getsatate_函数并使用返回的对象。
猜你喜欢
  • 2014-01-16
  • 1970-01-01
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-14
相关资源
最近更新 更多