// arguments:
// 1. private key
// 2. public key
// 3. key item
// 4. password
//
// eg.: crypt-test keyset.p15 keyset.p15 "John Doe <john.doe@example.com>" "secretpassword"

#include <cryptlib.h>
#include <iostream>

int main(int argc, char* argv[]) {
    CRYPT_ENVELOPE cryptEnvelope;
    CRYPT_SESSION cryptSession;
    int bytesCopiedENCRYPT;
    int bytesCopiedDECRYPT;
    char* envelopedDataENCRYPT;
    char* envelopedDataDECRYPT;
    char plainbuf[] = "test text 1 12 123 1234 12345";
    int timestamp;
    int sigCheckStatus;
    CRYPT_CONTEXT sigKeyContext;
    CRYPT_KEYSET cryptKeyset;


    // initialize crypt
    cryptInit();


// **** encrypting ****
    // create envelope
    cryptCreateEnvelope( &cryptEnvelope, CRYPT_UNUSED, CRYPT_FORMAT_SMIME);

    // get the private key for signing
    cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, argv[1], CRYPT_KEYOPT_READONLY );
    cryptGetPrivateKey( cryptKeyset, &sigKeyContext, CRYPT_KEYID_NAME, argv[3], argv[4]);
    cryptKeysetClose( cryptKeyset );
    
    // sign
    cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE, sigKeyContext);
    cryptDestroyContext( sigKeyContext );

    // push plain data
    cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE, strlen(plainbuf) );
    cryptPushData( cryptEnvelope, &plainbuf, strlen(plainbuf), &bytesCopiedENCRYPT );

    // apply timestamp
    cryptCreateSession( &cryptSession, CRYPT_UNUSED, CRYPT_SESSION_TSP );
    cryptSetAttributeString( cryptSession, CRYPT_SESSINFO_SERVER_NAME, "http://timestamping.edelweb.fr/service/tsp", 42);
    cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_TIMESTAMP, cryptSession );
    cryptDestroySession( cryptSession );

    // flush data
    cryptFlushData( cryptEnvelope );
    
    // pop encrypted data
    envelopedDataENCRYPT = (char *)malloc(32768);
    cryptPopData( cryptEnvelope, envelopedDataENCRYPT, 32768 , &bytesCopiedENCRYPT );

    // destroy envelope
    cryptDestroyEnvelope( cryptEnvelope );
// **** end of encrypting ****


// **** decrypting ****
    // create envelope
    cryptCreateEnvelope( &cryptEnvelope, CRYPT_UNUSED, CRYPT_FORMAT_AUTO);

    // get the publick key for verification
    cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, argv[2], CRYPT_KEYOPT_READONLY );
    cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_KEYSET_SIGCHECK, cryptKeyset);
    cryptKeysetClose( cryptKeyset );

    // push encrypted data
    cryptPushData( cryptEnvelope, envelopedDataENCRYPT, bytesCopiedENCRYPT, &bytesCopiedDECRYPT );
    cryptFlushData( cryptEnvelope );

    // pop decrypted data
    envelopedDataDECRYPT = (char *)malloc(32768);
    cryptPopData( cryptEnvelope, envelopedDataDECRYPT, 32768, &bytesCopiedDECRYPT );
    
    // check signature
    int requiredAttribute;
    printf("getattribute... %i\n",cryptGetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_CURRENT, &requiredAttribute ));
    if( requiredAttribute == CRYPT_ENVINFO_SIGNATURE )
    {
        cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE_RESULT,&sigCheckStatus );
        printf("signature: %i\n",sigCheckStatus);
    }
    else {printf("signature missing: %i\n",requiredAttribute);}
    
    // check timestamp
    cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_TIMESTAMP, &timestamp );
    printf("timestamp: %i\n",timestamp);

    // destroy envelope
    cryptDestroyEnvelope( cryptEnvelope );
// **** end of decrypting ****

    // destroy crypt
    cryptEnd();
}
