2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
12 % MagickCore Methods to Compute a Message Digest for an Image %
19 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
25 % https://imagemagick.org/script/license.php %
27 % Unless required by applicable law or agreed to in writing, software %
28 % distributed under the License is distributed on an "AS IS" BASIS, %
29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30 % See the License for the specific language governing permissions and %
31 % limitations under the License. %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/cache.h"
44 #include "MagickCore/exception.h"
45 #include "MagickCore/exception-private.h"
46 #include "MagickCore/property.h"
47 #include "MagickCore/image.h"
48 #include "MagickCore/memory_.h"
49 #include "MagickCore/memory-private.h"
50 #include "MagickCore/pixel-accessor.h"
51 #include "MagickCore/quantum.h"
52 #include "MagickCore/quantum-private.h"
53 #include "MagickCore/signature.h"
54 #include "MagickCore/signature-private.h"
55 #include "MagickCore/string_.h"
59 #define SignatureBlocksize 64
60 #define SignatureDigestsize 32
97 TransformSignature(SignatureInfo *);
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 + A c q u i r e S i g n a t u r e I n f o %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 % AcquireSignatureInfo() allocate the SignatureInfo structure.
112 % The format of the AcquireSignatureInfo method is:
114 % SignatureInfo *AcquireSignatureInfo(void)
117 MagickPrivate SignatureInfo *AcquireSignatureInfo(void)
125 signature_info=(SignatureInfo *) AcquireCriticalMemory(
126 sizeof(*signature_info));
127 (void) memset(signature_info,0,sizeof(*signature_info));
128 signature_info->digestsize=SignatureDigestsize;
129 signature_info->blocksize=SignatureBlocksize;
130 signature_info->digest=AcquireStringInfo(SignatureDigestsize);
131 signature_info->message=AcquireStringInfo(SignatureBlocksize);
132 signature_info->accumulator=(unsigned int *) AcquireQuantumMemory(
133 SignatureBlocksize,sizeof(*signature_info->accumulator));
134 if (signature_info->accumulator == (unsigned int *) NULL)
135 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
136 (void) memset(signature_info->accumulator,0,SignatureBlocksize*
137 sizeof(*signature_info->accumulator));
139 signature_info->lsb_first=(int) (*(char *) &lsb_first) == 1 ? MagickTrue :
141 signature_info->timestamp=(ssize_t) time((time_t *) NULL);
142 signature_info->signature=MagickCoreSignature;
143 InitializeSignature(signature_info);
144 return(signature_info);
148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 + D e s t r o y S i g n a t u r e I n f o %
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 % DestroySignatureInfo() zeros memory associated with the SignatureInfo
161 % The format of the DestroySignatureInfo method is:
163 % SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
165 % A description of each parameter follows:
167 % o signature_info: the cipher signature_info.
170 MagickPrivate SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
172 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
173 assert(signature_info != (SignatureInfo *) NULL);
174 assert(signature_info->signature == MagickCoreSignature);
175 if (signature_info->accumulator != (unsigned int *) NULL)
176 signature_info->accumulator=(unsigned int *) RelinquishMagickMemory(
177 signature_info->accumulator);
178 if (signature_info->message != (StringInfo *) NULL)
179 signature_info->message=DestroyStringInfo(signature_info->message);
180 if (signature_info->digest != (StringInfo *) NULL)
181 signature_info->digest=DestroyStringInfo(signature_info->digest);
182 signature_info->signature=(~MagickCoreSignature);
183 signature_info=(SignatureInfo *) RelinquishMagickMemory(signature_info);
184 return(signature_info);
188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 + F i n a l i z e S i g n a t u r e %
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 % FinalizeSignature() finalizes the Signature message accumulator computation.
200 % The format of the FinalizeSignature method is:
202 % FinalizeSignature(SignatureInfo *signature_info)
204 % A description of each parameter follows:
206 % o signature_info: the address of a structure of type SignatureInfo.
209 MagickPrivate void FinalizeSignature(SignatureInfo *signature_info)
214 register unsigned char
217 register unsigned int
231 Add padding and return the message accumulator.
233 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
234 assert(signature_info != (SignatureInfo *) NULL);
235 assert(signature_info->signature == MagickCoreSignature);
236 low_order=signature_info->low_order;
237 high_order=signature_info->high_order;
238 extent=((low_order >> 3) & 0x3f);
239 datum=GetStringInfoDatum(signature_info->message);
240 datum[extent++]=(unsigned char) 0x80;
241 if (extent <= (unsigned int) (GetStringInfoLength(signature_info->message)-8))
242 (void) memset(datum+extent,0,GetStringInfoLength(
243 signature_info->message)-8-extent);
246 (void) memset(datum+extent,0,GetStringInfoLength(
247 signature_info->message)-extent);
248 TransformSignature(signature_info);
249 (void) memset(datum,0,GetStringInfoLength(
250 signature_info->message)-8);
252 datum[56]=(unsigned char) (high_order >> 24);
253 datum[57]=(unsigned char) (high_order >> 16);
254 datum[58]=(unsigned char) (high_order >> 8);
255 datum[59]=(unsigned char) high_order;
256 datum[60]=(unsigned char) (low_order >> 24);
257 datum[61]=(unsigned char) (low_order >> 16);
258 datum[62]=(unsigned char) (low_order >> 8);
259 datum[63]=(unsigned char) low_order;
260 TransformSignature(signature_info);
261 p=signature_info->accumulator;
262 q=GetStringInfoDatum(signature_info->digest);
263 for (i=0; i < (SignatureDigestsize/4); i++)
265 *q++=(unsigned char) ((*p >> 24) & 0xff);
266 *q++=(unsigned char) ((*p >> 16) & 0xff);
267 *q++=(unsigned char) ((*p >> 8) & 0xff);
268 *q++=(unsigned char) (*p & 0xff);
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 + G e t S i g n a t u r e B l o c k s i z e %
282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 % GetSignatureBlocksize() returns the Signature blocksize.
286 % The format of the GetSignatureBlocksize method is:
288 % unsigned int *GetSignatureBlocksize(const SignatureInfo *signature_info)
290 % A description of each parameter follows:
292 % o signature_info: the signature info.
295 MagickPrivate unsigned int GetSignatureBlocksize(
296 const SignatureInfo *signature_info)
298 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
299 assert(signature_info != (SignatureInfo *) NULL);
300 assert(signature_info->signature == MagickCoreSignature);
301 return(signature_info->blocksize);
305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 + G e t S i g n a t u r e D i g e s t %
313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 % GetSignatureDigest() returns the signature digest.
317 % The format of the GetSignatureDigest method is:
319 % const StringInfo *GetSignatureDigest(const SignatureInfo *signature_info)
321 % A description of each parameter follows:
323 % o signature_info: the signature info.
326 MagickPrivate const StringInfo *GetSignatureDigest(
327 const SignatureInfo *signature_info)
329 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
330 assert(signature_info != (SignatureInfo *) NULL);
331 assert(signature_info->signature == MagickCoreSignature);
332 return(signature_info->digest);
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 + G e t S i g n a t u r e D i g e s t s i z e %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 % GetSignatureDigestsize() returns the Signature digest size.
348 % The format of the GetSignatureDigestsize method is:
350 % unsigned int *GetSignatureDigestsize(const SignatureInfo *signature_info)
352 % A description of each parameter follows:
354 % o signature_info: the signature info.
357 MagickPrivate unsigned int GetSignatureDigestsize(
358 const SignatureInfo *signature_info)
360 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
361 assert(signature_info != (SignatureInfo *) NULL);
362 assert(signature_info->signature == MagickCoreSignature);
363 return(signature_info->digestsize);
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 + I n i t i a l i z e S i g n a t u r e %
375 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377 % InitializeSignature() initializes the Signature accumulator.
379 % The format of the DestroySignatureInfo method is:
381 % void InitializeSignatureInfo(SignatureInfo *signature_info)
383 % A description of each parameter follows:
385 % o signature_info: the cipher signature_info.
388 MagickPrivate void InitializeSignature(SignatureInfo *signature_info)
390 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
391 assert(signature_info != (SignatureInfo *) NULL);
392 assert(signature_info->signature == MagickCoreSignature);
393 signature_info->accumulator[0]=0x6a09e667U;
394 signature_info->accumulator[1]=0xbb67ae85U;
395 signature_info->accumulator[2]=0x3c6ef372U;
396 signature_info->accumulator[3]=0xa54ff53aU;
397 signature_info->accumulator[4]=0x510e527fU;
398 signature_info->accumulator[5]=0x9b05688cU;
399 signature_info->accumulator[6]=0x1f83d9abU;
400 signature_info->accumulator[7]=0x5be0cd19U;
401 signature_info->low_order=0;
402 signature_info->high_order=0;
403 signature_info->extent=0;
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 + S e t S i g n a t u r e D i g e s t %
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 % SetSignatureDigest() set the signature digest.
419 % The format of the SetSignatureDigest method is:
421 % SetSignatureDigest(SignatureInfo *signature_info,
422 % const StringInfo *digest)
424 % A description of each parameter follows:
426 % o signature_info: the signature info.
428 % o digest: the digest.
431 MagickPrivate void SetSignatureDigest(SignatureInfo *signature_info,
432 const StringInfo *digest)
435 Set the signature accumulator.
437 assert(signature_info != (SignatureInfo *) NULL);
438 assert(signature_info->signature == MagickCoreSignature);
439 SetStringInfo(signature_info->digest,digest);
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 % S i g n a t u r e I m a g e %
451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 % SignatureImage() computes a message digest from an image pixel stream with
454 % an implementation of the NIST SHA-256 Message Digest algorithm. This
455 % signature uniquely identifies the image and is convenient for determining
456 % if an image has been modified or whether two images are identical.
458 % The format of the SignatureImage method is:
460 % MagickBooleanType SignatureImage(Image *image,ExceptionInfo *exception)
462 % A description of each parameter follows:
464 % o image: the image.
466 % o exception: return any errors or warnings in this structure.
469 MagickExport MagickBooleanType SignatureImage(Image *image,
470 ExceptionInfo *exception)
481 register const Quantum
497 Compute image digital signature.
499 assert(image != (Image *) NULL);
500 assert(image->signature == MagickCoreSignature);
501 if (image->debug != MagickFalse)
502 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
503 signature_info=AcquireSignatureInfo();
504 signature=AcquireStringInfo(GetPixelChannels(image)*image->columns*
506 image_view=AcquireVirtualCacheView(image,exception);
507 for (y=0; y < (ssize_t) image->rows; y++)
512 register unsigned char
515 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
516 if (p == (const Quantum *) NULL)
518 SetStringInfoLength(signature,GetPixelChannels(image)*image->columns*
520 pixels=GetStringInfoDatum(signature);
522 for (x=0; x < (ssize_t) image->columns; x++)
527 if (GetPixelReadMask(image,p) <= (QuantumRange/2))
529 p+=GetPixelChannels(image);
532 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
537 PixelChannel channel = GetPixelChannelChannel(image,i);
538 PixelTrait traits = GetPixelChannelTraits(image,channel);
539 if (traits == UndefinedPixelTrait)
541 pixel=QuantumScale*p[i];
542 if (signature_info->lsb_first == MagickFalse)
543 for (j=(ssize_t) sizeof(pixel)-1; j >= 0; j--)
544 *q++=(unsigned char) ((unsigned char *) &pixel)[j];
546 for (j=0; j < (ssize_t) sizeof(pixel); j++)
547 *q++=(unsigned char) ((unsigned char *) &pixel)[j];
549 p+=GetPixelChannels(image);
551 SetStringInfoLength(signature,(size_t) (q-pixels));
552 UpdateSignature(signature_info,signature);
554 image_view=DestroyCacheView(image_view);
555 FinalizeSignature(signature_info);
556 hex_signature=StringInfoToHexString(GetSignatureDigest(signature_info));
557 (void) DeleteImageProperty(image,"signature");
558 (void) SetImageProperty(image,"signature",hex_signature,exception);
562 hex_signature=DestroyString(hex_signature);
563 signature=DestroyStringInfo(signature);
564 signature_info=DestroySignatureInfo(signature_info);
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 + T r a n s f o r m S i g n a t u r e %
577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579 % TransformSignature() transforms the Signature message accumulator.
581 % The format of the TransformSignature method is:
583 % TransformSignature(SignatureInfo *signature_info)
585 % A description of each parameter follows:
587 % o signature_info: the address of a structure of type SignatureInfo.
591 static inline unsigned int Ch(unsigned int x,unsigned int y,unsigned int z)
593 return((x & y) ^ (~x & z));
596 static inline unsigned int Maj(unsigned int x,unsigned int y,unsigned int z)
598 return((x & y) ^ (x & z) ^ (y & z));
601 static inline unsigned int Trunc32(unsigned int x)
603 return((unsigned int) (x & 0xffffffffU));
606 static unsigned int RotateRight(unsigned int x,unsigned int n)
608 return(Trunc32((x >> n) | (x << (32-n))));
611 static void TransformSignature(SignatureInfo *signature_info)
613 #define Sigma0(x) (RotateRight(x,7) ^ RotateRight(x,18) ^ Trunc32((x) >> 3))
614 #define Sigma1(x) (RotateRight(x,17) ^ RotateRight(x,19) ^ Trunc32((x) >> 10))
615 #define Suma0(x) (RotateRight(x,2) ^ RotateRight(x,13) ^ RotateRight(x,22))
616 #define Suma1(x) (RotateRight(x,6) ^ RotateRight(x,11) ^ RotateRight(x,25))
621 register unsigned char
630 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU,
631 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U,
632 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U,
633 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
634 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U,
635 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U,
636 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
637 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
638 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U,
639 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U,
640 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU,
641 0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
642 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
643 }; /* 32-bit fractional part of the cube root of the first 64 primes */
661 p=GetStringInfoDatum(signature_info->message);
662 if (signature_info->lsb_first == MagickFalse)
664 DisableMSCWarning(4127)
665 if (sizeof(unsigned int) <= 4)
667 for (i=0; i < 16; i++)
669 T=(*((unsigned int *) p));
674 for (i=0; i < 16; i+=2)
676 T=(*((unsigned int *) p));
678 W[i]=Trunc32(T >> shift);
683 DisableMSCWarning(4127)
684 if (sizeof(unsigned int) <= 4)
686 for (i=0; i < 16; i++)
688 T=(*((unsigned int *) p));
690 W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
691 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
694 for (i=0; i < 16; i+=2)
696 T=(*((unsigned int *) p));
698 W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
699 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
701 W[i+1]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
702 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
705 Copy accumulator to registers.
707 A=signature_info->accumulator[0];
708 B=signature_info->accumulator[1];
709 C=signature_info->accumulator[2];
710 D=signature_info->accumulator[3];
711 E=signature_info->accumulator[4];
712 F=signature_info->accumulator[5];
713 G=signature_info->accumulator[6];
714 H=signature_info->accumulator[7];
715 for (i=16; i < 64; i++)
716 W[i]=Trunc32(Sigma1(W[i-2])+W[i-7]+Sigma0(W[i-15])+W[i-16]);
717 for (j=0; j < 64; j++)
719 T1=Trunc32(H+Suma1(E)+Ch(E,F,G)+K[j]+W[j]);
720 T2=Trunc32(Suma0(A)+Maj(A,B,C));
731 Add registers back to accumulator.
733 signature_info->accumulator[0]=Trunc32(signature_info->accumulator[0]+A);
734 signature_info->accumulator[1]=Trunc32(signature_info->accumulator[1]+B);
735 signature_info->accumulator[2]=Trunc32(signature_info->accumulator[2]+C);
736 signature_info->accumulator[3]=Trunc32(signature_info->accumulator[3]+D);
737 signature_info->accumulator[4]=Trunc32(signature_info->accumulator[4]+E);
738 signature_info->accumulator[5]=Trunc32(signature_info->accumulator[5]+F);
739 signature_info->accumulator[6]=Trunc32(signature_info->accumulator[6]+G);
740 signature_info->accumulator[7]=Trunc32(signature_info->accumulator[7]+H);
742 Reset working registers.
755 (void) memset(W,0,sizeof(W));
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763 + U p d a t e S i g n a t u r e %
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
769 % UpdateSignature() updates the Signature message accumulator.
771 % The format of the UpdateSignature method is:
773 % UpdateSignature(SignatureInfo *signature_info,const StringInfo *message)
775 % A description of each parameter follows:
777 % o signature_info: the address of a structure of type SignatureInfo.
779 % o message: the message.
782 MagickPrivate void UpdateSignature(SignatureInfo *signature_info,
783 const StringInfo *message)
788 register unsigned char
798 Update the Signature accumulator.
800 assert(signature_info != (SignatureInfo *) NULL);
801 assert(signature_info->signature == MagickCoreSignature);
802 n=GetStringInfoLength(message);
803 length=Trunc32((unsigned int) (signature_info->low_order+(n << 3)));
804 if (length < signature_info->low_order)
805 signature_info->high_order++;
806 signature_info->low_order=length;
807 signature_info->high_order+=(unsigned int) n >> 29;
808 p=GetStringInfoDatum(message);
809 if (signature_info->extent != 0)
811 i=GetStringInfoLength(signature_info->message)-signature_info->extent;
814 (void) memcpy(GetStringInfoDatum(signature_info->message)+
815 signature_info->extent,p,i);
818 signature_info->extent+=i;
819 if (signature_info->extent != GetStringInfoLength(signature_info->message))
821 TransformSignature(signature_info);
823 while (n >= GetStringInfoLength(signature_info->message))
825 SetStringInfoDatum(signature_info->message,p);
826 p+=GetStringInfoLength(signature_info->message);
827 n-=GetStringInfoLength(signature_info->message);
828 TransformSignature(signature_info);
830 (void) memcpy(GetStringInfoDatum(signature_info->message),p,n);
831 signature_info->extent=n;