Imported Upstream version 0.2.4
[debian/pino.git] / src / vapi / sha1.c
1 /*
2  * HMAC-SHA1 implementation via GLib.
3  *
4  * Copyright (C) 2009 Mark Lee <oauth@lazymalevolence.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  * Author : Mark Lee <oauth@lazymalevolence.com>
21  */
22
23 #include <string.h>
24 #include "sha1.h"
25
26 #define SHA1_BLOCKSIZE 64
27 #define SHA1_LEN 20
28
29 void
30 _oauth_hmac_sha1 (gchar *key, gchar *message,
31                   guchar **output, gsize *output_length)
32 {
33   gssize key_len;
34   gchar *final_key;
35   gchar opad[SHA1_BLOCKSIZE];
36   gchar ipad[SHA1_BLOCKSIZE];
37   GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA1);
38   if (strlen (key) > SHA1_BLOCKSIZE)
39   {
40     guchar new_key[SHA1_LEN];
41     key_len = SHA1_LEN;
42     g_checksum_update (checksum, key, strlen (key));
43     g_checksum_get_digest (checksum, new_key, &key_len);
44     g_assert (key_len == SHA1_LEN);
45     final_key = g_strdup ((gchar*)new_key);
46     g_checksum_reset (checksum);
47   }
48   else
49   {
50     final_key = g_strdup (key);
51     key_len = strlen (final_key);
52   }
53   memset (ipad, 0, sizeof (ipad));
54   memset (opad, 0, sizeof (opad));
55   memcpy (ipad, final_key, key_len);
56   memcpy (opad, final_key, key_len);
57   g_free (final_key);
58   for (gsize i = 0; i < SHA1_BLOCKSIZE; i++)
59   {
60     ipad[i] ^= 0x36;
61     opad[i] ^= 0x5c;
62   }
63   // inner
64   g_checksum_update (checksum, ipad, SHA1_BLOCKSIZE);
65   g_checksum_update (checksum, message, strlen (message));
66   guchar in[SHA1_LEN];
67   gssize in_len = SHA1_LEN;
68   g_checksum_get_digest (checksum, in, &in_len);
69   g_assert (in_len == SHA1_LEN);
70   // outer
71   g_checksum_reset (checksum);
72   g_checksum_update (checksum, opad, SHA1_BLOCKSIZE);
73   g_checksum_update (checksum, in, in_len);
74   *output = g_new0 (guchar, SHA1_LEN);
75   *output_length = SHA1_LEN;
76   g_checksum_get_digest (checksum, *output, output_length);
77   g_assert (*output_length == SHA1_LEN);
78   g_checksum_free (checksum);
79 }
80
81 /* vim: set et ts=2 sts=2 sw=2 ai cindent : */