--- ./lib/fsm.c.orig	2011-06-15 16:23:38.000000000 +0000
+++ ./lib/fsm.c	2011-06-15 16:39:51.000000000 +0000
@@ -808,11 +808,13 @@ int fsmMapAttrs(FSM_t fsm)
 	     */
 	    if (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOMD5)) {
 		fsm->fmd5sum = (fi->fmd5s ? fi->fmd5s[i] : NULL);
-		fsm->md5sum = (fi->md5s ? (fi->md5s + (16 * i)) : NULL);
+		fsm->md5sum = (fi->md5s ? (fi->md5s + (fi->digestlen * i)) : NULL);
 	    } else {
 		fsm->fmd5sum = NULL;
 		fsm->md5sum = NULL;
 	    }
+	    fsm->digestalgo = fi->digestalgo;
+	    fsm->digestlen = fi->digestlen;
 	}
 
     }
@@ -839,7 +841,7 @@ static int expandRegular(/*@special@*/ F
 	goto exit;
 
     if (st->st_size > 0 && (fsm->fmd5sum != NULL || fsm->md5sum != NULL))
-	fdInitDigest(fsm->wfd, PGPHASHALGO_MD5, 0);
+	fdInitDigest(fsm->wfd, fsm->digestalgo, 0);
 
     while (left) {
 
@@ -864,7 +866,7 @@ static int expandRegular(/*@special@*/ F
 	int asAscii = (fsm->md5sum == NULL ? 1 : 0);
 
 	(void) Fflush(fsm->wfd);
-	fdFiniDigest(fsm->wfd, PGPHASHALGO_MD5, &md5sum, NULL, asAscii);
+	fdFiniDigest(fsm->wfd, fsm->digestalgo, &md5sum, NULL, asAscii);
 
 	if (md5sum == NULL) {
 	    rc = CPIOERR_MD5SUM_MISMATCH;
@@ -872,7 +874,7 @@ static int expandRegular(/*@special@*/ F
 	}
 
 	if (fsm->md5sum != NULL) {
-	    if (memcmp(md5sum, fsm->md5sum, 16))
+	    if (memcmp(md5sum, fsm->md5sum, fsm->digestlen))
 		rc = CPIOERR_MD5SUM_MISMATCH;
 	} else {
 	    if (strcmp(md5sum, fsm->fmd5sum))
--- ./lib/fsm.h.orig	2011-06-15 16:37:18.000000000 +0000
+++ ./lib/fsm.h	2011-06-15 16:38:00.000000000 +0000
@@ -189,6 +189,8 @@ struct fsm_s {
     const char * fmd5sum;	/*!< Hex MD5 sum (NULL disables). */
 /*@shared@*/ /*@relnull@*/
     const char * md5sum;	/*!< Binary MD5 sum (NULL disables). */
+    int digestalgo;		/*!< digest algorithm */
+    int digestlen;		/*!< digest binary length */
 /*@dependent@*/ /*@observer@*/ /*@null@*/
     const char * fcontext;	/*!< File security context (NULL disables). */
     
--- ./lib/rpmfi.c.orig	2011-06-15 16:23:22.000000000 +0000
+++ ./lib/rpmfi.c	2011-06-15 17:16:18.000000000 +0000
@@ -211,12 +211,22 @@ const unsigned char * rpmfiMD5(rpmfi fi)
     if (fi != NULL && fi->i >= 0 && fi->i < fi->fc) {
 /*@-boundsread@*/
 	if (fi->md5s != NULL)
-	    MD5 = fi->md5s + (16 * fi->i);
+	    MD5 = fi->md5s + (fi->digestlen * fi->i);
 /*@=boundsread@*/
     }
     return MD5;
 }
 
+int rpmfiDigestAlgo(rpmfi fi)
+{
+   return fi ? fi->digestalgo : 0;
+}
+
+int rpmfiDigestLen(rpmfi fi)
+{
+   return fi ? fi->digestlen : 0;
+}
+
 const char * rpmfiFLink(rpmfi fi)
 {
     const char * flink = NULL;
@@ -536,7 +546,9 @@ int rpmfiCompare(const rpmfi afi, const
 	if (amd5 == bmd5) return 0;
 	if (amd5 == NULL) return 1;
 	if (bmd5 == NULL) return -1;
-	return memcmp(amd5, bmd5, 16);
+	/* can't meaningfully compare different hash types */
+	if (afi->digestalgo != bfi->digestalgo) return -1;
+	return memcmp(amd5, bmd5, afi->digestlen);
     }
 
     return 0;
@@ -596,20 +608,20 @@ fileAction rpmfiDecideFate(const rpmfi o
 	const unsigned char * omd5, * nmd5;
 	omd5 = rpmfiMD5(ofi);
 	if (diskWhat == REG) {
-	    if (domd5(fn, (unsigned char *)buffer, 0, NULL))
+	    if (domd5_algo(fn, (unsigned char *)buffer, 0, NULL, ofi->digestalgo))
 		return FA_CREATE;       /* assume file has been removed */
-	    if (omd5 && !memcmp(omd5, buffer, 16))
+	    if (omd5 && !memcmp(omd5, buffer, ofi->digestlen))
 		return FA_CREATE;       /* unmodified config file, replace. */
 	}
 
-	if (domd5(fn, buffer, 0, NULL))
+	if (domd5_algo(fn, buffer, 0, NULL, ofi->digestalgo))
 	    return FA_CREATE;	/* assume file has been removed */
 	omd5 = rpmfiMD5(ofi);
-	if (omd5 && !memcmp(omd5, buffer, 16))
+	if (omd5 && !memcmp(omd5, buffer, ofi->digestlen))
 	    return FA_CREATE;	/* unmodified config file, replace. */
 	nmd5 = rpmfiMD5(nfi);
 /*@-nullpass@*/
-	if (omd5 && nmd5 && !memcmp(omd5, nmd5, 16))
+	if (omd5 && nmd5 && ofi->digestalgo == nfi->digestalgo && !memcmp(omd5, nmd5, nfi->digestlen))
 	    return FA_SKIP;	/* identical file, don't bother. */
 /*@=nullpass@*/
     } else /* dbWhat == LINK */ {
@@ -663,10 +675,10 @@ int rpmfiConfigConflict(const rpmfi fi)
     memset(buffer, 0, sizeof(buffer));
     if (newWhat == REG) {
 	const unsigned char * nmd5;
-	if (domd5(fn, (unsigned char *)buffer, 0, NULL))
+	if (domd5_algo(fn, (unsigned char *)buffer, 0, NULL, fi->digestalgo))
 	    return 0;	/* assume file has been removed */
 	nmd5 = rpmfiMD5(fi);
-	if (nmd5 && !memcmp(nmd5, buffer, 16))
+	if (nmd5 && !memcmp(nmd5, buffer, fi->digestlen))
 	    return 0;	/* unmodified config file */
     } else /* newWhat == LINK */ {
 	const char * nFLink;
@@ -1268,7 +1280,7 @@ rpmfi rpmfiNew(const rpmts ts, Header h,
     rpmte p;
     rpmfi fi = NULL;
     const char * Type;
-    uint_32 * uip;
+    uint_32 * uip, * digestalgop;
     int dnlmax, bnlmax;
     unsigned char * t;
     int len;
@@ -1361,9 +1373,23 @@ if (fi->actions == NULL)
     fi->fmd5s = NULL;
     xx = hge(h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
 
+    fi->digestalgo = PGPHASHALGO_MD5;
+    fi->digestlen = 16;
+    if (hge(h, RPMTAG_FILEDIGESTALGO, NULL, &digestalgop, NULL)) {
+	fi->digestalgo = *digestalgop;
+	if (fi->digestalgo == PGPHASHALGO_SHA1)
+	    fi->digestlen = 20;
+	else if (fi->digestalgo == PGPHASHALGO_SHA256)
+	    fi->digestlen = 32;
+	else if (fi->digestalgo == PGPHASHALGO_SHA512)
+	    fi->digestlen = 64;
+	else
+	    fi->digestalgo = PGPHASHALGO_MD5;
+    }
+
     fi->md5s = NULL;
     if (fi->fmd5s) {
-	t = xmalloc(fi->fc * 16);
+	t = xmalloc(fi->fc * fi->digestlen);
 	fi->md5s = t;
 	for (i = 0; i < fi->fc; i++) {
 	    const char * fmd5;
@@ -1371,11 +1397,11 @@ if (fi->actions == NULL)
 
 	    fmd5 = fi->fmd5s[i];
 	    if (!(fmd5 && *fmd5 != '\0')) {
-		memset(t, 0, 16);
-		t += 16;
+		memset(t, 0, fi->digestlen);
+		t += fi->digestlen;
 		continue;
 	    }
-	    for (j = 0; j < 16; j++, t++, fmd5 += 2)
+	    for (j = 0; j < fi->digestlen; j++, t++, fmd5 += 2)
 		*t = (nibble(fmd5[0]) << 4) | nibble(fmd5[1]);
 	}
 	fi->fmd5s = hfd(fi->fmd5s, -1);
--- ./lib/rpmfi.h.orig	2011-06-15 16:23:26.000000000 +0000
+++ ./lib/rpmfi.h	2011-06-15 17:13:52.000000000 +0000
@@ -125,6 +125,8 @@ struct rpmfi_s {
 /*@unused@*/
     int_32 * odil;		/*!< Original dirindex(s) (from header) */
 
+    int digestalgo;		/*!< File digest algorithm */
+    int digestlen;		/*!< File digest binary length */
 /*@only@*/ /*@relnull@*/
     unsigned char * md5s;	/*!< File md5 sums in binary. */
 
@@ -343,6 +345,9 @@ rpmfileState rpmfiFState(/*@null@*/ rpmf
 extern const unsigned char * rpmfiMD5(/*@null@*/ rpmfi fi)
 	/*@*/;
 
+extern int rpmfiDigestAlgo(rpmfi fi);
+extern int rpmfiDigestLen(rpmfi fi);
+
 /**
  * Return current file linkto (i.e. symlink(2) target) from file info set.
  * @param fi		file info set
--- ./lib/rpmlib.h.orig	2011-06-15 16:55:35.000000000 +0000
+++ ./lib/rpmlib.h	2011-06-15 16:57:13.000000000 +0000
@@ -460,6 +460,8 @@ typedef enum rpmTag_e {
     RPMTAG_SCRIPTSTATES		= 1174, /*!< i scriptlet exit codes */
     RPMTAG_SCRIPTMETRICS	= 1175, /*!< i scriptlet execution times */
     RPMTAG_BUILDCPUCLOCK	= 1176, /*!< i */
+    /* tags 1997-4999 reserved */
+    RPMTAG_FILEDIGESTALGO       = 5011, /* i file digest algorithm */
 
 /*@-enummemuse@*/
     RPMTAG_FIRSTFREE_TAG	/*!< internal */
--- ./lib/transaction.c.orig	2011-06-15 16:50:14.000000000 +0000
+++ ./lib/transaction.c	2011-06-15 17:11:17.000000000 +0000
@@ -650,9 +650,9 @@ assert(otherFi != NULL);
 	    }
 		
 	    /* Here is a pre-existing modified config file that needs saving. */
-	    {	char md5sum[50];
+	    {	char md5sum[64];
 		const unsigned char * MD5 = rpmfiMD5(fi);
-		if (!domd5(fn, md5sum, 0, NULL) && memcmp(MD5, md5sum, 16)) {
+		if (!domd5_algo(fn, md5sum, 0, NULL, fi->digestalgo) && memcmp(MD5, md5sum, fi->digestlen)) {
 		    fi->actions[i] = FA_BACKUP;
 		    /*@switchbreak@*/ break;
 		}
--- ./lib/verify.c.orig	2011-06-15 16:47:27.000000000 +0000
+++ ./lib/verify.c	2011-06-15 17:16:56.000000000 +0000
@@ -118,17 +118,17 @@ int rpmVerifyFile(const rpmts ts, const
 /*@=branchstate@*/
 
     if (flags & RPMVERIFY_MD5) {
-	unsigned char md5sum[16];
+	unsigned char md5sum[64];
 	size_t fsize;
 
 	/* XXX If --nomd5, then prelinked library sizes are not corrected. */
-	rc = domd5(fn, md5sum, 0, &fsize);
+	rc = domd5_algo(fn, md5sum, 0, &fsize, rpmfiDigestAlgo(fi));
 	sb.st_size = fsize;
 	if (rc)
 	    *res |= (RPMVERIFY_READFAIL|RPMVERIFY_MD5);
 	else {
 	    const unsigned char * MD5 = rpmfiMD5(fi);
-	    if (MD5 == NULL || memcmp(md5sum, MD5, sizeof(md5sum)))
+	    if (MD5 == NULL || memcmp(md5sum, MD5, rpmfiDigestLen(fi)))
 		*res |= RPMVERIFY_MD5;
 	}
     } 
--- ./rpmdb/legacy.c.orig	2011-06-15 16:41:13.000000000 +0000
+++ ./rpmdb/legacy.c	2011-06-15 16:43:54.000000000 +0000
@@ -145,7 +145,7 @@ exit:
     return fdno;
 }
 
-int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
+int domd5_algo(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep, int algo)
 {
     const char * path;
     urltype ut = urlPath(fn, &path);
@@ -193,7 +193,7 @@ int domd5(const char * fn, unsigned char
 #endif
 	}
 
-	ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
+	ctx = rpmDigestInit(algo, RPMDIGEST_NONE);
 	if (fsize)
 	    xx = rpmDigestUpdate(ctx, mapped, fsize);
 	xx = rpmDigestFinal(ctx, (void **)&md5sum, &md5len, asAscii);
@@ -219,11 +219,11 @@ int domd5(const char * fn, unsigned char
 	    break;
 	}
 	
-	fdInitDigest(fd, PGPHASHALGO_MD5, 0);
+	fdInitDigest(fd, algo, 0);
 	fsize = 0;
 	while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
 	    fsize += rc;
-	fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
+	fdFiniDigest(fd, algo, (void **)&md5sum, &md5len, asAscii);
 	if (Ferror(fd))
 	    rc = 1;
 
@@ -251,6 +251,11 @@ exit:
     return rc;
 }
 
+int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
+{
+  return domd5_algo(fn, digest, asAscii, fsizep, PGPHASHALGO_MD5);
+}
+
 /*@-exportheadervar@*/
 /*@unchecked@*/
 int _noDirTokens = 0;
--- ./rpmdb/legacy.h.orig	2011-06-15 16:41:16.000000000 +0000
+++ ./rpmdb/legacy.h	2011-06-15 17:10:37.000000000 +0000
@@ -29,6 +29,8 @@ int domd5(const char * fn, /*@out@*/ uns
 		/*@null@*/ /*@out@*/ size_t *fsizep)
 	/*@globals h_errno, fileSystem, internalState @*/
 	/*@modifies digest, *fsizep, fileSystem, internalState @*/;
+int domd5_algo(const char * fn, /*@out@*/ unsigned char * digest, int asAscii,
+		/*@null@*/ /*@out@*/ size_t *fsizep, int algo);
 
 /**
  * Convert absolute path tag to (dirname,basename,dirindex) tags.
