2 Implements operations with CMS EnvelopedData and SignedData messages
4 Contains function CMS() which parses CMS message and creates either
5 EnvelopedData or SignedData objects (EncryptedData and CompressedData
6 can be easily added, because OpenSSL contain nessesary function)
8 Each of these objects contains create() static method which is used to
9 create it from raw data and neccessary certificates.
14 from ctypescrypto.exception import LibCryptoError
15 from ctypescrypto.bio import Membio
16 from ctypescrypto.oid import Oid
18 class CMSError(LibCryptoError):
20 Exception which is raised when error occurs
26 Constants for flags passed to the CMS methods.
33 NO_SIGS=NO_CONTENT_VERIFY|NO_ATTR_VERIFY
35 NO_SIGNER_CERT_VERIFY=0x20
50 def CMS(data,format="PEM"):
52 Parses CMS data and returns either SignedData or EnvelopedData
57 ptr=libcrypto.PEM_read_bio_CMS(b.bio,None,None,None)
59 ptr=libcrypto.d2i_CMS_bio(b.bio,None)
60 typeoid = Oid(libcrypto.OBJ_obj2nid(libcrypto.CMS_get0_type(ptr)))
61 if typeoid.shortname()=="pkcs7-signedData":
62 return SignedData(ptr)
63 elif typeoid.shortname()=="pkcs7-envelopedData":
64 return EnvelopedData(ptr)
66 raise NotImplementedError("cannot handle "+typeoid.shortname())
72 def __init__(self,ptr=None):
75 def create(data,cert,pkey,flags=Flags.BINARY):
77 Creates SignedData message by signing data with pkey and
80 @param data - data to sign
81 @param pkey - pkey object with private key to sign
84 raise ValueError("Specified keypair has no private part")
86 raise ValueError("Certificate doesn't match public key")
88 ptr=libcrypto.CMS_sign(cert.cert,pkey.ptr,None,b.bio,flags)
90 raise CMSError("signing message")
91 return SignedData(ptr)
92 def sign(self,cert,pkey,md=None,data=None,flags=Flags.BINARY):
94 Adds another signer to already signed message
95 @param cert - signer's certificate
96 @param pkey - signer's private key
97 @param data - data to sign (if detached)
98 @param md - message digest to use as DigestType object (if None - default for key
103 raise ValueError("Specified keypair has no private part")
104 if cert.pubkey!=pkey:
105 raise ValueError("Certificate doesn't match public key")
106 p1=libcrypto.CMS_sign_add1_Signer(self.ptr,cert.cert,pkey.ptr,
109 raise CMSError("adding signer")
110 if flags & Flags.REUSE_DIGEST==0:
116 res= libcrypto.CMS_final(self.ptr,biodata,None,flags)
119 def verify(self,store,flags,data=None):
124 res=libcrypto.CMS_verify(self.ptr,store.store,bio,None,flags)
128 Serialize in DER format
131 if not libcrypto.i2d_CMS_bio(b.bio,self.ptr):
132 raise CMSError("writing CMS to PEM")
137 Serialize in PEM format
140 if not libcrypto.PEM_write_bio_CMS(b.bio,self.ptr):
141 raise CMSError("writing CMS to PEM")
145 def signers(self,store=None):
147 Return list of signer's certificates
149 raise NotImplementedError
153 Returns signed data if present
155 raise NotImplementedError
156 def addcert(self,cert):
158 Adds a certificate (probably intermediate CA) to the SignedData
161 raise NotImplementedError
162 def addcrl(self,crl):
164 Adds a CRL to the signed data structure
166 raise NotImplementedError
170 List of the certificates contained in the structure
172 raise NotImplementedError
176 List of the CRLs contained in the structure
178 raise NotImplementedError
181 def __init__(self,ptr):
183 Initializes an object. For internal use
188 Serialize in DER format
191 if not libcrypto.i2d_CMS_bio(b.bio,self.ptr):
192 raise CMSError("writing CMS to PEM")
197 Serialize in PEM format
200 if not libcrypto.PEM_write_bio_CMS(b.bio,self.ptr):
201 raise CMSError("writing CMS to PEM")
204 def create(recipients,data,cipher,flags=0):
206 Creates and encrypts message
207 @param recipients - list of X509 objects
208 @param data - contents of the message
209 @param cipher - CipherType object
212 # Need to be able to handle OPENSSL stacks
213 raise NotImplementedError
214 def decrypt(self,pkey,cert,flags=0):
217 @param pkey - private key to decrypt
218 @param cert - certificate of this private key (to find
219 neccessary RecipientInfo
221 @returns - decrypted data
224 raise ValueError("Specified keypair has no private part")
225 if pkey != cert.pubkey:
226 raise ValueError("Certificate doesn't match private key")
228 res=libcrypto.CMS_decrypt(self.ptr,pkey.ptr,cert.ccert,None,b.bio,flags)
230 raise CMSError("decrypting CMS")