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-2014 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 % http://www.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/pixel-accessor.h"
50 #include "MagickCore/quantum.h"
51 #include "MagickCore/quantum-private.h"
52 #include "MagickCore/signature.h"
53 #include "MagickCore/signature-private.h"
54 #include "MagickCore/string_.h"
58 #define SignatureBlocksize 64
59 #define SignatureDigestsize 32
96 TransformSignature(SignatureInfo *);
99 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 + A c q u i r e S i g n a t u r e I n f o %
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109 % AcquireSignatureInfo() allocate the SignatureInfo structure.
111 % The format of the AcquireSignatureInfo method is:
113 % SignatureInfo *AcquireSignatureInfo(void)
116 MagickPrivate SignatureInfo *AcquireSignatureInfo(void)
124 signature_info=(SignatureInfo *) AcquireMagickMemory(sizeof(*signature_info));
125 if (signature_info == (SignatureInfo *) NULL)
126 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
127 (void) ResetMagickMemory(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");
137 signature_info->lsb_first=(int) (*(char *) &lsb_first) == 1 ? MagickTrue :
139 signature_info->timestamp=(ssize_t) time(0);
140 signature_info->signature=MagickSignature;
141 InitializeSignature(signature_info);
142 return(signature_info);
146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 + D e s t r o y S i g n a t u r e I n f o %
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156 % DestroySignatureInfo() zeros memory associated with the SignatureInfo
159 % The format of the DestroySignatureInfo method is:
161 % SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
163 % A description of each parameter follows:
165 % o signature_info: the cipher signature_info.
168 MagickPrivate SignatureInfo *DestroySignatureInfo(SignatureInfo *signature_info)
170 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
171 assert(signature_info != (SignatureInfo *) NULL);
172 assert(signature_info->signature == MagickSignature);
173 if (signature_info->accumulator != (unsigned int *) NULL)
174 signature_info->accumulator=(unsigned int *) RelinquishMagickMemory(
175 signature_info->accumulator);
176 if (signature_info->message != (StringInfo *) NULL)
177 signature_info->message=DestroyStringInfo(signature_info->message);
178 if (signature_info->digest != (StringInfo *) NULL)
179 signature_info->digest=DestroyStringInfo(signature_info->digest);
180 signature_info->signature=(~MagickSignature);
181 signature_info=(SignatureInfo *) RelinquishMagickMemory(signature_info);
182 return(signature_info);
186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 + F i n a l i z e S i g n a t u r e %
194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 % FinalizeSignature() finalizes the Signature message accumulator computation.
198 % The format of the FinalizeSignature method is:
200 % FinalizeSignature(SignatureInfo *signature_info)
202 % A description of each parameter follows:
204 % o signature_info: the address of a structure of type SignatureInfo.
207 MagickPrivate void FinalizeSignature(SignatureInfo *signature_info)
212 register unsigned char
215 register unsigned int
227 Add padding and return the message accumulator.
229 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
230 assert(signature_info != (SignatureInfo *) NULL);
231 assert(signature_info->signature == MagickSignature);
232 low_order=signature_info->low_order;
233 high_order=signature_info->high_order;
234 count=((low_order >> 3) & 0x3f);
235 datum=GetStringInfoDatum(signature_info->message);
236 datum[count++]=(unsigned char) 0x80;
237 if (count <= (unsigned int) (GetStringInfoLength(signature_info->message)-8))
238 (void) ResetMagickMemory(datum+count,0,GetStringInfoLength(
239 signature_info->message)-8-count);
242 (void) ResetMagickMemory(datum+count,0,GetStringInfoLength(
243 signature_info->message)-count);
244 TransformSignature(signature_info);
245 (void) ResetMagickMemory(datum,0,GetStringInfoLength(
246 signature_info->message)-8);
248 datum[56]=(unsigned char) (high_order >> 24);
249 datum[57]=(unsigned char) (high_order >> 16);
250 datum[58]=(unsigned char) (high_order >> 8);
251 datum[59]=(unsigned char) high_order;
252 datum[60]=(unsigned char) (low_order >> 24);
253 datum[61]=(unsigned char) (low_order >> 16);
254 datum[62]=(unsigned char) (low_order >> 8);
255 datum[63]=(unsigned char) low_order;
256 TransformSignature(signature_info);
257 p=signature_info->accumulator;
258 q=GetStringInfoDatum(signature_info->digest);
259 for (i=0; i < (SignatureDigestsize/4); i++)
261 *q++=(unsigned char) ((*p >> 24) & 0xff);
262 *q++=(unsigned char) ((*p >> 16) & 0xff);
263 *q++=(unsigned char) ((*p >> 8) & 0xff);
264 *q++=(unsigned char) (*p & 0xff);
268 Reset working registers.
276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 + G e t S i g n a t u r e B l o c k s i z e %
284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286 % GetSignatureBlocksize() returns the Signature blocksize.
288 % The format of the GetSignatureBlocksize method is:
290 % unsigned int *GetSignatureBlocksize(const SignatureInfo *signature_info)
292 % A description of each parameter follows:
294 % o signature_info: the signature info.
297 MagickPrivate unsigned int GetSignatureBlocksize(
298 const SignatureInfo *signature_info)
300 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
301 assert(signature_info != (SignatureInfo *) NULL);
302 assert(signature_info->signature == MagickSignature);
303 return(signature_info->blocksize);
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 + G e t S i g n a t u r e D i g e s t %
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317 % GetSignatureDigest() returns the signature digest.
319 % The format of the GetSignatureDigest method is:
321 % const StringInfo *GetSignatureDigest(const SignatureInfo *signature_info)
323 % A description of each parameter follows:
325 % o signature_info: the signature info.
328 MagickPrivate const StringInfo *GetSignatureDigest(
329 const SignatureInfo *signature_info)
331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
332 assert(signature_info != (SignatureInfo *) NULL);
333 assert(signature_info->signature == MagickSignature);
334 return(signature_info->digest);
338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 + G e t S i g n a t u r e D i g e s t s i z e %
346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348 % GetSignatureDigestsize() returns the Signature digest size.
350 % The format of the GetSignatureDigestsize method is:
352 % unsigned int *GetSignatureDigestsize(const SignatureInfo *signature_info)
354 % A description of each parameter follows:
356 % o signature_info: the signature info.
359 MagickPrivate unsigned int GetSignatureDigestsize(
360 const SignatureInfo *signature_info)
362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
363 assert(signature_info != (SignatureInfo *) NULL);
364 assert(signature_info->signature == MagickSignature);
365 return(signature_info->digestsize);
369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 + I n i t i a l i z e S i g n a t u r e %
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 % InitializeSignature() initializes the Signature accumulator.
381 % The format of the DestroySignatureInfo method is:
383 % void InitializeSignatureInfo(SignatureInfo *signature_info)
385 % A description of each parameter follows:
387 % o signature_info: the cipher signature_info.
390 MagickPrivate void InitializeSignature(SignatureInfo *signature_info)
392 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
393 assert(signature_info != (SignatureInfo *) NULL);
394 assert(signature_info->signature == MagickSignature);
395 signature_info->accumulator[0]=0x6a09e667U;
396 signature_info->accumulator[1]=0xbb67ae85U;
397 signature_info->accumulator[2]=0x3c6ef372U;
398 signature_info->accumulator[3]=0xa54ff53aU;
399 signature_info->accumulator[4]=0x510e527fU;
400 signature_info->accumulator[5]=0x9b05688cU;
401 signature_info->accumulator[6]=0x1f83d9abU;
402 signature_info->accumulator[7]=0x5be0cd19U;
403 signature_info->low_order=0;
404 signature_info->high_order=0;
405 signature_info->offset=0;
409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413 + S e t S i g n a t u r e D i g e s t %
417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 % SetSignatureDigest() set the signature digest.
421 % The format of the SetSignatureDigest method is:
423 % SetSignatureDigest(SignatureInfo *signature_info,
424 % const StringInfo *digest)
426 % A description of each parameter follows:
428 % o signature_info: the signature info.
430 % o digest: the digest.
433 MagickPrivate void SetSignatureDigest(SignatureInfo *signature_info,
434 const StringInfo *digest)
437 Set the signature accumulator.
439 assert(signature_info != (SignatureInfo *) NULL);
440 assert(signature_info->signature == MagickSignature);
441 SetStringInfo(signature_info->digest,digest);
445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 % S i g n a t u r e I m a g e %
453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
455 % SignatureImage() computes a message digest from an image pixel stream with
456 % an implementation of the NIST SHA-256 Message Digest algorithm. This
457 % signature uniquely identifies the image and is convenient for determining
458 % if an image has been modified or whether two images are identical.
460 % The format of the SignatureImage method is:
462 % MagickBooleanType SignatureImage(Image *image,ExceptionInfo *exception)
464 % A description of each parameter follows:
466 % o image: the image.
468 % o exception: return any errors or warnings in this structure.
471 MagickExport MagickBooleanType SignatureImage(Image *image,
472 ExceptionInfo *exception)
483 register const Quantum
499 Compute image digital signature.
501 assert(image != (Image *) NULL);
502 assert(image->signature == MagickSignature);
503 if (image->debug != MagickFalse)
504 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
505 signature_info=AcquireSignatureInfo();
506 signature=AcquireStringInfo(image->columns*GetPixelChannels(image)*
508 image_view=AcquireVirtualCacheView(image,exception);
509 for (y=0; y < (ssize_t) image->rows; y++)
514 register unsigned char
517 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
518 if (p == (const Quantum *) NULL)
520 SetStringInfoLength(signature,image->columns*GetPixelChannels(image)*
522 pixels=GetStringInfoDatum(signature);
524 for (x=0; x < (ssize_t) image->columns; x++)
529 if (GetPixelReadMask(image,p) == 0)
531 p+=GetPixelChannels(image);
534 for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
539 PixelChannel channel=GetPixelChannelChannel(image,i);
540 PixelTrait traits=GetPixelChannelTraits(image,channel);
541 if (traits == UndefinedPixelTrait)
543 pixel=QuantumScale*p[i];
544 for (j=0; j < (ssize_t) sizeof(pixel); j++)
545 *q++=(unsigned char) ((unsigned char *) &pixel)[j];
547 p+=GetPixelChannels(image);
549 SetStringInfoLength(signature,(size_t) (q-pixels));
550 UpdateSignature(signature_info,signature);
552 image_view=DestroyCacheView(image_view);
553 FinalizeSignature(signature_info);
554 hex_signature=StringInfoToHexString(GetSignatureDigest(signature_info));
555 (void) DeleteImageProperty(image,"signature");
556 (void) SetImageProperty(image,"signature",hex_signature,exception);
560 hex_signature=DestroyString(hex_signature);
561 signature=DestroyStringInfo(signature);
562 signature_info=DestroySignatureInfo(signature_info);
567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 + T r a n s f o r m S i g n a t u r e %
575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577 % TransformSignature() transforms the Signature message accumulator.
579 % The format of the TransformSignature method is:
581 % TransformSignature(SignatureInfo *signature_info)
583 % A description of each parameter follows:
585 % o signature_info: the address of a structure of type SignatureInfo.
589 static inline unsigned int Ch(unsigned int x,unsigned int y,unsigned int z)
591 return((x & y) ^ (~x & z));
594 static inline unsigned int Maj(unsigned int x,unsigned int y,unsigned int z)
596 return((x & y) ^ (x & z) ^ (y & z));
599 static inline unsigned int Trunc32(unsigned int x)
601 return((unsigned int) (x & 0xffffffffU));
604 static unsigned int RotateRight(unsigned int x,unsigned int n)
606 return(Trunc32((x >> n) | (x << (32-n))));
609 static void TransformSignature(SignatureInfo *signature_info)
611 #define Sigma0(x) (RotateRight(x,7) ^ RotateRight(x,18) ^ Trunc32((x) >> 3))
612 #define Sigma1(x) (RotateRight(x,17) ^ RotateRight(x,19) ^ Trunc32((x) >> 10))
613 #define Suma0(x) (RotateRight(x,2) ^ RotateRight(x,13) ^ RotateRight(x,22))
614 #define Suma1(x) (RotateRight(x,6) ^ RotateRight(x,11) ^ RotateRight(x,25))
619 register unsigned char
628 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU,
629 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U,
630 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U,
631 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
632 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U,
633 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U,
634 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU,
635 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
636 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U,
637 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U,
638 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU,
639 0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
640 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
641 }; /* 32-bit fractional part of the cube root of the first 64 primes */
659 p=GetStringInfoDatum(signature_info->message);
660 if (signature_info->lsb_first == MagickFalse)
662 DisableMSCWarning(4127)
663 if (sizeof(unsigned int) <= 4)
665 for (i=0; i < 16; i++)
667 T=(*((unsigned int *) p));
672 for (i=0; i < 16; i+=2)
674 T=(*((unsigned int *) p));
676 W[i]=Trunc32(T >> shift);
681 DisableMSCWarning(4127)
682 if (sizeof(unsigned int) <= 4)
684 for (i=0; i < 16; i++)
686 T=(*((unsigned int *) p));
688 W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
689 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
692 for (i=0; i < 16; i+=2)
694 T=(*((unsigned int *) p));
696 W[i]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
697 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
699 W[i+1]=((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
700 ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
703 Copy accumulator to registers.
705 A=signature_info->accumulator[0];
706 B=signature_info->accumulator[1];
707 C=signature_info->accumulator[2];
708 D=signature_info->accumulator[3];
709 E=signature_info->accumulator[4];
710 F=signature_info->accumulator[5];
711 G=signature_info->accumulator[6];
712 H=signature_info->accumulator[7];
713 for (i=16; i < 64; i++)
714 W[i]=Trunc32(Sigma1(W[i-2])+W[i-7]+Sigma0(W[i-15])+W[i-16]);
715 for (j=0; j < 64; j++)
717 T1=Trunc32(H+Suma1(E)+Ch(E,F,G)+K[j]+W[j]);
718 T2=Trunc32(Suma0(A)+Maj(A,B,C));
729 Add registers back to accumulator.
731 signature_info->accumulator[0]=Trunc32(signature_info->accumulator[0]+A);
732 signature_info->accumulator[1]=Trunc32(signature_info->accumulator[1]+B);
733 signature_info->accumulator[2]=Trunc32(signature_info->accumulator[2]+C);
734 signature_info->accumulator[3]=Trunc32(signature_info->accumulator[3]+D);
735 signature_info->accumulator[4]=Trunc32(signature_info->accumulator[4]+E);
736 signature_info->accumulator[5]=Trunc32(signature_info->accumulator[5]+F);
737 signature_info->accumulator[6]=Trunc32(signature_info->accumulator[6]+G);
738 signature_info->accumulator[7]=Trunc32(signature_info->accumulator[7]+H);
740 Reset working registers.
753 (void) ResetMagickMemory(W,0,sizeof(W));
757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
761 + U p d a t e S i g n a t u r e %
765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 % UpdateSignature() updates the Signature message accumulator.
769 % The format of the UpdateSignature method is:
771 % UpdateSignature(SignatureInfo *signature_info,const StringInfo *message)
773 % A description of each parameter follows:
775 % o signature_info: the address of a structure of type SignatureInfo.
777 % o message: the message.
780 MagickPrivate void UpdateSignature(SignatureInfo *signature_info,
781 const StringInfo *message)
786 register unsigned char
796 Update the Signature accumulator.
798 assert(signature_info != (SignatureInfo *) NULL);
799 assert(signature_info->signature == MagickSignature);
800 n=GetStringInfoLength(message);
801 length=Trunc32((unsigned int) (signature_info->low_order+(n << 3)));
802 if (length < signature_info->low_order)
803 signature_info->high_order++;
804 signature_info->low_order=length;
805 signature_info->high_order+=(unsigned int) (n >> 29);
806 p=GetStringInfoDatum(message);
807 if (signature_info->offset != 0)
809 i=GetStringInfoLength(signature_info->message)-signature_info->offset;
812 (void) CopyMagickMemory(GetStringInfoDatum(signature_info->message)+
813 signature_info->offset,p,i);
816 signature_info->offset+=i;
817 if (signature_info->offset !=
818 GetStringInfoLength(signature_info->message))
820 TransformSignature(signature_info);
822 while (n >= GetStringInfoLength(signature_info->message))
824 SetStringInfoDatum(signature_info->message,p);
825 p+=GetStringInfoLength(signature_info->message);
826 n-=GetStringInfoLength(signature_info->message);
827 TransformSignature(signature_info);
829 (void) CopyMagickMemory(GetStringInfoDatum(signature_info->message),p,n);
830 signature_info->offset=n;
832 Reset working registers.