"""
-
+from ctypes import c_int, c_void_p, c_char_p, c_int
from ctypescrypto.exception import LibCryptoError
+from ctypescrypto import libcrypto
from ctypescrypto.bio import Membio
from ctypescrypto.oid import Oid
return SignedData(ptr)
elif typeoid.shortname()=="pkcs7-envelopedData":
return EnvelopedData(ptr)
+ elif typeoid.shortname()=="pkcs7-encryptedData":
+ return EncryptedData(ptr)
else:
raise NotImplementedError("cannot handle "+typeoid.shortname())
+class CMSBase:
+ """
+ Common ancessor for all CMS types.
+ Implements serializatio/deserialization
+ """
+ def __init__(self,ptr=None):
+ self.ptr=ptr
+ def __str__(self):
+ """
+ Serialize in DER format
+ """
+ b=Membio()
+ if not libcrypto.i2d_CMS_bio(b.bio,self.ptr):
+ raise CMSError("writing CMS to PEM")
+ return str(b)
+ def pem(self):
+ """
+ Serialize in PEM format
+ """
+ b=Membio()
+ if not libcrypto.PEM_write_bio_CMS(b.bio,self.ptr):
+ raise CMSError("writing CMS to PEM")
+ return str(b)
+
-class SignedData:
- def __init__(self,ptr=None):
- self.ptr=ptr
+class SignedData(CMSBase):
@staticmethod
def create(data,cert,pkey,flags=Flags.BINARY):
"""
Adds another signer to already signed message
@param cert - signer's certificate
@param pkey - signer's private key
- @param data - data to sign (if detached)
- @param md - message digest to use as DigestType object (if None - default for key
- would be used)
- @param flags - flags
+ @param md - message digest to use as DigestType object
+ (if None - default for key would be used)
+ @param data - data to sign (if detached and
+ Flags.REUSE_DIGEST is not specified)
+ @param flags - ORed combination of Flags consants
"""
if not pkey.cansign:
raise ValueError("Specified keypair has no private part")
if res<=0:
raise CMSError
def verify(self,store,flags,data=None):
+ """
+ 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
+ @returns True if signature valid, False otherwise
+ """
bio=None
if data!=None:
b=Membio(data)
bio=b.bio
- res=libcrypto.CMS_verify(self.ptr,store.store,bio,None,flags)
+ res=libcrypto.CMS_verify(self.ptr,None,store.store,bio,None,flags)
return res>0
- def __str__(self):
- """
- Serialize in DER format
- """
- b=Membio()
- if not libcrypto.i2d_CMS_bio(b.bio,self.ptr):
- raise CMSError("writing CMS to PEM")
- return str(b)
-
- def pem(self):
- """
- Serialize in PEM format
- """
- b=Membio()
- if not libcrypto.PEM_write_bio_CMS(b.bio,self.ptr):
- raise CMSError("writing CMS to PEM")
- return str(b)
-
@property
def signers(self,store=None):
"""
@property
def data(self):
"""
- Returns signed data if present
+ Returns signed data if present in the message
"""
- raise NotImplementedError
+ b=Membio()
+ if not libcrypto.CMS_verify(self.ptr,None,None,None,b.bio,Flags.NO_VERIFY):
+ raise CMSError("extract data")
+ return str(b)
def addcert(self,cert):
"""
Adds a certificate (probably intermediate CA) to the SignedData
"""
raise NotImplementedError
-class EnvelopedData:
- def __init__(self,ptr):
- """
- Initializes an object. For internal use
- """
- self.ptr=ptr
- def __str__(self):
- """
- Serialize in DER format
- """
- b=Membio()
- if not libcrypto.i2d_CMS_bio(b.bio,self.ptr):
- raise CMSError("writing CMS to PEM")
- return str(b)
-
- def pem(self):
- """
- Serialize in PEM format
- """
- b=Membio()
- if not libcrypto.PEM_write_bio_CMS(b.bio,self.ptr):
- raise CMSError("writing CMS to PEM")
- return str(b)
+class EnvelopedData(CMSBase):
@staticmethod
def create(recipients,data,cipher,flags=0):
"""
if res<=0:
raise CMSError("decrypting CMS")
return str(b)
+
+class EncryptedData(CMSBase):
+ @staticmethod
+ def create(data,cipher,key,flags=0):
+ """
+ Creates an EncryptedData message.
+ @param data data to encrypt
+ @param cipher cipher.CipherType object represening required
+ cipher type
+ @param key - byte array used as simmetic key
+ @param flags - OR-ed combination of Flags constant
+ """
+ b=Membio(data)
+ ptr=libcrypto.CMS_EncryptedData_encrypt(b.bio,cipher.cipher_type,key,len(key),flags)
+ if ptr is None:
+ raise CMSError("encrypt data")
+ return EncryptedData(ptr)
+ def decrypt(self,key,flags=0):
+ """
+ Decrypts encrypted data message
+ @param key - symmetic key to decrypt
+ @param flags - OR-ed combination of Flags constant
+ """
+ b=Membio()
+ if libcrypto.CMS_EncryptedData_decrypt(self.ptr,key,len(key),None,
+ b.bio,flags)<=0:
+ raise CMSError("decrypt data")
+ return str(b)
+
+
+
+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)