On Mon, 9 Jul 2001, Alexander op de Weegh wrote:

> Hi all,
> I have padding question.
> I am using the following code for creating a PKCS#7
> signed and enveloped message:
>
> X509 *signer, *recipient;
> RSA *signkey;
> p7 = PKCS7_new();
> PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped);
> PKCS7_add_certificate(p7, signer);
> PKCS7_add_certificate(p7, recipient);
> pkey = EVP_PKEY_new();
> EVP_PKEY_assign_RSA(pkey, signkey);
> si = PKCS7_add_signature(p7, signer, pkey, EVP_md5());
> ri = PKCS7_add_recipient(p7, recipient);
> PKCS7_set_cipher(p7, EVP_des_ede3_cbc());
> p7bio = PKCS7_dataInit(p7, NULL);
> BIO_write(data, datalen);
> PKCS7_dataFinal(p7, p7bio);

I was capable to decode plaintext and verify the hash using
the code attached, linked against 0.9.6b

> After doing this, I write the PKCS#7 message as PEM, send it to another
> machine and decode it there. I get an error, saying the no valid padding is
> found.

What was the code that says that? Any more details on the error?

> Which is quite logical, if you ask me, since the data that is
> encrypted using 3DES is not padded at all. So, I add padding and then do the
> BIO_write(). Then the other machine, complaints about an invalid signature.
> Which is also logical, because the receiver decrypts the data, removes the
> padding and then calculates the hash and compares it with the signature.
> But, on the sender's side, the signature is calculated including the
> padding!
>
> Help! What should I do?

Hope this code could be useful.
Please remember to read http://eprint.iacr.org/2001/045/ps.gz
before choosing SignedAndEnveloped, Signed-inside-Enveloped or friends.

regards,
Vadim
/* PKCS7 Signed And Enveloped basic operations
 */

#include <stdio.h>
#include <string.h>
#include <assert.h>

#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/pkcs7.h>

int main() {
  PKCS7 *enc, *dec;
  BIO *p7bio, *fl;
  EVP_CIPHER *cph;
  PKCS7_SIGNER_INFO *si;
  PKCS7_RECIP_INFO *ri;
  X509 *recpt, *signer;
  EVP_PKEY *dec_key, *sig_key;
  int sz, res;
#define BIG 10*1024
  unsigned char *p, bf[BIG], *src = "Some data", decoded[BIG];

  OpenSSL_add_all_algorithms();
  ERR_load_crypto_strings();
  // init PRNG!

  fl = BIO_new_file("recpt.cert", "r");
  recpt = PEM_read_bio_X509(fl, NULL, NULL, NULL);
  BIO_free(fl);
  assert(recpt != NULL);

  fl = BIO_new_file("recpt.key", "r");
  dec_key=PEM_read_bio_PrivateKey(fl, NULL, NULL, NULL);
  BIO_free(fl);
  assert(recpt != NULL);

  fl = BIO_new_file("signer.key", "r");
  sig_key=PEM_read_bio_PrivateKey(fl, NULL, NULL, NULL);
  BIO_free(fl);
  assert(sig_key != NULL);

  fl = BIO_new_file("signer.cert", "r");
  signer = PEM_read_bio_X509(fl, NULL, NULL, NULL);
  BIO_free(fl);
  assert(signer != NULL);

  // prepare an PKCS7
  enc = PKCS7_new();
  assert(enc != NULL);

  res = PKCS7_set_type(enc, NID_pkcs7_signedAndEnveloped);

  PKCS7_content_new(enc, NID_pkcs7_data);

  cph = EVP_des_ede3_cbc();
  res = PKCS7_set_cipher(enc, cph);
  ri = PKCS7_add_recipient(enc, recpt);
  assert(ri != NULL);

  si = PKCS7_add_signature(enc, signer, sig_key, EVP_sha1());
  assert(si != NULL);

  p7bio = PKCS7_dataInit(enc, NULL);
  sz = BIO_write(p7bio, src, strlen(src));
  assert(sz != 0);
  BIO_flush(p7bio);
  res = PKCS7_dataFinal(enc, p7bio);
  assert(res != 0);

  // DER-encode
  p = bf;
  sz = i2d_PKCS7(enc, &p);

  // output/input encoded PKCS7

  // decode
  p = bf;
  dec = d2i_PKCS7(NULL, &p, sz);
  p7bio = PKCS7_dataDecode(dec, dec_key, NULL, recpt);
  assert(p7bio != NULL);

  sz = BIO_read(p7bio, decoded, BIG);

  if(sz == strlen(src))
    printf("Length Ok\n");

  if(!strncmp(src, decoded, sz))
    printf("Data Ok\n");

  // actually, scan signers instead
  si = sk_PKCS7_SIGNER_INFO_value(dec->d.signed_and_enveloped->signer_info, 0);
  assert(si != NULL);

  // try to match calculated and decrypted digests
  // one should verify certificate(s) as well.
  res = PKCS7_signatureVerify(p7bio, dec, si, signer);
  if(res == 1)
    printf("Signature Ok\n");

  return 0;
}

Reply via email to