]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - lib/ext2fs/digest_encode.c
Merge remote-tracking branch 'josch/libarchive' into josch-libarchive
[thirdparty/e2fsprogs.git] / lib / ext2fs / digest_encode.c
CommitLineData
bf34b4af
TT
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
437651ad
TT
23static const char *lookup_table =
24 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
25
bf34b4af
TT
26/**
27 * ext2fs_digest_encode() -
28 *
29 * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
30 * The encoded string is roughly 4/3 times the size of the input string.
31 */
437651ad 32int ext2fs_digest_encode(const char *src, int len, char *dst)
bf34b4af 33{
437651ad
TT
34 int i = 0, bits = 0, ac = 0;
35 char *cp = dst;
bf34b4af 36
437651ad
TT
37 while (i < len) {
38 ac += (((unsigned char) src[i]) << bits);
39 bits += 8;
40 do {
41 *cp++ = lookup_table[ac & 0x3f];
42 ac >>= 6;
43 bits -= 6;
44 } while (bits >= 6);
45 i++;
bf34b4af 46 }
437651ad
TT
47 if (bits)
48 *cp++ = lookup_table[ac & 0x3f];
49 return cp - dst;
50}
51
52int ext2fs_digest_decode(const char *src, int len, char *dst)
53{
54 int i = 0, bits = 0, ac = 0;
55 const char *p;
56 char *cp = dst;
57
58 while (i < len) {
59 p = strchr(lookup_table, src[i]);
60 if (p == NULL || src[i] == 0)
61 return -1;
62 ac += (p - lookup_table) << bits;
63 bits += 6;
64 if (bits >= 8) {
65 *cp++ = ac & 0xff;
66 ac >>= 8;
67 bits -= 8;
68 }
8afaf3be 69 i++;
bf34b4af 70 }
437651ad
TT
71 if (ac)
72 return -1;
73 return cp - dst;
bf34b4af
TT
74}
75
437651ad 76
bf34b4af
TT
77#ifdef UNITTEST
78static const struct {
79 unsigned char d[32];
8afaf3be 80 unsigned int len;
fa04febc 81 const char *ed;
bf34b4af
TT
82} tests[] = {
83 { { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
84 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
85 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
8afaf3be 86 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }, 32,
437651ad 87 "jDLxChJ,cQhm7TPyZ+WukcirBROZbOJTkWZmbgnU4WF"
bf34b4af
TT
88 },
89 { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
90 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
91 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
8afaf3be 92 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, 32,
437651ad 93 "6inF,+YAPreQBBk3d5qIjA7AhNqlXoHn0Cx,hJPAV0K"
bf34b4af
TT
94 },
95 { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
96 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
97 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
8afaf3be 98 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, 32,
437651ad 99 "k0oahJtB4gb5AbykM4DY5MKPknFZ,HyZ2ze7Unx2GEM"
bf34b4af 100 },
8afaf3be 101 { { 0x00, }, 1,
437651ad 102 "AA"
8afaf3be
TT
103 },
104 { { 0x01, }, 1,
437651ad 105 "BA"
8afaf3be
TT
106 },
107 { { 0x01, 0x02 }, 2,
437651ad 108 "BIA"
8afaf3be
TT
109 },
110 { { 0x01, 0x02, 0x03 }, 3,
437651ad 111 "BIwA"
8afaf3be
TT
112 },
113 { { 0x01, 0x02, 0x03, 0x04 }, 4,
437651ad 114 "BIwAEA"
8afaf3be
TT
115 },
116 { { 0x01, 0x02, 0x03, 0x04, 0xff }, 5,
437651ad 117 "BIwAE8P"
8afaf3be
TT
118 },
119 { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe }, 6,
437651ad 120 "BIwAE8v,"
8afaf3be
TT
121 },
122 { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe, 0xfd }, 7,
437651ad 123 "BIwAE8v,9D"
8afaf3be 124 },
bf34b4af
TT
125};
126
127int main(int argc, char **argv)
128{
fa04febc 129 int i, ret, len;
bf34b4af 130 int errors = 0;
fa04febc 131 char tmp[1024], tmp2[1024];
bf34b4af 132
437651ad
TT
133 if (argc == 3 && !strcmp(argv[1], "encode")) {
134 memset(tmp, 0, sizeof(tmp));
135 ext2fs_digest_encode(argv[2], strlen(argv[2]), tmp);
136 puts(tmp);
137 exit(0);
138 }
139 if (argc == 3 && !strcmp(argv[1], "decode")) {
140 memset(tmp, 0, sizeof(tmp));
141 ret = ext2fs_digest_decode(argv[2], strlen(argv[2]), tmp);
142 puts(tmp);
143 fprintf(stderr, "returned %d\n", ret);
144 exit(0);
145 }
bf34b4af 146 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
8afaf3be 147 memset(tmp, 0, sizeof(tmp));
fa04febc
DL
148 ret = ext2fs_digest_encode((const char *) tests[i].d,
149 tests[i].len, tmp);
8afaf3be
TT
150 len = strlen(tmp);
151 printf("Test Digest %d (returned %d): ", i, ret);
152 if (ret != len) {
153 printf("FAILED returned %d, string length was %d\n",
154 ret, len);
155 errors++;
437651ad
TT
156 continue;
157 } else if (strcmp(tmp, tests[i].ed) != 0) {
8afaf3be
TT
158 printf("FAILED: got %s, expected %s\n", tmp,
159 tests[i].ed);
bf34b4af 160 errors++;
437651ad
TT
161 continue;
162 }
163 ret = ext2fs_digest_decode(tmp, len, tmp2);
164 if (ret != tests[i].len) {
165 printf("FAILED decode returned %d, expected %d\n",
166 ret, tests[i].len);
167 errors++;
168 continue;
169 }
170 if (memcmp(tmp2, tests[i].d, ret) != 0) {
171 puts("FAILED: decode mismatched");
172 errors++;
173 continue;
174 }
175 printf("OK\n");
bf34b4af 176 }
8afaf3be
TT
177 for (i = 1; i < argc; i++) {
178 memset(tmp, 0, sizeof(tmp));
179 ret = ext2fs_digest_encode(argv[i], strlen(argv[i]), tmp);
180 len = strlen(tmp);
181 printf("Digest of '%s' is '%s' (returned %d, length %d)\n",
182 argv[i], tmp, ret, len);
183 }
bf34b4af
TT
184 return errors;
185}
186
187#endif /* UNITTEST */