1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# $Id$
"""CMS routines.
For the moment these just call the OpenSSL CLI tool, which is slow,
requires disk I/O, and likes PEM format. Fix this later.
"""
import os, rpki.x509
# openssl smime -sign -nodetach -outform DER -signer biz-certs/Alice-EE.cer -certfile biz-certs/Alice-CA.cer -inkey biz-certs/Alice-EE.key -in PLAN -out PLAN.der
def encode(xml, key, cert_files):
"""Encode a chunk of XML as CMS signed with a specified key and bag of certificates.
We have to sort the certificates into the correct order before the
OpenSSL CLI tool will accept them. rpki.x509 handles that for us.
"""
certs = rpki.x509.X509_chain()
certs.load_from_PEM(cert_files)
certs.chainsort()
signer_filename = "cms.tmp.signer.pem"
certfile_filename = "cms.tmp.certfile.pem"
f = open(signer_filename, "w")
f.write(certs[0].get_PEM())
f.close()
f = open(certfile_filename, "w")
for cert in certs[1:]:
f.write(cert.get_PEM())
f.close()
i,o = os.popen2(["openssl", "smime", "-sign", "-nodetach", "-outform", "DER", "-signer", signer_filename, "-certfile", certfile_filename, "-inkey", key])
i.write(xml)
i.close()
cms = o.read()
o.close()
os.unlink(signer_filename)
os.unlink(certfile_filename)
return cms
# openssl smime -verify -inform DER -in PLAN.der -CAfile biz-certs/Alice-Root.cer
def decode(cms, ta):
"""Decode and check the signature of a chunk of CMS.
Returns the signed text (XML, until proven otherwise) on success.
if OpenSSL CLI tool reports anything other than successful
verification, we raise an exception.
"""
i,o,e = os.popen3(["openssl", "smime", "-verify", "-inform", "DER", "-CAfile", ta])
i.write(cms)
i.close()
xml = o.read()
o.close()
status = e.read()
e.close()
if status == "Verification successful\n":
return xml
else:
raise RuntimeError, "CMS verification failed: %s" % status
|