ocssw  1.0
/disk01/web/ocssw/build/src/lib24to8/signature.c (r8106/r2592)
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %        SSSSS  IIIII   GGGG  N   N   AAA   TTTTT  U   U  RRRR   EEEEE        %
00006 %        SS       I    G      NN  N  A   A    T    U   U  R   R  E            %
00007 %         SSS     I    G  GG  N N N  AAAAA    T    U   U  RRRR   EEE          %
00008 %           SS    I    G   G  N  NN  A   A    T    U   U  R R    E            %
00009 %        SSSSS  IIIII   GGG   N   N  A   A    T     UUU   R  R   EEEEE        %
00010 %                                                                             %
00011 %                                                                             %
00012 %               Compute a Digital Signature for a Image Colormap              %
00013 %                                                                             %
00014 %                                                                             %
00015 %                                                                             %
00016 %                           Software Design                                   %
00017 %                             John Cristy                                     %
00018 %                            December 1992                                    %
00019 %                                                                             %
00020 %  Copyright 1994 E. I. du Pont de Nemours and Company                        %
00021 %                                                                             %
00022 %  Permission to use, copy, modify, distribute, and sell this software and    %
00023 %  its documentation for any purpose is hereby granted without fee,           %
00024 %  provided that the above Copyright notice appear in all copies and that     %
00025 %  both that Copyright notice and this permission notice appear in            %
00026 %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
00027 %  and Company not be used in advertising or publicity pertaining to          %
00028 %  distribution of the software without specific, written prior               %
00029 %  permission.  E. I. du Pont de Nemours and Company makes no representations %
00030 %  about the suitability of this software for any purpose.  It is provided    %
00031 %  "as is" without express or implied warranty.                               %
00032 %                                                                             %
00033 %  E. I. du Pont de Nemours and Company disclaims all warranties with regard  %
00034 %  to this software, including all implied warranties of merchantability      %
00035 %  and fitness, in no event shall E. I. du Pont de Nemours and Company be     %
00036 %  liable for any special, indirect or consequential damages or any           %
00037 %  damages whatsoever resulting from loss of use, data or profits, whether    %
00038 %  in an action of contract, negligence or other tortuous action, arising     %
00039 %  out of or in connection with the use or performance of this software.      %
00040 %                                                                             %
00041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00042 %
00043 %  Routine ColormapSignature computes a digital signature from the image
00044 %  colormap.  This signature uniquely identifies the colormap and is convenient
00045 %  for determining if the colormap of a sequence of images is identical when
00046 %  animating.  The digital signature is from RSA Data Security MD5 Digest
00047 %  Algorithm described in Internet draft [MD5], July 1992.
00048 %
00049 %
00050 */
00051 
00052 /*
00053   Include declarations.
00054 */
00055 #include "magick.h"
00056 #include "image.h"
00057 
00058 /*
00059   Typedef declarations.
00060 */
00061 typedef struct _MessageDigest
00062 {
00063   uint32_t 
00064     number_bits[2],
00065     accumulator[4];
00066 
00067   unsigned char
00068     message[64],
00069     digest[16];
00070 } MessageDigest;
00071 
00072 /*
00073   Forward declarations.
00074 */
00075 static void
00076   TransformMessageDigest _Declare((MessageDigest *,uint32_t *)),
00077   UpdateMessageDigest _Declare((MessageDigest *,unsigned char *,uint32_t));
00078 
00079 /*
00080 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00081 %                                                                             %
00082 %                                                                             %
00083 %                                                                             %
00084 %   C o m p u t e M e s s a g e D i g e s t                                   %
00085 %                                                                             %
00086 %                                                                             %
00087 %                                                                             %
00088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00089 %
00090 %  Function ComputeMessageDigest computes the message digest.
00091 %
00092 %  The format of the ComputeMessageDigest routine is:
00093 %
00094 %      ComputeMessageDigest(message_digest,input_message,message_length)
00095 %
00096 %  A description of each parameter follows:
00097 %
00098 %    o message_digest: The address of a structure of type MessageDigest.
00099 %
00100 %
00101 */
00102 static void ComputeMessageDigest(message_digest)
00103 MessageDigest
00104   *message_digest;
00105 {
00106   int
00107     number_bytes;
00108 
00109   register unsigned char
00110     *p;
00111 
00112   register unsigned int
00113     i;
00114 
00115   unsigned char
00116     padding[64];
00117 
00118   uint32_t 
00119     message[16],
00120     padding_length;
00121 
00122   /*
00123     Save number of bits.
00124   */
00125   message[14]=message_digest->number_bits[0];
00126   message[15]=message_digest->number_bits[1];
00127   /*
00128     Compute number of bytes mod 64.
00129   */
00130   number_bytes=(int) ((message_digest->number_bits[0] >> 3) & 0x3F);
00131   /*
00132     Pad message to 56 mod 64.
00133   */
00134   padding_length=(number_bytes < 56) ? (56-number_bytes) : (120-number_bytes);
00135   padding[0]=0x80;
00136   for (i=1; i < padding_length; i++)
00137     padding[i]=(char) 0;
00138   UpdateMessageDigest(message_digest,padding,padding_length);
00139   /*
00140     Append length in bits and transform.
00141   */
00142   p=message_digest->message;
00143   for (i=0; i < 14; i++)
00144   {
00145     message[i]=(uint32_t) (*p++);
00146     message[i]|=((uint32_t) (*p++)) << 8;
00147     message[i]|=((uint32_t) (*p++)) << 16;
00148     message[i]|=((uint32_t) (*p++)) << 24;
00149   }
00150   TransformMessageDigest(message_digest,message);
00151   /*
00152     Store message in digest.
00153   */
00154   p=message_digest->digest;
00155   for (i=0; i < 4; i++)
00156   {
00157     *p++=(unsigned char) (message_digest->accumulator[i] & 0xff);
00158     *p++=(unsigned char) ((message_digest->accumulator[i] >> 8) & 0xff);
00159     *p++=(unsigned char) ((message_digest->accumulator[i] >> 16) & 0xff);
00160     *p++=(unsigned char) ((message_digest->accumulator[i] >> 24) & 0xff);
00161   }
00162 }
00163 
00164 /*
00165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00166 %                                                                             %
00167 %                                                                             %
00168 %                                                                             %
00169 %   I n i t i a l i z e M e s s a g e D i g e s t                             %
00170 %                                                                             %
00171 %                                                                             %
00172 %                                                                             %
00173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00174 %
00175 %  Function InitializeMessageDigest initializes the message digest structure.
00176 %
00177 %  The format of the InitializeMessageDigest routine is:
00178 %
00179 %      InitializeMessageDigest(message_digest)
00180 %
00181 %  A description of each parameter follows:
00182 %
00183 %    o message_digest: The address of a structure of type MessageDigest.
00184 %
00185 %
00186 */
00187 static void InitializeMessageDigest(message_digest)
00188 MessageDigest
00189   *message_digest;
00190 {
00191   message_digest->number_bits[0]=(uint32_t) 0;
00192   message_digest->number_bits[1]=(uint32_t) 0;
00193   /*
00194     Load magic initialization constants.
00195   */
00196   message_digest->accumulator[0]=(uint32_t) 0x67452301;
00197   message_digest->accumulator[1]=(uint32_t) 0xefcdab89;
00198   message_digest->accumulator[2]=(uint32_t) 0x98badcfe;
00199   message_digest->accumulator[3]=(uint32_t) 0x10325476;
00200 }
00201 
00202 /*
00203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00204 %                                                                             %
00205 %                                                                             %
00206 %                                                                             %
00207 %   T r a n s f o r m M e s s a g e D i g e s t                               %
00208 %                                                                             %
00209 %                                                                             %
00210 %                                                                             %
00211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00212 %
00213 %  Function TransformMessageDigest updates the message digest.
00214 %
00215 %  The format of the TransformMessageDigest routine is:
00216 %
00217 %      TransformMessageDigest(message_digest,message)
00218 %
00219 %  A description of each parameter follows:
00220 %
00221 %    o message_digest: The address of a structure of type MessageDigest.
00222 %
00223 %
00224 */
00225 static void TransformMessageDigest(message_digest,message)
00226 MessageDigest
00227   *message_digest;
00228 
00229 uint32_t 
00230   *message;
00231 {
00232 #define F(x,y,z)  (((x) & (y)) | ((~x) & (z)))
00233 #define G(x,y,z)  (((x) & (z)) | ((y) & (~z)))
00234 #define H(x,y,z)  ((x) ^ (y) ^ (z))
00235 #define I(x,y,z)  ((y) ^ ((x) | (~z)))
00236 #define RotateLeft(x,n)  (((x) << (n)) | (((x) & 0xffffffff) >> (32-(n))))
00237 
00238   static uint32_t 
00239     additive_constant[64]=  /* 4294967296*abs(sin(i)), i in radians */
00240     {
00241       0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf,
00242       0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af,
00243       0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e,
00244       0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
00245       0xd62f105d, 0x2441453,  0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6,
00246       0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
00247       0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
00248       0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
00249       0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,  0xd9d4d039,
00250       0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97,
00251       0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d,
00252       0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
00253       0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
00254     };
00255 
00256   register int
00257     i;
00258 
00259   register unsigned int
00260     j;
00261 
00262   register uint32_t 
00263     a,
00264     b,
00265     c,
00266     d,
00267     *p;
00268 
00269   /*
00270     Save accumulator.
00271   */
00272   a=message_digest->accumulator[0];
00273   b=message_digest->accumulator[1];
00274   c=message_digest->accumulator[2];
00275   d=message_digest->accumulator[3];
00276   /*
00277     a=b+((a+F(b,c,d)+X[k]+t) <<< s).
00278   */
00279   p=additive_constant;
00280   j=0;
00281   for (i=0; i < 4; i++)
00282   {
00283     a+=F(b,c,d)+message[j & 0x0f]+(*p++);
00284     a=RotateLeft(a,7)+b;
00285     j++;
00286     d+=F(a,b,c)+message[j & 0x0f]+(*p++);
00287     d=RotateLeft(d,12)+a;
00288     j++;
00289     c+=F(d,a,b)+message[j & 0x0f]+(*p++);
00290     c=RotateLeft(c,17)+d;
00291     j++;
00292     b+=F(c,d,a)+message[j & 0x0f]+(*p++);
00293     b=RotateLeft(b,22)+c;
00294     j++;
00295   }
00296   /*
00297     a=b+((a+G(b,c,d)+X[k]+t) <<< s).
00298   */
00299   j=1;
00300   for (i=0; i < 4; i++)
00301   {
00302     a+=G(b,c,d)+message[j & 0x0f]+(*p++);
00303     a=RotateLeft(a,5)+b;
00304     j+=5;
00305     d+=G(a,b,c)+message[j & 0x0f]+(*p++);
00306     d=RotateLeft(d,9)+a;
00307     j+=5;
00308     c+=G(d,a,b)+message[j & 0x0f]+(*p++);
00309     c=RotateLeft(c,14)+d;
00310     j+=5;
00311     b+=G(c,d,a)+message[j & 0x0f]+(*p++);
00312     b=RotateLeft(b,20)+c;
00313     j+=5;
00314   }
00315   /*
00316     a=b+((a+H(b,c,d)+X[k]+t) <<< s).
00317   */
00318   j=5;
00319   for (i=0; i < 4; i++)
00320   {
00321     a+=H(b,c,d)+message[j & 0x0f]+(*p++);
00322     a=RotateLeft(a,4)+b;
00323     j+=3;
00324     d+=H(a,b,c)+message[j & 0x0f]+(*p++);
00325     d=RotateLeft(d,11)+a;
00326     j+=3;
00327     c+=H(d,a,b)+message[j & 0x0f]+(*p++);
00328     c=RotateLeft(c,16)+d;
00329     j+=3;
00330     b+=H(c,d,a)+message[j & 0x0f]+(*p++);
00331     b=RotateLeft(b,23)+c;
00332     j+=3;
00333   }
00334   /*
00335     a=b+((a+I(b,c,d)+X[k]+t) <<< s).
00336   */
00337   j=0;
00338   for (i=0; i < 4; i++)
00339   {
00340     a+=I(b,c,d)+message[j & 0x0f]+(*p++);
00341     a=RotateLeft(a,6)+b;
00342     j+=7;
00343     d+=I(a,b,c)+message[j & 0x0f]+(*p++);
00344     d=RotateLeft(d,10)+a;
00345     j+=7;
00346     c+=I(d,a,b)+message[j & 0x0f]+(*p++);
00347     c=RotateLeft(c,15)+d;
00348     j+=7;
00349     b+=I(c,d,a)+message[j & 0x0f]+(*p++);
00350     b=RotateLeft(b,21)+c;
00351     j+=7;
00352   }
00353   /*
00354     Increment accumulator.
00355   */
00356   message_digest->accumulator[0]+=a;
00357   message_digest->accumulator[1]+=b;
00358   message_digest->accumulator[2]+=c;
00359   message_digest->accumulator[3]+=d;
00360 }
00361 
00362 /*
00363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00364 %                                                                             %
00365 %                                                                             %
00366 %                                                                             %
00367 %   U p d a t e M e s s a g e D i g e s t                                     %
00368 %                                                                             %
00369 %                                                                             %
00370 %                                                                             %
00371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00372 %
00373 %  Function UpdateMessageDigest updates the message digest.
00374 %
00375 %  The format of the UpdateMessageDigest routine is:
00376 %
00377 %      UpdateMessageDigest(message_digest,input_message,message_length)
00378 %
00379 %  A description of each parameter follows:
00380 %
00381 %    o message_digest: The address of a structure of type MessageDigest.
00382 %
00383 %
00384 */
00385 static void UpdateMessageDigest(message_digest,input_message,message_length)
00386 MessageDigest
00387   *message_digest;
00388 
00389 unsigned char
00390   *input_message;
00391 
00392 uint32_t 
00393   message_length;
00394 {
00395   int
00396     number_bytes;
00397 
00398   register unsigned char
00399     *p;
00400 
00401   register unsigned int
00402     i;
00403 
00404   uint32_t 
00405     message[16];
00406 
00407   /*
00408     Compute number of bytes mod 64.
00409   */
00410   number_bytes=(int) ((message_digest->number_bits[0] >> 3) & 0x3F);
00411   /*
00412     Update number of bits.
00413   */
00414   if (((message_digest->number_bits[0]+(message_length << 3)) & 0xffffffff) <
00415       message_digest->number_bits[0])
00416     message_digest->number_bits[1]++;
00417   message_digest->number_bits[0]+=message_length << 3;
00418   message_digest->number_bits[1]+=message_length >> 29;
00419   while (message_length--)
00420   {
00421     /*
00422       Add new character to message.
00423     */
00424     message_digest->message[number_bytes++]=(*input_message++);
00425     if (number_bytes == 0x40)
00426       {
00427         /*
00428           Transform message digest 64 bytes at a time.
00429         */
00430         p=message_digest->message;
00431         for (i=0; i < 16; i++)
00432         {
00433           message[i]=(uint32_t) (*p++);
00434           message[i]|=((uint32_t) (*p++)) << 8;
00435           message[i]|=((uint32_t) (*p++)) << 16;
00436           message[i]|=((uint32_t) (*p++)) << 24;
00437         }
00438         TransformMessageDigest(message_digest,message);
00439         number_bytes=0;
00440       }
00441   }
00442 }
00443 
00444 /*
00445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00446 %                                                                             %
00447 %                                                                             %
00448 %                                                                             %
00449 %   C o l o r m a p S i g n a t u r e                                         %
00450 %                                                                             %
00451 %                                                                             %
00452 %                                                                             %
00453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00454 %
00455 %  Fucntion ColormapSignature computes a digital signature from the image
00456 %  colormap.  This signature uniquely identifies the colormap and is convenient
00457 %  for determining if the colormap of a sequence of images is identical when
00458 %  animating.  The digital signature is from RSA Data Security MD5 Digest
00459 %  Algorithm described in Internet draft [MD5], July 1992.
00460 %
00461 %  The format of the ColormapSignature routine is:
00462 %
00463 %      ColormapSignature(image)
00464 %
00465 %  A description of each parameter follows:
00466 %
00467 %    o image: The address of a structure of type Image.
00468 %
00469 %
00470 %
00471 */
00472 void ColormapSignature(image)
00473 Image
00474   *image;
00475 {
00476   char
00477     *hex;
00478 
00479   MessageDigest
00480     message_digest;
00481 
00482   register int
00483     i;
00484 
00485   register unsigned char
00486     *p;
00487 
00488   unsigned char
00489     *colormap;
00490 
00491   if (image->class != PseudoClass)
00492     return;
00493   /*
00494     Allocate colormap.
00495   */
00496   colormap=(unsigned char *) malloc(3*image->colors*sizeof(unsigned char));
00497   if (colormap == (unsigned char *) NULL)
00498     {
00499       Warning("Unable to compute colormap signature",
00500         "Memory allocation failed");
00501       return;
00502     }
00503   p=colormap;
00504   for (i=0; i < image->colors; i++)
00505   {
00506     *p++=image->colormap[i].red;
00507     *p++=image->colormap[i].green;
00508     *p++=image->colormap[i].blue;
00509   }
00510   /*
00511     Compute program colormap signature.
00512   */
00513   InitializeMessageDigest(&message_digest);
00514   UpdateMessageDigest(&message_digest,colormap,
00515     (uint32_t) (image->colors*3));
00516   ComputeMessageDigest(&message_digest);
00517   (void) free((char *) colormap);
00518   /*
00519     Allocate memory for signature.
00520   */
00521   if (image->signature != (char *) NULL)
00522     (void) free((char *) image->signature);
00523   image->signature=(char *) malloc(33*sizeof(char));
00524   if (image->signature == (char *) NULL)
00525     {
00526       Warning("Unable to compute colormap signature",
00527         "Memory allocation failed");
00528       return;
00529     }
00530   /*
00531     Convert digital signature to a 32 character hex string.
00532   */
00533   p=(unsigned char *) image->signature;
00534   hex="0123456789abcdef";
00535   for (i=0; i < 16; i++)
00536   {
00537     *p++=hex[(message_digest.digest[i] >> 4) & 0xf];
00538     *p++=hex[message_digest.digest[i] & 0xf];
00539   }
00540   *p='\0';
00541 }