else:
raise NotImplementedError("cannot handle "+typeoid.shortname())
-class CMSBase:
+class CMSBase(object):
"""
Common ancessor for all CMS types.
Implements serializatio/deserialization
class SignedData(CMSBase):
@staticmethod
- def create(data,cert,pkey,flags=Flags.BINARY):
+ def create(data,cert,pkey,flags=Flags.BINARY,certs=[]):
"""
Creates SignedData message by signing data with pkey and
certificate.
@param data - data to sign
@param pkey - pkey object with private key to sign
+ @param flags - OReed combination of Flags constants
+ @param certs - list of X509 objects to include into CMS
"""
if not pkey.cansign:
raise ValueError("Specified keypair has no private part")
if cert.pubkey!=pkey:
raise ValueError("Certificate doesn't match public key")
b=Membio(data)
- ptr=libcrypto.CMS_sign(cert.cert,pkey.ptr,None,b.bio,flags)
+ if certs is not None and len(certs)>0:
+ certstack=StackOfX509(certs)
+ else:
+ certstack=None
+ ptr=libcrypto.CMS_sign(cert.cert,pkey.ptr,certstack,b.bio,flags)
if ptr is None:
raise CMSError("signing message")
return SignedData(ptr)
res= libcrypto.CMS_final(self.ptr,biodata,None,flags)
if res<=0:
raise CMSError
- def verify(self,store,flags,data=None):
+ def verify(self,store,flags,data=None,certs=[]):
"""
Verifies signature under CMS message using trusted cert store
@param store - X509Store object with trusted certs
@param flags - OR-ed combination of flag consants
@param data - message data, if messge has detached signature
+ param certs - list of certificates to use during verification
+ If Flags.NOINTERN is specified, these are only
+ sertificates to search for signing certificates
@returns True if signature valid, False otherwise
"""
bio=None
if data!=None:
b=Membio(data)
bio=b.bio
- res=libcrypto.CMS_verify(self.ptr,None,store.store,bio,None,flags)
+ if certs is not None and len(certs)>0:
+ certstack=StackOfX509(certs)
+ else:
+ certstack=None
+ res=libcrypto.CMS_verify(self.ptr,certstack,store.store,bio,None,flags)
return res>0
@property
- def signers(self,store=None):
+ def signers(self):
"""
Return list of signer's certificates
"""
- raise NotImplementedError
+ p=libcrypto.CMS_get0_signers(self.ptr)
+ if p is None:
+ raise CMSError
+ return StackOfX509(ptr=p,disposable=False)
@property
def data(self):
"""
Adds a certificate (probably intermediate CA) to the SignedData
structure
"""
- raise NotImplementedError
+ if libcrypto.CMS_add1_cert(self.ptr,cert.cert)<=0:
+ raise CMSError("adding cert")
def addcrl(self,crl):
"""
Adds a CRL to the signed data structure
"""
List of the certificates contained in the structure
"""
- raise NotImplementedError
+ p=CMS_get1_certs(self.ptr)
+ if p is None:
+ raise CMSError("getting certs")
+ return StackOfX509(ptr=p,disposable=True)
@property
def crls(self):
"""
@param cipher - CipherType object
@param flags - flag
"""
- # Need to be able to handle OPENSSL stacks
- raise NotImplementedError
+ recp=StackOfX509(recipients)
+ b=Membio(data)
+ p=libcrypto.CMS_encrypt(recp.ptr,b.bio,cipher.cipher_type,flags)
+ if p is None:
+ raise CMSError("encrypt EnvelopedData")
+ return EnvelopedData(p)
def decrypt(self,pkey,cert,flags=0):
"""
Decrypts message
raise CMSError("decrypt data")
return str(b)
-
+__all__=['CMS','CMSError','Flags','SignedData','EnvelopedData','EncryptedData']
libcrypto.CMS_verify.restype=c_int
libcrypto.CMS_verify.argtypes=(c_void_p,c_void_p,c_void_p,c_void_p,c_void_p,c_int)