[Cryptography-dev] Destroying keys and secrets?

John Pacific me at johnpacific.com
Thu Feb 22 16:54:07 EST 2018


Andrew,

If you notice the call to `BN_clear_free`, it zeros the memory of the key
once it gets garbage collected.

However, as several others have explained, this does not prevent the memory
getting stored on the disk in some manner.

-tux

On Feb 22, 2018 14:41, "Andrew W. Donoho" <andrew.donoho at gmail.com> wrote:

>
>
> > On Feb 20, 2018, at 11:00 , cryptography-dev-request at python.org wrote:
> >
> > ec.derive_private_key_from_bytes(secret_bytes, ec.SECP384R1(), backend)
> > could potentially be a way to do this specific operation while reducing
> the
> > number of copies (to zero in Python and 2-3 in OpenSSL, although the
> latter
> > are zeroed), but without tests that can detect non-required copies of
> > secret material it would be extremely hard to prevent regression in the
> > long term as the code is updated.
>
>
>
>
> Paul,
>
>
>
>         Based upon your hint above I just went in to the code and looked
> around. It looks like a straightforward extension. Note: I am not a library
> developer and, hence, have not developed all of the various skills to
> properly build pyca/cryptography. Nor am I particularly knowledgable about
> Python v2.7 & v3.6 interoperation issues, much less CPython, Cython and
> PyPy interoperation. The below code is a gedanken exploration to see how
> hard or involved it might actually be to extend pyca/cryptography.
>
>         TL;DR: It isn’t hard. I C&P three functions and then modded them.
> Gratz to the team on an excellent design.
>
>         It is clear that I could deploy my own copy of cryptography and
> call it a day. But I believe that key hygiene is an important social good.
> I am happy to help look at/write each routine that imports key material and
> propose versions that allow good key hygiene. As you note above, there is
> no solution for your regression testing issue except to discuss it in code
> commentary. Now to find a routine that can bang the contents of a bytes
> array to 0, 1 and then random.
>
>         Should I proceed to engage with your team or just continue on my
> merry way? I want to help but if it isn’t something the team prioritizes
> highly right now, I fully understand.
>
>
>
> Anon,
> Andrew
> ____________________________________
> Andrew W. Donoho
> Donoho Design Group, L.L.C.
> andrew.donoho at gmail.com, +1 (512) 666-7596, twitter.com/adonoho
>
> No risk, no art.
>         No art, no reward.
>                 -- Seth Godin
>
>
>
>
> ===== backend.py =====
>
> def _bytes_to_bn(self, num, bn=None):
>     # Was: def _int_to_bn(self, num, bn=None):
>     """
>     Converts a python bytes array to a BIGNUM. The returned BIGNUM will not
>     be garbage collected (to support adding them to structs that take
>     ownership of the object). Be sure to register it for GC if it will
>     be discarded after use.
>     """
>     assert bn is None or bn != self._ffi.NULL
>
>     if bn is None:
>         bn = self._ffi.NULL
>
>     bn_ptr = self._lib.BN_bin2bn(num, len(num), bn)
>     self.openssl_assert(bn_ptr != self._ffi.NULL)
>     return bn_ptr
>
>
> def derive_elliptic_curve_private_key_bytes(self, private_bytes, curve):
>     # Was: def derive_elliptic_curve_private_key(self, private_value,
> curve):
>     curve_nid = self._elliptic_curve_to_nid(curve)
>
>     ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid)
>     self.openssl_assert(ec_cdata != self._ffi.NULL)
>     ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
>
>     get_func, group = self._ec_key_determine_group_get_func(ec_cdata)
>
>     point = self._lib.EC_POINT_new(group)
>     self.openssl_assert(point != self._ffi.NULL)
>     point = self._ffi.gc(point, self._lib.EC_POINT_free)
>
>     value = self._bytes_to_bn(private_bytes)
>     value = self._ffi.gc(value, self._lib.BN_clear_free)
>
>     with self._tmp_bn_ctx() as bn_ctx:
>         res = self._lib.EC_POINT_mul(group, point, value, self._ffi.NULL,
>                                      self._ffi.NULL, bn_ctx)
>         self.openssl_assert(res == 1)
>
>         bn_x = self._lib.BN_CTX_get(bn_ctx)
>         bn_y = self._lib.BN_CTX_get(bn_ctx)
>
>         res = get_func(group, point, bn_x, bn_y, bn_ctx)
>         self.openssl_assert(res == 1)
>
>     res = self._lib.EC_KEY_set_public_key(ec_cdata, point)
>     self.openssl_assert(res == 1)
>     private = self._bytes_to_bn(private_bytes)
>     private = self._ffi.gc(private, self._lib.BN_clear_free)
>     res = self._lib.EC_KEY_set_private_key(ec_cdata, private)
>     self.openssl_assert(res == 1)
>
>     evp_pkey = self._ec_cdata_to_evp_pkey(ec_cdata)
>
>     return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey)
>
>
>
> ===== ec.py =====
>
> def derive_private_key_bytes(private_value, curve, backend):
>     # Was: def derive_private_key(private_value, curve, backend):
>    if not isinstance(curve, EllipticCurve):
>         raise TypeError("curve must provide the EllipticCurve interface.")
>
>     return backend.derive_elliptic_curve_private_key_bytes(private_value,
> curve)
>
>
>
>
> _______________________________________________
> Cryptography-dev mailing list
> Cryptography-dev at python.org
> https://mail.python.org/mailman/listinfo/cryptography-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cryptography-dev/attachments/20180222/b7e87baf/attachment.html>


More information about the Cryptography-dev mailing list