]> wagner.pp.ru Git - oss/ctypescrypto.git/commitdiff
CMS verification implemented
authorVictor Wagner <wagner@atlas-card.ru>
Mon, 27 Oct 2014 10:04:21 +0000 (13:04 +0300)
committerVictor Wagner <wagner@atlas-card.ru>
Mon, 27 Oct 2014 10:04:21 +0000 (13:04 +0300)
ctypescrypto/cms.py

index 9defb1d5b5c1403b1b6c16e6f4b9d8ebc76f71b4..f1a4dbbefa26bc1787fca3af1ae0763ebbd675d4 100644 (file)
@@ -10,8 +10,9 @@ create it from raw data and neccessary certificates.
 
 
 """
-
+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
 
@@ -62,15 +63,39 @@ def CMS(data,format="PEM"):
                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):
                """
@@ -94,10 +119,11 @@ class SignedData:
                        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")
@@ -117,30 +143,20 @@ class SignedData:
                        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):
                """
@@ -150,9 +166,12 @@ class SignedData:
        @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
@@ -177,29 +196,7 @@ class 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):
                """
@@ -229,3 +226,36 @@ class EnvelopedData:
                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)