home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ImageMagick / magick / signature.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  17.4 KB  |  542 lines

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %                                                                             %
  4. %                                                                             %
  5. %        SSSSS  IIIII   GGGG  N   N   AAA   TTTTT  U   U  RRRR   EEEEE        %
  6. %        SS       I    G      NN  N  A   A    T    U   U  R   R  E            %
  7. %         SSS     I    G  GG  N N N  AAAAA    T    U   U  RRRR   EEE          %
  8. %           SS    I    G   G  N  NN  A   A    T    U   U  R R    E            %
  9. %        SSSSS  IIIII   GGG   N   N  A   A    T     UUU   R  R   EEEEE        %
  10. %                                                                             %
  11. %                                                                             %
  12. %               Compute a Digital Signature for a Image Colormap              %
  13. %                                                                             %
  14. %                                                                             %
  15. %                                                                             %
  16. %                           Software Design                                   %
  17. %                             John Cristy                                     %
  18. %                            December 1992                                    %
  19. %                                                                             %
  20. %  Copyright 1994 E. I. du Pont de Nemours & Company                          %
  21. %                                                                             %
  22. %  Permission to use, copy, modify, distribute, and sell this software and    %
  23. %  its documentation for any purpose is hereby granted without fee,           %
  24. %  provided that the above Copyright notice appear in all copies and that     %
  25. %  both that Copyright notice and this permission notice appear in            %
  26. %  supporting documentation, and that the name of E. I. du Pont de Nemours    %
  27. %  & Company not be used in advertising or publicity pertaining to            %
  28. %  distribution of the software without specific, written prior               %
  29. %  permission.  E. I. du Pont de Nemours & Company makes no representations   %
  30. %  about the suitability of this software for any purpose.  It is provided    %
  31. %  "as is" without express or implied warranty.                               %
  32. %                                                                             %
  33. %  E. I. du Pont de Nemours & Company disclaims all warranties with regard    %
  34. %  to this software, including all implied warranties of merchantability      %
  35. %  and fitness, in no event shall E. I. du Pont de Nemours & Company be       %
  36. %  liable for any special, indirect or consequential damages or any           %
  37. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  38. %  in an action of contract, negligence or other tortuous action, arising     %
  39. %  out of or in connection with the use or performance of this software.      %
  40. %                                                                             %
  41. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42. %
  43. %  Routine ColormapSignature computes a digital signature from the image
  44. %  colormap.  This signature uniquely identifies the colormap and is convenient
  45. %  for determining if the colormap of a sequence of images is identical when
  46. %  animating.  The digital signature is from RSA Data Security MD5 Digest
  47. %  Algorithm described in Internet draft [MD5], July 1992.
  48. %
  49. %
  50. */
  51.  
  52. /*
  53.   Include declarations.
  54. */
  55. #include "magick.h"
  56. #include "image.h"
  57.  
  58. /*
  59.   Typedef declarations.
  60. */
  61. typedef struct _MessageDigest
  62. {
  63.   unsigned long
  64.     number_bits[2],
  65.     accumulator[4];
  66.  
  67.   unsigned char
  68.     message[64],
  69.     digest[16];
  70. } MessageDigest;
  71.  
  72. /*
  73.   Forward declarations.
  74. */
  75. static void
  76.   TransformMessageDigest _Declare((MessageDigest *,unsigned long *)),
  77.   UpdateMessageDigest _Declare((MessageDigest *,unsigned char *,unsigned long));
  78.  
  79. /*
  80. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  81. %                                                                             %
  82. %                                                                             %
  83. %                                                                             %
  84. %   C o m p u t e M e s s a g e D i g e s t                                   %
  85. %                                                                             %
  86. %                                                                             %
  87. %                                                                             %
  88. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  89. %
  90. %  Function ComputeMessageDigest computes the message digest.
  91. %
  92. %  The format of the ComputeMessageDigest routine is:
  93. %
  94. %      ComputeMessageDigest(message_digest,input_message,message_length)
  95. %
  96. %  A description of each parameter follows:
  97. %
  98. %    o message_digest: The address of a structure of type MessageDigest.
  99. %
  100. %
  101. */
  102. static void ComputeMessageDigest(message_digest)
  103. MessageDigest
  104.   *message_digest;
  105. {
  106.   int
  107.     number_bytes;
  108.  
  109.   register unsigned char
  110.     *p;
  111.  
  112.   register unsigned int
  113.     i;
  114.  
  115.   unsigned char
  116.     padding[64];
  117.  
  118.   unsigned long
  119.     message[16],
  120.     padding_length;
  121.  
  122.   /*
  123.     Save number of bits.
  124.   */
  125.   message[14]=message_digest->number_bits[0];
  126.   message[15]=message_digest->number_bits[1];
  127.   /*
  128.     Compute number of bytes mod 64.
  129.   */
  130.   number_bytes=(int) ((message_digest->number_bits[0] >> 3) & 0x3F);
  131.   /*
  132.     Pad message to 56 mod 64.
  133.   */
  134.   padding_length=(number_bytes < 56) ? (56-number_bytes) : (120-number_bytes);
  135.   padding[0]=0x80;
  136.   for (i=1; i < padding_length; i++)
  137.     padding[i]=(char) 0;
  138.   UpdateMessageDigest(message_digest,padding,padding_length);
  139.   /*
  140.     Append length in bits and transform.
  141.   */
  142.   p=message_digest->message;
  143.   for (i=0; i < 14; i++)
  144.   {
  145.     message[i]=(unsigned long) (*p++);
  146.     message[i]|=((unsigned long) (*p++)) << 8;
  147.     message[i]|=((unsigned long) (*p++)) << 16;
  148.     message[i]|=((unsigned long) (*p++)) << 24;
  149.   }
  150.   TransformMessageDigest(message_digest,message);
  151.   /*
  152.     Store message in digest.
  153.   */
  154.   p=message_digest->digest;
  155.   for (i=0; i < 4; i++)
  156.   {
  157.     *p++=(unsigned char) (message_digest->accumulator[i] & 0xff);
  158.     *p++=(unsigned char) ((message_digest->accumulator[i] >> 8) & 0xff);
  159.     *p++=(unsigned char) ((message_digest->accumulator[i] >> 16) & 0xff);
  160.     *p++=(unsigned char) ((message_digest->accumulator[i] >> 24) & 0xff);
  161.   }
  162. }
  163.  
  164. /*
  165. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  166. %                                                                             %
  167. %                                                                             %
  168. %                                                                             %
  169. %   I n i t i a l i z e M e s s a g e D i g e s t                             %
  170. %                                                                             %
  171. %                                                                             %
  172. %                                                                             %
  173. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  174. %
  175. %  Function InitializeMessageDigest initializes the message digest structure.
  176. %
  177. %  The format of the InitializeMessageDigest routine is:
  178. %
  179. %      InitializeMessageDigest(message_digest)
  180. %
  181. %  A description of each parameter follows:
  182. %
  183. %    o message_digest: The address of a structure of type MessageDigest.
  184. %
  185. %
  186. */
  187. static void InitializeMessageDigest(message_digest)
  188. MessageDigest
  189.   *message_digest;
  190. {
  191.   message_digest->number_bits[0]=(unsigned long) 0;
  192.   message_digest->number_bits[1]=(unsigned long) 0;
  193.   /*
  194.     Load magic initialization constants.
  195.   */
  196.   message_digest->accumulator[0]=(unsigned long) 0x67452301;
  197.   message_digest->accumulator[1]=(unsigned long) 0xefcdab89;
  198.   message_digest->accumulator[2]=(unsigned long) 0x98badcfe;
  199.   message_digest->accumulator[3]=(unsigned long) 0x10325476;
  200. }
  201.  
  202. /*
  203. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  204. %                                                                             %
  205. %                                                                             %
  206. %                                                                             %
  207. %   T r a n s f o r m M e s s a g e D i g e s t                               %
  208. %                                                                             %
  209. %                                                                             %
  210. %                                                                             %
  211. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  212. %
  213. %  Function TransformMessageDigest updates the message digest.
  214. %
  215. %  The format of the TransformMessageDigest routine is:
  216. %
  217. %      TransformMessageDigest(message_digest,message)
  218. %
  219. %  A description of each parameter follows:
  220. %
  221. %    o message_digest: The address of a structure of type MessageDigest.
  222. %
  223. %
  224. */
  225. static void TransformMessageDigest(message_digest,message)
  226. MessageDigest
  227.   *message_digest;
  228.  
  229. unsigned long
  230.   *message;
  231. {
  232. #define F(x,y,z)  (((x) & (y)) | ((~x) & (z)))
  233. #define G(x,y,z)  (((x) & (z)) | ((y) & (~z)))
  234. #define H(x,y,z)  ((x) ^ (y) ^ (z))
  235. #define I(x,y,z)  ((y) ^ ((x) | (~z)))
  236. #define RotateLeft(x,n)  (((x) << (n)) | (((x) & 0xffffffff) >> (32-(n))))
  237.  
  238.   static unsigned long
  239.     additive_constant[64]=  /* 4294967296*abs(sin(i)), i in radians */
  240.     {
  241.       0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf,
  242.       0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af,
  243.       0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e,
  244.       0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
  245.       0xd62f105d, 0x2441453,  0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6,
  246.       0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
  247.       0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
  248.       0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
  249.       0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,  0xd9d4d039,
  250.       0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97,
  251.       0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d,
  252.       0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
  253.       0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
  254.     };
  255.  
  256.   register int
  257.     i;
  258.  
  259.   register unsigned int
  260.     j;
  261.  
  262.   register unsigned long
  263.     a,
  264.     b,
  265.     c,
  266.     d,
  267.     *p;
  268.  
  269.   /*
  270.     Save accumulator.
  271.   */
  272.   a=message_digest->accumulator[0];
  273.   b=message_digest->accumulator[1];
  274.   c=message_digest->accumulator[2];
  275.   d=message_digest->accumulator[3];
  276.   /*
  277.     a=b+((a+F(b,c,d)+X[k]+t) <<< s).
  278.   */
  279.   p=additive_constant;
  280.   j=0;
  281.   for (i=0; i < 4; i++)
  282.   {
  283.     a+=F(b,c,d)+message[j & 0x0f]+(*p++);
  284.     a=RotateLeft(a,7)+b;
  285.     j++;
  286.     d+=F(a,b,c)+message[j & 0x0f]+(*p++);
  287.     d=RotateLeft(d,12)+a;
  288.     j++;
  289.     c+=F(d,a,b)+message[j & 0x0f]+(*p++);
  290.     c=RotateLeft(c,17)+d;
  291.     j++;
  292.     b+=F(c,d,a)+message[j & 0x0f]+(*p++);
  293.     b=RotateLeft(b,22)+c;
  294.     j++;
  295.   }
  296.   /*
  297.     a=b+((a+G(b,c,d)+X[k]+t) <<< s).
  298.   */
  299.   j=1;
  300.   for (i=0; i < 4; i++)
  301.   {
  302.     a+=G(b,c,d)+message[j & 0x0f]+(*p++);
  303.     a=RotateLeft(a,5)+b;
  304.     j+=5;
  305.     d+=G(a,b,c)+message[j & 0x0f]+(*p++);
  306.     d=RotateLeft(d,9)+a;
  307.     j+=5;
  308.     c+=G(d,a,b)+message[j & 0x0f]+(*p++);
  309.     c=RotateLeft(c,14)+d;
  310.     j+=5;
  311.     b+=G(c,d,a)+message[j & 0x0f]+(*p++);
  312.     b=RotateLeft(b,20)+c;
  313.     j+=5;
  314.   }
  315.   /*
  316.     a=b+((a+H(b,c,d)+X[k]+t) <<< s).
  317.   */
  318.   j=5;
  319.   for (i=0; i < 4; i++)
  320.   {
  321.     a+=H(b,c,d)+message[j & 0x0f]+(*p++);
  322.     a=RotateLeft(a,4)+b;
  323.     j+=3;
  324.     d+=H(a,b,c)+message[j & 0x0f]+(*p++);
  325.     d=RotateLeft(d,11)+a;
  326.     j+=3;
  327.     c+=H(d,a,b)+message[j & 0x0f]+(*p++);
  328.     c=RotateLeft(c,16)+d;
  329.     j+=3;
  330.     b+=H(c,d,a)+message[j & 0x0f]+(*p++);
  331.     b=RotateLeft(b,23)+c;
  332.     j+=3;
  333.   }
  334.   /*
  335.     a=b+((a+I(b,c,d)+X[k]+t) <<< s).
  336.   */
  337.   j=0;
  338.   for (i=0; i < 4; i++)
  339.   {
  340.     a+=I(b,c,d)+message[j & 0x0f]+(*p++);
  341.     a=RotateLeft(a,6)+b;
  342.     j+=7;
  343.     d+=I(a,b,c)+message[j & 0x0f]+(*p++);
  344.     d=RotateLeft(d,10)+a;
  345.     j+=7;
  346.     c+=I(d,a,b)+message[j & 0x0f]+(*p++);
  347.     c=RotateLeft(c,15)+d;
  348.     j+=7;
  349.     b+=I(c,d,a)+message[j & 0x0f]+(*p++);
  350.     b=RotateLeft(b,21)+c;
  351.     j+=7;
  352.   }
  353.   /*
  354.     Increment accumulator.
  355.   */
  356.   message_digest->accumulator[0]+=a;
  357.   message_digest->accumulator[1]+=b;
  358.   message_digest->accumulator[2]+=c;
  359.   message_digest->accumulator[3]+=d;
  360. }
  361.  
  362. /*
  363. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  364. %                                                                             %
  365. %                                                                             %
  366. %                                                                             %
  367. %   U p d a t e M e s s a g e D i g e s t                                     %
  368. %                                                                             %
  369. %                                                                             %
  370. %                                                                             %
  371. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  372. %
  373. %  Function UpdateMessageDigest updates the message digest.
  374. %
  375. %  The format of the UpdateMessageDigest routine is:
  376. %
  377. %      UpdateMessageDigest(message_digest,input_message,message_length)
  378. %
  379. %  A description of each parameter follows:
  380. %
  381. %    o message_digest: The address of a structure of type MessageDigest.
  382. %
  383. %
  384. */
  385. static void UpdateMessageDigest(message_digest,input_message,message_length)
  386. MessageDigest
  387.   *message_digest;
  388.  
  389. unsigned char
  390.   *input_message;
  391.  
  392. unsigned long
  393.   message_length;
  394. {
  395.   int
  396.     number_bytes;
  397.  
  398.   register unsigned char
  399.     *p;
  400.  
  401.   register unsigned int
  402.     i;
  403.  
  404.   unsigned long
  405.     message[16];
  406.  
  407.   /*
  408.     Compute number of bytes mod 64.
  409.   */
  410.   number_bytes=(int) ((message_digest->number_bits[0] >> 3) & 0x3F);
  411.   /*
  412.     Update number of bits.
  413.   */
  414.   if (((message_digest->number_bits[0]+(message_length << 3)) & 0xffffffff) <
  415.       message_digest->number_bits[0])
  416.     message_digest->number_bits[1]++;
  417.   message_digest->number_bits[0]+=message_length << 3;
  418.   message_digest->number_bits[1]+=message_length >> 29;
  419.   while (message_length--)
  420.   {
  421.     /*
  422.       Add new character to message.
  423.     */
  424.     message_digest->message[number_bytes++]=(*input_message++);
  425.     if (number_bytes == 0x40)
  426.       {
  427.         /*
  428.           Transform message digest 64 bytes at a time.
  429.         */
  430.         p=message_digest->message;
  431.         for (i=0; i < 16; i++)
  432.         {
  433.           message[i]=(unsigned long) (*p++);
  434.           message[i]|=((unsigned long) (*p++)) << 8;
  435.           message[i]|=((unsigned long) (*p++)) << 16;
  436.           message[i]|=((unsigned long) (*p++)) << 24;
  437.         }
  438.         TransformMessageDigest(message_digest,message);
  439.         number_bytes=0;
  440.       }
  441.   }
  442. }
  443.  
  444. /*
  445. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  446. %                                                                             %
  447. %                                                                             %
  448. %                                                                             %
  449. %   C o l o r m a p S i g n a t u r e                                         %
  450. %                                                                             %
  451. %                                                                             %
  452. %                                                                             %
  453. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  454. %
  455. %  Fucntion ColormapSignature computes a digital signature from the image
  456. %  colormap.  This signature uniquely identifies the colormap and is convenient
  457. %  for determining if the colormap of a sequence of images is identical when
  458. %  animating.  The digital signature is from RSA Data Security MD5 Digest
  459. %  Algorithm described in Internet draft [MD5], July 1992.
  460. %
  461. %  The format of the ColormapSignature routine is:
  462. %
  463. %      ColormapSignature(image)
  464. %
  465. %  A description of each parameter follows:
  466. %
  467. %    o image: The address of a structure of type Image.
  468. %
  469. %
  470. %
  471. */
  472. void ColormapSignature(image)
  473. Image
  474.   *image;
  475. {
  476.   char
  477.     *hex;
  478.  
  479.   MessageDigest
  480.     message_digest;
  481.  
  482.   register int
  483.     i;
  484.  
  485.   register unsigned char
  486.     *p;
  487.  
  488.   unsigned char
  489.     *colormap;
  490.  
  491.   if (image->class != PseudoClass)
  492.     return;
  493.   /*
  494.     Allocate colormap.
  495.   */
  496.   colormap=(unsigned char *) malloc(3*image->colors*sizeof(unsigned char));
  497.   if (colormap == (unsigned char *) NULL)
  498.     {
  499.       Warning("Unable to compute colormap signature",
  500.         "Memory allocation failed");
  501.       return;
  502.     }
  503.   p=colormap;
  504.   for (i=0; i < image->colors; i++)
  505.   {
  506.     *p++=image->colormap[i].red;
  507.     *p++=image->colormap[i].green;
  508.     *p++=image->colormap[i].blue;
  509.   }
  510.   /*
  511.     Compute program colormap signature.
  512.   */
  513.   InitializeMessageDigest(&message_digest);
  514.   UpdateMessageDigest(&message_digest,colormap,
  515.     (unsigned long) (image->colors*3));
  516.   ComputeMessageDigest(&message_digest);
  517.   (void) free((char *) colormap);
  518.   /*
  519.     Allocate memory for signature.
  520.   */
  521.   if (image->signature != (char *) NULL)
  522.     (void) free((char *) image->signature);
  523.   image->signature=(char *) malloc(33*sizeof(char));
  524.   if (image->signature == (char *) NULL)
  525.     {
  526.       Warning("Unable to compute colormap signature",
  527.         "Memory allocation failed");
  528.       return;
  529.     }
  530.   /*
  531.     Convert digital signature to a 32 character hex string.
  532.   */
  533.   p=(unsigned char *) image->signature;
  534.   hex="0123456789abcdef";
  535.   for (i=0; i < 16; i++)
  536.   {
  537.     *p++=hex[(message_digest.digest[i] >> 4) & 0xf];
  538.     *p++=hex[message_digest.digest[i] & 0xf];
  539.   }
  540.   *p='\0';
  541. }
  542.