2013-10-16 23 views
8

PDF'ler için imza doğrulamayı uygulamaya çalışıyorum. Bu büyük bir konudur, bu yüzden bir seferde bir adım atarım, önce kendimi imzaladığım bir PDF söz konusu olduğunda, aslında geçerli bir Acrobat ile tüm varsayılan değerleri kullanarak pozitif bir sonuç vermeye çalışıyorum - SHA256 olmalı Sindirmek için ve PKCS7 ayrılmış imzası. Yani, openssl çatlamak ve PDF'de verilen bayt aralığı okuyarak ve SHA256_* fonksiyonları arayarak karşılaştırmak için bir hash var. Bu yüzden şimdi sertifika verilerini vb. Okumak ve PKCS7_* işlevlerini kullanmam gerekiyor. found in the documentation olarakPKCS # 7 İmza Doğrulama

int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags); 

: Bu seferki istediğim biri olarak görünüyor. Bu belgenin haricinde, bunlardan herhangi birinin nasıl inşa edileceğini söylemiyor. Tamam, bu yüzden BIO *indata, here'daki bazı işlevlerle ve these (kesin ayrıntıları çalışmadığı halde) kullanan bir dizi diziyle yapılabilir, ancak PKCS7 *p7 veya STACK_OF(x) için çağrılır. Bu yapıları başlatmanın belgelenmiş bir yolunu bulamıyorum. pkcs7.h başlığında bazı pkcs7_ctrl fonksiyonları vardır: -.

long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); 

int PKCS7_set_type(PKCS7 *p7, int type); 
int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other); 
int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); 
int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst); 
int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si); 
int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); 
int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); 
int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); 
int PKCS7_content_new(PKCS7 *p7, int nid); 
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, 
    BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); 
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509); 

BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); 
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); 
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); 

ama bu bir orman gibi görünmüyor bazı kurallar olmadan çevresinde alay körlemesine başlamak etkili olacağını

ben belirgin bir şey kaçırdım mı

? Bu işlevi PDF'den ayrıştırdığım veri değerleriyle çağırmaya nasıl giderim?

cevap

7

Tamam, tüm bunları (çok) zor yoldan buldum. Bunu böyle yaparsın, böylece diğerleri daha kolay öğrenebilir.

biz uzunluğu int sig_length imzasını char* sig kullandığınızı varsayalım ve doğrulama verileri char* data, int data_length. (Orada bazı incelikleri PDF imzalar için burada ama bunlar iyi PDF spec olarak belgelenmiştir.)

OpenSSL_add_all_algorithms(); 
OpenSSL_add_all_digests(); 
EVP_add_digest(EVP_md5()); 
EVP_add_digest(EVP_sha1()); 
EVP_add_digest(EVP_sha256()); 

BIO* sig_BIO = BIO_new_mem_buf(sig, sig_length) 
PKCS7* sig_pkcs7 = d2i_PKCS7_bio(sig_BIO, NULL); 

BIO* data_BIO = BIO_new_mem_buf(data, data_length) 
BIO* data_pkcs7_BIO = PKCS7_dataInit(sig_pkcs7, data_BIO); 

// Goto this place in the BIO. Why? No idea! 
char unneeded[1024*4]; 
while (BIO_read(dataPKCS7_BIO, unneeded, sizeof(buffer)) > 0); 

int result; 
X509_STORE *certificateStore = X509_STORE_new(); 
X509_STORE_CTX certificateContext; 
STACK_OF(PKCS7_SIGNER_INFO) *signerStack = PKCS7_get_signer_info(sig_pkcs7); 
int numSignerInfo = sk_PKCS7_SIGNER_INFO_num(signerStack); 
for (int i=0; i<numSignerInfo; ++i) { 
    PKCS7_SIGNER_INFO *signerInfo = sk_PKCS7_SIGNER_INFO_value(signerStack, i); 
    result = PKCS7_dataVerify(certificateStore, &certificateContext, data_pkcs7_BIO, sig_pkcs7, signerInfo); 
} 

X509_STORE_CTX_cleanup(&certificateContext); 
BIO_free(sig_BIO); 
BIO_free(data_BIO); 
BIO_free(data_pkcs7_BIO); 
PKCS7_free(sig_pkcs7); 
X509_STORE_free(certificateStore); 

eser aslında PKCS7_dataVerify olduğunu ve herhangi sindirir kendiniz çalıştırmak gerekmez yapar işlevi.

Ama bekleyin, eğer bunu denerseniz, işe yaramaz! Niye ya? Çünkü doğrulama hem güvenilir hem de dürüst. Buna ek olarak, aynı zamanda karmaşık ve belgesiz olan mağazaya sertifika ekleyerek de güven tesis etmeniz gerekecektir.

X509_VERIFY_PARAM_set_flags(certificateStore->param, X509_V_FLAG_CB_ISSUER_CHECK); 
X509_STORE_set_verify_cb_func(certificateStore, verificationCallback); 

static int verificationCallback(int ok, X509_STORE_CTX *ctx) { 
    switch (ctx->error) 
    { 
     case X509_V_ERR_INVALID_PURPOSE: //... 
     case X509_V_ERR_CERT_HAS_EXPIRED: //... 
     case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: //... 
     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: //... 
     // ... etc 
     default: break; 
    } 
    return ok; 
} 

İyi misin hatayı ayarla ve söyleyebilir: ince taneli sonuçlarını istiyorsanız böyle sertifika depolama yoluyla doğrulama bir geri arama ayarlamak isteyeceksiniz için Örneğin, geçerliliğini yitirmiş olan sertifikaları görmezden gelmek istiyorsanız, örneğin doğrulamak için: