Make private keys readable only by the owner

This commit is contained in:
Fred Miller 2018-10-21 00:05:24 +08:00
parent e8d76d050d
commit f16621a38b
No known key found for this signature in database
GPG Key ID: CE1E1CA0EEB080EB
2 changed files with 25 additions and 2 deletions

View File

@ -5,6 +5,7 @@ import datetime
import ipaddress
import sys
import typing
import contextlib
from pyasn1.type import univ, constraint, char, namedtype, tag
from pyasn1.codec.der.decoder import decode
@ -195,6 +196,21 @@ class CertStore:
dh = cls.load_dhparam(dh_path)
return cls(key, ca, ca_path, dh)
@staticmethod
@contextlib.contextmanager
def umask_secret():
"""
Context to temporarily set umask to its original value bitor 0o77.
Useful when writing private keys to disk so that only the owner
will be able to read them.
"""
original_umask = os.umask(0)
os.umask(original_umask | 0o77)
try:
yield
finally:
os.umask(original_umask)
@staticmethod
def create_store(path, basename, o=None, cn=None, expiry=DEFAULT_EXP):
if not os.path.exists(path):
@ -205,7 +221,7 @@ class CertStore:
key, ca = create_ca(o=o, cn=cn, exp=expiry)
# Dump the CA plus private key
with open(os.path.join(path, basename + "-ca.pem"), "wb") as f:
with CertStore.umask_secret(), open(os.path.join(path, basename + "-ca.pem"), "wb") as f:
f.write(
OpenSSL.crypto.dump_privatekey(
OpenSSL.crypto.FILETYPE_PEM,
@ -236,7 +252,7 @@ class CertStore:
f.write(p12.export())
# Dump the certificate and key in a PKCS12 format for Windows devices
with open(os.path.join(path, basename + "-ca.p12"), "wb") as f:
with CertStore.umask_secret(), open(os.path.join(path, basename + "-ca.p12"), "wb") as f:
p12 = OpenSSL.crypto.PKCS12()
p12.set_certificate(ca)
p12.set_privatekey(key)

View File

@ -111,6 +111,13 @@ class TestCertStore:
certs.CertStore.load_dhparam(filename)
assert os.path.exists(filename)
def test_umask_secret(self, tmpdir):
filename = str(tmpdir.join("secret"))
with certs.CertStore.umask_secret(), open(filename, "wb"):
pass
# TODO: How do we actually attempt to read that file as another user?
assert os.stat(filename).st_mode & 0o77 == 0
class TestDummyCert: