X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgchecksum.c;h=9107e78b5e178861bddc00317d1b5ae0ef878220;hb=35eaf037bdfca985abf5d349e7355f1d2ed9c77b;hp=bfd9d5cfb20229903c7f6f131242785753041b4a;hpb=ca25b31ee39611ec0561a4d7efabe2afbc0697a8;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gchecksum.c b/glib/gchecksum.c index bfd9d5c..9107e78 100644 --- a/glib/gchecksum.c +++ b/glib/gchecksum.c @@ -13,24 +13,48 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . */ -#include +#include "config.h" #include -#include "glibconfig.h" #include "gchecksum.h" -#include "glib.h" + +#include "gslice.h" +#include "gmem.h" +#include "gstrfuncs.h" +#include "gtestutils.h" +#include "gtypes.h" #include "glibintl.h" -#include "galias.h" -#define IS_VALID_TYPE(type) ((type) >= G_CHECKSUM_MD5 && (type) <= G_CHECKSUM_SHA256) +/** + * SECTION:checksum + * @title: Data Checksums + * @short_description: computes the checksum for data + * + * GLib provides a generic API for computing checksums (or "digests") + * for a sequence of arbitrary bytes, using various hashing algorithms + * like MD5, SHA-1 and SHA-256. Checksums are commonly used in various + * environments and specifications. + * + * GLib supports incremental checksums using the GChecksum data + * structure, by calling g_checksum_update() as long as there's data + * available and then using g_checksum_get_string() or + * g_checksum_get_digest() to compute the checksum and return it either + * as a string in hexadecimal form, or as a raw sequence of bytes. To + * compute the checksum for binary blobs and NUL-terminated strings in + * one go, use the convenience functions g_compute_checksum_for_data() + * and g_compute_checksum_for_string(), respectively. + * + * Support for checksums has been added in GLib 2.16 + **/ + +#define IS_VALID_TYPE(type) ((type) >= G_CHECKSUM_MD5 && (type) <= G_CHECKSUM_SHA512) +/* The fact that these are lower case characters is part of the ABI */ static const gchar hex_digits[] = "0123456789abcdef"; #define MD5_DATASIZE 64 @@ -40,8 +64,11 @@ typedef struct { guint32 buf[4]; guint32 bits[2]; - - guchar data[MD5_DATASIZE]; + + union { + guchar data[MD5_DATASIZE]; + guint32 data32[MD5_DATASIZE / 4]; + } u; guchar digest[MD5_DIGEST_LEN]; } Md5sum; @@ -73,6 +100,21 @@ typedef struct guchar digest[SHA256_DIGEST_LEN]; } Sha256sum; +#define SHA512_BLOCK_LEN 128 /* 1024 bits message block */ +#define SHA512_DIGEST_LEN 64 + +typedef struct +{ + guint64 H[8]; + + guint8 block[SHA512_BLOCK_LEN]; + guint8 block_len; + + guint64 data_len[2]; + + guchar digest[SHA512_DIGEST_LEN]; +} Sha512sum; + struct _GChecksum { GChecksumType type; @@ -83,6 +125,7 @@ struct _GChecksum Md5sum md5; Sha1sum sha1; Sha256sum sha256; + Sha512sum sha512; } sum; }; @@ -122,10 +165,7 @@ sha_byte_reverse (guint32 *buffer, length /= sizeof (guint32); while (length--) { - *buffer = ((guint32) (((*buffer & (guint32) 0x000000ffU) << 24) | - ((*buffer & (guint32) 0x0000ff00U) << 8) | - ((*buffer & (guint32) 0x00ff0000U) >> 8) | - ((*buffer & (guint32) 0xff000000U) >> 24))); + *buffer = GUINT32_SWAP_LE_BE (*buffer); ++buffer; } } @@ -189,11 +229,11 @@ md5_sum_init (Md5sum *md5) * reflect the addition of 16 longwords of new data. md5_sum_update() * blocks the data and converts bytes into longwords for this routine. */ -static void -md5_transform (guint32 buf[4], - guint32 const in[16]) +static void +md5_transform (guint32 buf[4], + guint32 const in[16]) { - register guint32 a, b, c, d; + guint32 a, b, c, d; /* The four core functions - F1 is optimized somewhat */ #define F1(x, y, z) (z ^ (x & (y ^ z))) @@ -203,7 +243,7 @@ md5_transform (guint32 buf[4], /* This is the central step in the MD5 algorithm. */ #define md5_step(f, w, x, y, z, data, s) \ - ( w += f (x, y, z) + data, w = w << s | w >> (32 - s), w += x ) + ( w += f (x, y, z) + data, w = w << s | w >> (32 - s), w += x ) a = buf[0]; b = buf[1]; @@ -226,7 +266,7 @@ md5_transform (guint32 buf[4], md5_step (F1, d, a, b, c, in[13] + 0xfd987193, 12); md5_step (F1, c, d, a, b, in[14] + 0xa679438e, 17); md5_step (F1, b, c, d, a, in[15] + 0x49b40821, 22); - + md5_step (F2, a, b, c, d, in[1] + 0xf61e2562, 5); md5_step (F2, d, a, b, c, in[6] + 0xc040b340, 9); md5_step (F2, c, d, a, b, in[11] + 0x265e5a51, 14); @@ -306,13 +346,13 @@ md5_sum_update (Md5sum *md5, md5->bits[1] += length >> 29; - /* bytes already in Md5sum->data */ + /* bytes already in Md5sum->u.data */ bit = (bit >> 3) & 0x3f; /* handle any leading odd-sized chunks */ if (bit) { - guchar *p = (guchar *) md5->data + bit; + guchar *p = md5->u.data + bit; bit = MD5_DATASIZE - bit; if (length < bit) @@ -322,9 +362,9 @@ md5_sum_update (Md5sum *md5, } memcpy (p, data, bit); - - md5_byte_reverse (md5->data, 16); - md5_transform (md5->buf, (guint32 *) md5->data); + + md5_byte_reverse (md5->u.data, 16); + md5_transform (md5->buf, md5->u.data32); data += bit; length -= bit; @@ -333,17 +373,17 @@ md5_sum_update (Md5sum *md5, /* process data in 64-byte chunks */ while (length >= MD5_DATASIZE) { - memcpy (md5->data, data, MD5_DATASIZE); - - md5_byte_reverse (md5->data, 16); - md5_transform (md5->buf, (guint32 *) md5->data); + memcpy (md5->u.data, data, MD5_DATASIZE); + + md5_byte_reverse (md5->u.data, 16); + md5_transform (md5->buf, md5->u.data32); data += MD5_DATASIZE; length -= MD5_DATASIZE; } /* handle any remaining bytes of data */ - memcpy (md5->data, data, length); + memcpy (md5->u.data, data, length); } /* closes a checksum */ @@ -359,7 +399,7 @@ md5_sum_close (Md5sum *md5) /* Set the first char of padding to 0x80. * This is safe since there is always at least one byte free */ - p = md5->data + count; + p = md5->u.data + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ @@ -370,12 +410,12 @@ md5_sum_close (Md5sum *md5) { /* Two lots of padding: Pad the first block to 64 bytes */ memset (p, 0, count); - - md5_byte_reverse (md5->data, 16); - md5_transform (md5->buf, (guint32 *) md5->data); + + md5_byte_reverse (md5->u.data, 16); + md5_transform (md5->buf, md5->u.data32); /* Now fill the next block with 56 bytes */ - memset (md5->data, 0, MD5_DATASIZE - 8); + memset (md5->u.data, 0, MD5_DATASIZE - 8); } else { @@ -383,20 +423,20 @@ md5_sum_close (Md5sum *md5) memset (p, 0, count - 8); } - md5_byte_reverse (md5->data, 14); + md5_byte_reverse (md5->u.data, 14); /* Append length in bits and transform */ - ((guint32 *) md5->data)[14] = md5->bits[0]; - ((guint32 *) md5->data)[15] = md5->bits[1]; + md5->u.data32[14] = md5->bits[0]; + md5->u.data32[15] = md5->bits[1]; - md5_transform (md5->buf, (guint32 *) md5->data); + md5_transform (md5->buf, md5->u.data32); md5_byte_reverse ((guchar *) md5->buf, 4); - + memcpy (md5->digest, md5->buf, 16); /* Reset buffers in case they contain sensitive data */ memset (md5->buf, 0, sizeof (md5->buf)); - memset (md5->data, 0, sizeof (md5->data)); + memset (md5->u.data, 0, sizeof (md5->u.data)); } static gchar * @@ -541,7 +581,7 @@ sha1_transform (guint32 buf[5], D = buf[3]; E = buf[4]; - /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ + /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ subRound (A, B, C, D, E, f1, K1, in[0]); subRound (E, A, B, C, D, f1, K1, in[1]); subRound (D, E, A, B, C, f1, K1, in[2]); @@ -583,7 +623,7 @@ sha1_transform (guint32 buf[5], subRound (D, E, A, B, C, f2, K2, expand (in, 37)); subRound (C, D, E, A, B, f2, K2, expand (in, 38)); subRound (B, C, D, E, A, f2, K2, expand (in, 39)); - + subRound (A, B, C, D, E, f3, K3, expand (in, 40)); subRound (E, A, B, C, D, f3, K3, expand (in, 41)); subRound (D, E, A, B, C, f3, K3, expand (in, 42)); @@ -674,7 +714,7 @@ sha1_sum_update (Sha1sum *sha1, memcpy (p, buffer, count); return; } - + memcpy (p, buffer, dataCount); sha_byte_reverse (sha1->data, SHA1_DATASIZE); @@ -688,7 +728,7 @@ sha1_sum_update (Sha1sum *sha1, while (count >= SHA1_DATASIZE) { memcpy (sha1->data, buffer, SHA1_DATASIZE); - + sha_byte_reverse (sha1->data, SHA1_DATASIZE); sha1_transform (sha1->buf, sha1->data); @@ -1043,6 +1083,284 @@ sha256_sum_digest (Sha256sum *sha256, digest[i] = sha256->digest[i]; } +/* + * SHA-512 Checksum + * + * Implemented following FIPS-180-2 standard at + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf. + * References in the form [§x.y.z] map to sections in that document. + * + * Author: Eduardo Lima Mitev + */ + +/* SHA-384 and SHA-512 functions [§4.1.3] */ +#define Ch(x,y,z) ((x & y) ^ (~x & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define SHR(n,x) (x >> n) +#define ROTR(n,x) (SHR (n, x) | (x << (64 - n))) +#define SIGMA0(x) (ROTR (28, x) ^ ROTR (34, x) ^ ROTR (39, x)) +#define SIGMA1(x) (ROTR (14, x) ^ ROTR (18, x) ^ ROTR (41, x)) +#define sigma0(x) (ROTR ( 1, x) ^ ROTR ( 8, x) ^ SHR ( 7, x)) +#define sigma1(x) (ROTR (19, x) ^ ROTR (61, x) ^ SHR ( 6, x)) + +#define PUT_UINT64(n,b,i) G_STMT_START{ \ + (b)[(i) ] = (guint8) (n >> 56); \ + (b)[(i) + 1] = (guint8) (n >> 48); \ + (b)[(i) + 2] = (guint8) (n >> 40); \ + (b)[(i) + 3] = (guint8) (n >> 32); \ + (b)[(i) + 4] = (guint8) (n >> 24); \ + (b)[(i) + 5] = (guint8) (n >> 16); \ + (b)[(i) + 6] = (guint8) (n >> 8); \ + (b)[(i) + 7] = (guint8) (n ); } G_STMT_END + +static void +sha512_sum_init (Sha512sum *sha512) +{ + /* Initial Hash Value [§5.3.4] */ + sha512->H[0] = 0x6a09e667f3bcc908; + sha512->H[1] = 0xbb67ae8584caa73b; + sha512->H[2] = 0x3c6ef372fe94f82b; + sha512->H[3] = 0xa54ff53a5f1d36f1; + sha512->H[4] = 0x510e527fade682d1; + sha512->H[5] = 0x9b05688c2b3e6c1f; + sha512->H[6] = 0x1f83d9abfb41bd6b; + sha512->H[7] = 0x5be0cd19137e2179; + + sha512->block_len = 0; + + sha512->data_len[0] = 0; + sha512->data_len[1] = 0; +} + +/* SHA-384 and SHA-512 constants [§4.2.3] */ +static const guint64 SHA512_K[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, + 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, + 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, + 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, + 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, + 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, + 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, + 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, + 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +}; + +static void +sha512_transform (guint64 H[8], + guint8 const data[SHA512_BLOCK_LEN]) +{ + gint i; + gint t; + guint64 a, b, c, d, e, f, g, h; + guint64 M[16]; + guint64 W[80]; + + /* SHA-512 hash computation [§6.3.2] */ + + /* prepare the message schedule */ + for (i = 0; i < 16; i++) + { + gint p = i * 8; + + M[i] = + ((guint64) data[p + 0] << 56) | + ((guint64) data[p + 1] << 48) | + ((guint64) data[p + 2] << 40) | + ((guint64) data[p + 3] << 32) | + ((guint64) data[p + 4] << 24) | + ((guint64) data[p + 5] << 16) | + ((guint64) data[p + 6] << 8) | + ((guint64) data[p + 7] ); + } + + for (t = 0; t < 80; t++) + if (t < 16) + W[t] = M[t]; + else + W[t] = sigma1 (W[t - 2]) + W[t - 7] + sigma0 (W[t - 15]) + W[t - 16]; + + /* initialize the eight working variables */ + a = H[0]; + b = H[1]; + c = H[2]; + d = H[3]; + e = H[4]; + f = H[5]; + g = H[6]; + h = H[7]; + + for (t = 0; t < 80; t++) + { + guint64 T1, T2; + + T1 = h + SIGMA1 (e) + Ch (e, f, g) + SHA512_K[t] + W[t]; + T2 = SIGMA0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* Compute the intermediate hash value H */ + H[0] += a; + H[1] += b; + H[2] += c; + H[3] += d; + H[4] += e; + H[5] += f; + H[6] += g; + H[7] += h; +} + +static void +sha512_sum_update (Sha512sum *sha512, + const guchar *buffer, + gsize length) +{ + gsize block_left, offset = 0; + + if (length == 0) + return; + + sha512->data_len[0] += length * 8; + if (sha512->data_len[0] < length) + sha512->data_len[1]++; + + /* try to fill current block */ + block_left = SHA512_BLOCK_LEN - sha512->block_len; + if (block_left > 0) + { + gsize fill_len; + + fill_len = MIN (block_left, length); + memcpy (sha512->block + sha512->block_len, buffer, fill_len); + sha512->block_len += fill_len; + length -= fill_len; + offset += fill_len; + + if (sha512->block_len == SHA512_BLOCK_LEN) + { + sha512_transform (sha512->H, sha512->block); + sha512->block_len = 0; + } + } + + /* process complete blocks */ + while (length >= SHA512_BLOCK_LEN) + { + memcpy (sha512->block, buffer + offset, SHA512_BLOCK_LEN); + + sha512_transform (sha512->H, sha512->block); + + length -= SHA512_BLOCK_LEN; + offset += SHA512_BLOCK_LEN; + } + + /* keep remaining data for next block */ + if (length > 0) + { + memcpy (sha512->block, buffer + offset, length); + sha512->block_len = length; + } +} + +static void +sha512_sum_close (Sha512sum *sha512) +{ + guint l; + gint zeros; + guint8 pad[SHA512_BLOCK_LEN * 2] = { 0, }; + guint pad_len = 0; + gint i; + + /* apply padding [§5.1.2] */ + l = sha512->block_len * 8; + zeros = 896 - (l + 1); + + if (zeros < 0) + zeros += 128 * 8; + + pad[0] = 0x80; /* 1000 0000 */ + zeros -= 7; + pad_len++; + + memset (pad + pad_len, 0x00, zeros / 8); + pad_len += zeros / 8; + zeros = zeros % 8; + + /* put message bit length at the end of padding */ + PUT_UINT64 (sha512->data_len[1], pad, pad_len); + pad_len += 8; + + PUT_UINT64 (sha512->data_len[0], pad, pad_len); + pad_len += 8; + + /* update checksum with the padded block */ + sha512_sum_update (sha512, pad, pad_len); + + /* copy resulting 64-bit words into digest */ + for (i = 0; i < 8; i++) + PUT_UINT64 (sha512->H[i], sha512->digest, i * 8); +} + +static gchar * +sha512_sum_to_string (Sha512sum *sha512) +{ + return digest_to_string (sha512->digest, SHA512_DIGEST_LEN); +} + +static void +sha512_sum_digest (Sha512sum *sha512, + guint8 *digest) +{ + memcpy (digest, sha512->digest, SHA512_DIGEST_LEN); +} + +#undef Ch +#undef Maj +#undef SHR +#undef ROTR +#undef SIGMA0 +#undef SIGMA1 +#undef sigma0 +#undef sigma1 + +#undef PUT_UINT64 /* * Public API @@ -1054,9 +1372,9 @@ sha256_sum_digest (Sha256sum *sha256, * * Gets the length in bytes of digests of type @checksum_type * - * Return value: the checksum length, or -1 if @checksum_type is + * Returns: the checksum length, or -1 if @checksum_type is * not supported. - * + * * Since: 2.16 */ gssize @@ -1075,6 +1393,9 @@ g_checksum_type_get_length (GChecksumType checksum_type) case G_CHECKSUM_SHA256: len = SHA256_DIGEST_LEN; break; + case G_CHECKSUM_SHA512: + len = SHA512_DIGEST_LEN; + break; default: len = -1; break; @@ -1087,7 +1408,7 @@ g_checksum_type_get_length (GChecksumType checksum_type) * g_checksum_new: * @checksum_type: the desired type of checksum * - * Creates a new #GChecksum, using the checksum algorithm @checksum_type. + * Creates a new #GChecksum, using the checksum algorithm @checksum_type. * If the @checksum_type is not known, %NULL is returned. * A #GChecksum can be used to compute the checksum, or digest, of an * arbitrary binary blob, using different hashing algorithms. @@ -1101,7 +1422,7 @@ g_checksum_type_get_length (GChecksumType checksum_type) * will be closed and it won't be possible to call g_checksum_update() * on it anymore. * - * Return value: the newly created #GChecksum, or %NULL. + * Returns: (transfer full): the newly created #GChecksum, or %NULL. * Use g_checksum_free() to free the memory allocated by it. * * Since: 2.16 @@ -1117,7 +1438,28 @@ g_checksum_new (GChecksumType checksum_type) checksum = g_slice_new0 (GChecksum); checksum->type = checksum_type; - switch (checksum_type) + g_checksum_reset (checksum); + + return checksum; +} + +/** + * g_checksum_reset: + * @checksum: the #GChecksum to reset + * + * Resets the state of the @checksum back to its initial state. + * + * Since: 2.18 + **/ +void +g_checksum_reset (GChecksum *checksum) +{ + g_return_if_fail (checksum != NULL); + + g_free (checksum->digest_str); + checksum->digest_str = NULL; + + switch (checksum->type) { case G_CHECKSUM_MD5: md5_sum_init (&(checksum->sum.md5)); @@ -1128,12 +1470,13 @@ g_checksum_new (GChecksumType checksum_type) case G_CHECKSUM_SHA256: sha256_sum_init (&(checksum->sum.sha256)); break; + case G_CHECKSUM_SHA512: + sha512_sum_init (&(checksum->sum.sha512)); + break; default: g_assert_not_reached (); break; } - - return checksum; } /** @@ -1144,7 +1487,7 @@ g_checksum_new (GChecksumType checksum_type) * g_checksum_get_string() or g_checksum_get_digest(), the copied * checksum will be closed as well. * - * Return value: the copy of the passed #GChecksum. Use g_checksum_free() + * Returns: the copy of the passed #GChecksum. Use g_checksum_free() * when finished using it. * * Since: 2.16 @@ -1186,7 +1529,7 @@ g_checksum_free (GChecksum *checksum) /** * g_checksum_update: * @checksum: a #GChecksum - * @data: buffer used to compute the checksum + * @data: (array length=length) (element-type guint8): buffer used to compute the checksum * @length: size of the buffer, or -1 if it is a null-terminated string. * * Feeds @data into an existing #GChecksum. The checksum must still be @@ -1198,17 +1541,17 @@ g_checksum_free (GChecksum *checksum) void g_checksum_update (GChecksum *checksum, const guchar *data, - gsize length) + gssize length) { g_return_if_fail (checksum != NULL); - g_return_if_fail (data != NULL); + g_return_if_fail (length == 0 || data != NULL); if (length < 0) - length = strlen (data); + length = strlen ((const gchar *) data); if (checksum->digest_str) { - g_warning ("The checksum `%s' has been closed and cannot be updated " + g_warning ("The checksum '%s' has been closed and cannot be updated " "anymore.", checksum->digest_str); return; @@ -1225,6 +1568,9 @@ g_checksum_update (GChecksum *checksum, case G_CHECKSUM_SHA256: sha256_sum_update (&(checksum->sum.sha256), data, length); break; + case G_CHECKSUM_SHA512: + sha512_sum_update (&(checksum->sum.sha512), data, length); + break; default: g_assert_not_reached (); break; @@ -1240,19 +1586,21 @@ g_checksum_update (GChecksum *checksum, * Once this function has been called the #GChecksum can no longer be * updated with g_checksum_update(). * - * Return value: the hexadecimal representation of the checksum. The + * The hexadecimal characters will be lower case. + * + * Returns: the hexadecimal representation of the checksum. The * returned string is owned by the checksum and should not be modified * or freed. - * + * * Since: 2.16 */ -G_CONST_RETURN gchar * +const gchar * g_checksum_get_string (GChecksum *checksum) { gchar *str = NULL; g_return_val_if_fail (checksum != NULL, NULL); - + if (checksum->digest_str) return checksum->digest_str; @@ -1270,6 +1618,10 @@ g_checksum_get_string (GChecksum *checksum) sha256_sum_close (&(checksum->sum.sha256)); str = sha256_sum_to_string (&(checksum->sum.sha256)); break; + case G_CHECKSUM_SHA512: + sha512_sum_close (&(checksum->sum.sha512)); + str = sha512_sum_to_string (&(checksum->sum.sha512)); + break; default: g_assert_not_reached (); break; @@ -1281,7 +1633,7 @@ g_checksum_get_string (GChecksum *checksum) } /** - * g_checksum_get_digest: + * g_checksum_get_digest: (skip) * @checksum: a #GChecksum * @buffer: output buffer * @digest_len: an inout parameter. The caller initializes it to the size of @buffer. @@ -1337,6 +1689,14 @@ g_checksum_get_digest (GChecksum *checksum, } sha256_sum_digest (&(checksum->sum.sha256), buffer); break; + case G_CHECKSUM_SHA512: + if (checksum_open) + { + sha512_sum_close (&(checksum->sum.sha512)); + str = sha512_sum_to_string (&(checksum->sum.sha512)); + } + sha512_sum_digest (&(checksum->sum.sha512), buffer); + break; default: g_assert_not_reached (); break; @@ -1351,14 +1711,16 @@ g_checksum_get_digest (GChecksum *checksum, /** * g_compute_checksum_for_data: * @checksum_type: a #GChecksumType - * @data: binary blob to compute the digest of + * @data: (array length=length) (element-type guint8): binary blob to compute the digest of * @length: length of @data * * Computes the checksum for a binary @data of @length. This is a * convenience wrapper for g_checksum_new(), g_checksum_get_string() * and g_checksum_free(). * - * Return value: the digest of the binary data as a string in hexadecimal. + * The hexadecimal string returned will be in lower case. + * + * Returns: the digest of the binary data as a string in hexadecimal. * The returned string should be freed with g_free() when done using it. * * Since: 2.16 @@ -1372,8 +1734,7 @@ g_compute_checksum_for_data (GChecksumType checksum_type, gchar *retval; g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL); - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (length > 1, NULL); + g_return_val_if_fail (length == 0 || data != NULL, NULL); checksum = g_checksum_new (checksum_type); if (!checksum) @@ -1394,7 +1755,9 @@ g_compute_checksum_for_data (GChecksumType checksum_type, * * Computes the checksum of a string. * - * Return value: the checksum as a hexadecimal string. The returned string + * The hexadecimal string returned will be in lower case. + * + * Returns: the checksum as a hexadecimal string. The returned string * should be freed with g_free() when done using it. * * Since: 2.16 @@ -1402,10 +1765,10 @@ g_compute_checksum_for_data (GChecksumType checksum_type, gchar * g_compute_checksum_for_string (GChecksumType checksum_type, const gchar *str, - gsize length) + gssize length) { g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL); - g_return_val_if_fail (str != NULL, NULL); + g_return_val_if_fail (length == 0 || str != NULL, NULL); if (length < 0) length = strlen (str); @@ -1413,5 +1776,32 @@ g_compute_checksum_for_string (GChecksumType checksum_type, return g_compute_checksum_for_data (checksum_type, (const guchar *) str, length); } -#define __G_CHECKSUM_C__ -#include "galiasdef.c" +/** + * g_compute_checksum_for_bytes: + * @checksum_type: a #GChecksumType + * @data: binary blob to compute the digest of + * + * Computes the checksum for a binary @data. This is a + * convenience wrapper for g_checksum_new(), g_checksum_get_string() + * and g_checksum_free(). + * + * The hexadecimal string returned will be in lower case. + * + * Returns: the digest of the binary data as a string in hexadecimal. + * The returned string should be freed with g_free() when done using it. + * + * Since: 2.34 + */ +gchar * +g_compute_checksum_for_bytes (GChecksumType checksum_type, + GBytes *data) +{ + gconstpointer byte_data; + gsize length; + + g_return_val_if_fail (IS_VALID_TYPE (checksum_type), NULL); + g_return_val_if_fail (data != NULL, NULL); + + byte_data = g_bytes_get_data (data, &length); + return g_compute_checksum_for_data (checksum_type, byte_data, length); +}