Whamcloud - gitweb
libext2fs: add ext2fs_digest_encode()
[tools/e2fsprogs.git] / lib / ext2fs / digest_encode.c
1 /*
2  * lib/ext2fs/digest_encode.c
3  *
4  * A function to encode a digest using 64 characters that are valid in a
5  * filename per ext2fs rules.
6  *
7  * Written by Uday Savagaonkar, 2014.
8  *
9  * Copyright 2014 Google Inc.  All Rights Reserved.
10  *
11  * %Begin-Header%
12  * This file may be redistributed under the terms of the GNU Library
13  * General Public License, version 2.
14  * %End-Header%
15  */
16
17 #include "config.h"
18 #if HAVE_SYS_TYPES_H
19 #include <sys/types.h>
20 #endif
21 #include "ext2fs.h"
22
23 /**
24  * ext2fs_digest_encode() -
25  *
26  * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
27  * The encoded string is roughly 4/3 times the size of the input string.
28  */
29 int ext2fs_digest_encode(const char *src, unsigned long len, char *dst)
30 {
31         static const char *lookup_table =
32                 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+";
33         unsigned num_chunks, i;
34         char tmp_buf[3];
35         unsigned c0, c1, c2, c3;
36
37         num_chunks = len/3;
38         for (i = 0; i < num_chunks; i++) {
39                 c0 = src[3*i] & 0x3f;
40                 c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f;
41                 c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f;
42                 c3 = (src[3*i+2]>>2) & 0x3f;
43                 dst[4*i] = lookup_table[c0];
44                 dst[4*i+1] = lookup_table[c1];
45                 dst[4*i+2] = lookup_table[c2];
46                 dst[4*i+3] = lookup_table[c3];
47         }
48         if (i*3 < len) {
49                 memset(tmp_buf, 0, 3);
50                 memcpy(tmp_buf, &src[3*i], len-3*i);
51                 c0 = tmp_buf[0] & 0x3f;
52                 c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f;
53                 c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f;
54                 c3 = (tmp_buf[2]>>2) & 0x3f;
55                 dst[4*i] = lookup_table[c0];
56                 dst[4*i+1] = lookup_table[c1];
57                 dst[4*i+2] = lookup_table[c2];
58                 dst[4*i+3] = lookup_table[c3];
59         }
60         return 4*(i+1);
61 }
62
63 #ifdef UNITTEST
64 static const struct {
65         unsigned char d[32];
66         const unsigned char *ed;
67 } tests[] = {
68         { { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
69             0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
70             0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
71             0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 },
72         "JdlXcHj+CqHM7tpYz_wUKCIRbrozBojtKwzMBGNu4wfa"
73         },
74         { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
75             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
76             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
77             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad },
78         "6INf+_yapREqbbK3D5QiJa7aHnQLxOhN0cX+Hjpav0ka"
79         },
80         { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
81             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
82             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
83             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 },
84         "K0OAHjTb4GB5aBYKm4dy5mkpKNfz+hYz2ZE7uNX2gema"
85         },
86 };
87
88 int main(int argc, char **argv)
89 {
90         int i;
91         int errors = 0;
92         unsigned char tmp[44];
93
94         for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
95                 ext2fs_digest_encode(tmp, tests[i].d, 32);
96                 printf("Test Digest %d: ", i);
97                 if (memcmp(tmp, tests[i].ed, 44) != 0) {
98                         printf("FAILED\n");
99                         errors++;
100                 } else
101                         printf("OK\n");
102         }
103         return errors;
104 }
105
106 #endif /* UNITTEST */