RSA BSAFE Crypto-C

Cryptographic Components for C

Search

BER-encoding the Digest

This sample demonstrates how to send a digest to a recipient. It is recommended that the algorithm and digest are BER-encoded.

/* $Id: mdber.c,v 1.6 2004/12/03 02:08:36 sparki Exp $ */
/*
 * Copyright (C) 1998-2004 RSA Security Inc.
 *
 * This file shall only be used to demonstrate how to interface to an
 * RSA Security Inc. licensed development product.
 *
 * You have a royalty-free right to use, reproduce and distribute this
 * demonstration file, provided that you agree that RSA Security Inc.
 * has no warranty, implied or otherwise, or liability for this
 * demonstration file (including any modified version).  This software
 * is provided "as is" without warranties or representations of any
 * kind. RSA Security disclaims all conditions and warranties, statutory
 * and otherwise, both express and implied, with respect to the software,
 * its quality and performance, including but not limited to, all
 * implied warranties of merchantability, fitness for a particular
 * purpose, title and noninfringement of third party rights. Without
 * limiting the foregoing, RSA Security does not warrant that the
 * software is error-free or that errors in the product will be
 * corrected. You agree that RSA Security shall not be liable for any
 * direct, indirect, incidental, special, consequential, punitive or
 * other damages whatsoever resulting from your use of this software
 * or any modified version.
 *
 *
 */

/*  This program will prompt the user for some input to digest.  You may
 *  want to rerun this program using the same input data to prove 
 *  that you get the same digest.  A slight change to the data
 *  will result in a totally different digest.
 *
 *  This program is a slight variation to mdigest.c in that it illustrates
 *  the BER encoding of a digest as a PKCS #1 DigestInfo.
 */

#include "bsafe.h"
#include "demoutil.h"  /* in samples/common/include */

#define DIGEST_LEN 20

/* 15 bytes for SHA1, 18 for MD5 */
#define DIGEST_INFO_LEN DIGEST_LEN + 15

#define BUF_LEN 256         /* arbitrary */

B_ALGORITHM_METHOD *DIGEST_CHOOSER[] = {
  &AM_SHA,
  (B_ALGORITHM_METHOD *)NULL_PTR

/* This will fix a problem that the IA64 compiler finds when *
 * seeing a short chooser list */
#ifdef IA64_FORCE_LARGE
                IA64_FORCE_LARGE
#endif
};


#ifdef CRYPTOC_APP
#define MAIN mdberMain
#else
#define MAIN main
#endif

int MAIN(int argc, char *argv[])
{
  B_ALGORITHM_OBJ digester = (B_ALGORITHM_OBJ)NULL_PTR;
  unsigned char dataToDigest[BUF_LEN];
  unsigned int dataToDigestLen;
  unsigned char digestedData[DIGEST_LEN];
  unsigned int digestedDataLen;

  ITEM *sha1AlgInfoBER;

  /* buffer to hold digest OID information & 20-byte digest */
  unsigned char digestInfoBER[DIGEST_INFO_LEN];
  unsigned int digestInfoBERLen;

  ITEM retrievedAlgorithmID;
  ITEM retrievedDigest;
  int status;

  do {
    /* The RSA_* demo code utilities are described in
       common/include/demoutil.h.  This procedure simply checks the
       command-line arguments for input or output options. */
    if ((status = RSA_SetOptions (argc, argv)) != 0)
      break;

    RSA_PrintMessage ("BER-encoded Message Digest using SHA1\n");
    RSA_PrintMessage ("=====================================\n");

    /*  Create an algorithm object */
    if ((status = B_CreateAlgorithmObject (&digester)) != 0)
      break;

    /*  Set the algorithm object to SHA1 */
    if ((status = B_SetAlgorithmInfo (digester, AI_SHA1, NULL_PTR)) != 0)
      break;

    /*  Initialize the digest algorithm. Prompt the user for input. */
    if ((status = B_DigestInit (digester, (B_KEY_OBJ)NULL_PTR, DIGEST_CHOOSER,
                                (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    do {
      status = RSA_GetCommand ((char *)dataToDigest, sizeof (dataToDigest),
                               "Enter data to digest");
    } while (status != 0);

    dataToDigestLen = T_strlen ((char *)dataToDigest);

    RSA_PrintBuf ("Data to Digest", dataToDigest, dataToDigestLen);

    /*  Update -- Digest the user's input */
    if ((status = B_DigestUpdate (digester, dataToDigest, dataToDigestLen,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Final */
    if ((status = B_DigestFinal (digester, digestedData, &digestedDataLen,
                                 DIGEST_LEN,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    RSA_PrintBuf ("Digested Data", digestedData, digestedDataLen);

    /*  BER-encode the digest  */
    if ((status = B_GetAlgorithmInfo ((POINTER *)&sha1AlgInfoBER, digester,
                                      AI_SHA1_BER)) != 0)
      break;

    if ((status = B_EncodeDigestInfo (digestInfoBER, &digestInfoBERLen,
                                      DIGEST_INFO_LEN, sha1AlgInfoBER,
                                      digestedData, digestedDataLen)) != 0)
      break;

    RSA_PrintBuf ("BER-encoded Digest", digestInfoBER, digestInfoBERLen);

    /*  BER-decode the BER-encoded digest   */
    if ((status = B_DecodeDigestInfo (&retrievedAlgorithmID, &retrievedDigest,
                                      digestInfoBER, digestInfoBERLen)) != 0)
      break;

    RSA_PrintBuf ("Retrieved Algorithm ID", retrievedAlgorithmID.data,
                  retrievedAlgorithmID.len);

    RSA_PrintBuf ("Retrieved Digest", retrievedDigest.data,
                  retrievedDigest.len);

    if (digestedDataLen != retrievedDigest.len) {
      status = RSA_DEMO_E_INFO_DOES_NOT_VERIFY;
      break;
    }

    if (T_memcmp (digestedData, retrievedDigest.data,
                  retrievedDigest.len) != 0) {
      status = RSA_DEMO_E_INFO_DOES_NOT_VERIFY;
      break;
    }

    RSA_PrintMessage ("Retrieved digest matches with digested data!\n");
  } while (0);

  if (status != 0)
    RSA_PrintError ("mdber", status);

  /*  Remember to destroy all objects, and free up any memory
      allocated   */
  B_DestroyAlgorithmObject (&digester);

  T_memset (dataToDigest, 0, BUF_LEN);

  return (status);
} /*  end main  */

Copyright (c) 1999-2005 RSA Security Inc. All rights reserved. 068-001001-6210-001-000 - 6.2.1