b32 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4ca5fde0dc3d010bd9ced37fbc91f1f78c9fa98a9bd03be71b85a138c792d8e8
4
+ data.tar.gz: a5b291d92995d6e1bce4f0b843ca0ee58ab63da03cdae747d51f10e49810aa26
5
+ SHA512:
6
+ metadata.gz: 434575fbb0c8e112d92152d819bbe2fe0eec8eba2bf609bf6503ee230a62c43aaa79b0d4895e0ad9bfb9bb6d5ee6591795ea12e29bbdeb0b6c00f182a4496a26
7
+ data.tar.gz: b5723291614d401069e7c62c772d8528d2575528ea371dcd184446305e5ef51642b92b0e8b6589bf8d9365eaf96644eb2164d8ff83c929a89f93076f9f67981f
@@ -0,0 +1,61 @@
1
+ #include <stdlib.h>
2
+ #include <ruby.h>
3
+ #include <ruby/encoding.h>
4
+ #include "base32.h"
5
+ #include <ctype.h>
6
+
7
+
8
+ static VALUE m_B32;
9
+ static VALUE e_DecodeError;
10
+
11
+ static VALUE
12
+ b32_encode(int argc, VALUE* argv, VALUE self)
13
+ {
14
+ VALUE input;
15
+ const unsigned char* src;
16
+ size_t srclen;
17
+ rb_scan_args(argc, argv, "1", &input);
18
+
19
+ if (TYPE(input) != T_STRING) {
20
+ rb_raise(rb_eTypeError, "expected a String");
21
+ }
22
+
23
+ src = (unsigned char*) StringValueCStr(input);
24
+ srclen = BASE32_LEN(RSTRING_LEN(input));
25
+
26
+ unsigned char dest[srclen];
27
+ base32_encode(src, RSTRING_LEN(input), dest);
28
+ return rb_utf8_str_new((const char*) dest, srclen );
29
+ }
30
+
31
+ static VALUE
32
+ b32_decode(int argc, VALUE *argv, VALUE self)
33
+ {
34
+ VALUE input;
35
+ const unsigned char* src;
36
+ size_t input_len, estimate_len;
37
+
38
+ rb_scan_args(argc, argv, "1", &input);
39
+
40
+ if (TYPE(input) != T_STRING) {
41
+ rb_raise(rb_eTypeError, "expected a String");
42
+ }
43
+
44
+ src = (unsigned char*) StringValueCStr(input);
45
+ input_len = RSTRING_LEN(input);
46
+ estimate_len = UNBASE32_LEN(input_len);
47
+ unsigned char out[estimate_len];
48
+
49
+ base32_decode(src, out);
50
+
51
+ return rb_utf8_str_new_cstr((const char*) out);
52
+ }
53
+
54
+ void
55
+ Init_b32() {
56
+ m_B32 = rb_define_module("B32");
57
+
58
+ e_DecodeError = rb_define_class_under(m_B32, "DecodeError", rb_eStandardError);
59
+ rb_define_module_function(m_B32, "encode", b32_encode, -1);
60
+ rb_define_module_function(m_B32, "decode", b32_decode, -1);
61
+ }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * base32 (de)coder implementation as specified by RFC4648.
3
+ *
4
+ * Copyright (c) 2010 Adrien Kunysz
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ **/
24
+
25
+ #include <assert.h> // assert()
26
+ #include <limits.h> // CHAR_BIT
27
+
28
+ #include "base32.h"
29
+
30
+ /**
31
+ * Let this be a sequence of plain data before encoding:
32
+ *
33
+ * 01234567 01234567 01234567 01234567 01234567
34
+ * +--------+--------+--------+--------+--------+
35
+ * |< 0 >< 1| >< 2 ><|.3 >< 4.|>< 5 ><.|6 >< 7 >|
36
+ * +--------+--------+--------+--------+--------+
37
+ *
38
+ * There are 5 octets of 8 bits each in each sequence.
39
+ * There are 8 blocks of 5 bits each in each sequence.
40
+ *
41
+ * You probably want to refer to that graph when reading the algorithms in this
42
+ * file. We use "octet" instead of "byte" intentionnaly as we really work with
43
+ * 8 bits quantities. This implementation will probably not work properly on
44
+ * systems that don't have exactly 8 bits per (unsigned) char.
45
+ **/
46
+
47
+ static size_t min(size_t x, size_t y)
48
+ {
49
+ return x < y ? x : y;
50
+ }
51
+
52
+ static const unsigned char PADDING_CHAR = '=';
53
+
54
+ /**
55
+ * Pad the given buffer with len padding characters.
56
+ */
57
+ static void pad(unsigned char *buf, int len)
58
+ {
59
+ for (int i = 0; i < len; i++)
60
+ buf[i] = PADDING_CHAR;
61
+ }
62
+
63
+ /**
64
+ * This convert a 5 bits value into a base32 character.
65
+ * Only the 5 least significant bits are used.
66
+ */
67
+ static unsigned char encode_char(unsigned char c)
68
+ {
69
+ static unsigned char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
70
+ return base32[c & 0x1F]; // 0001 1111
71
+ }
72
+
73
+ /**
74
+ * Decode given character into a 5 bits value.
75
+ * Returns -1 iff the argument given was an invalid base32 character
76
+ * or a padding character.
77
+ */
78
+ static int decode_char(unsigned char c)
79
+ {
80
+ char retval = -1;
81
+
82
+ if (c >= 'A' && c <= 'Z')
83
+ retval = c - 'A';
84
+ if (c >= '2' && c <= '7')
85
+ retval = c - '2' + 26;
86
+
87
+ assert(retval == -1 || ((retval & 0x1F) == retval));
88
+
89
+ return retval;
90
+ }
91
+
92
+ /**
93
+ * Given a block id between 0 and 7 inclusive, this will return the index of
94
+ * the octet in which this block starts. For example, given 3 it will return 1
95
+ * because block 3 starts in octet 1:
96
+ *
97
+ * +--------+--------+
98
+ * | ......<|.3 >....|
99
+ * +--------+--------+
100
+ * octet 1 | octet 2
101
+ */
102
+ static int get_octet(int block)
103
+ {
104
+ assert(block >= 0 && block < 8);
105
+ return (block*5) / 8;
106
+ }
107
+
108
+ /**
109
+ * Given a block id between 0 and 7 inclusive, this will return how many bits
110
+ * we can drop at the end of the octet in which this block starts.
111
+ * For example, given block 0 it will return 3 because there are 3 bits
112
+ * we don't care about at the end:
113
+ *
114
+ * +--------+-
115
+ * |< 0 >...|
116
+ * +--------+-
117
+ *
118
+ * Given block 1, it will return -2 because there
119
+ * are actually two bits missing to have a complete block:
120
+ *
121
+ * +--------+-
122
+ * |.....< 1|..
123
+ * +--------+-
124
+ **/
125
+ static int get_offset(int block)
126
+ {
127
+ assert(block >= 0 && block < 8);
128
+ return (8 - 5 - (5*block) % 8);
129
+ }
130
+
131
+ /**
132
+ * Like "b >> offset" but it will do the right thing with negative offset.
133
+ * We need this as bitwise shifting by a negative offset is undefined
134
+ * behavior.
135
+ */
136
+ static unsigned char shift_right(unsigned char byte, char offset)
137
+ {
138
+ if (offset > 0)
139
+ return byte >> offset;
140
+ else
141
+ return byte << -offset;
142
+ }
143
+
144
+ static unsigned char shift_left(unsigned char byte, char offset)
145
+ {
146
+ return shift_right(byte, - offset);
147
+ }
148
+
149
+ /**
150
+ * Encode a sequence. A sequence is no longer than 5 octets by definition.
151
+ * Thus passing a length greater than 5 to this function is an error. Encoding
152
+ * sequences shorter than 5 octets is supported and padding will be added to the
153
+ * output as per the specification.
154
+ */
155
+ static void encode_sequence(const unsigned char *plain, int len, unsigned char *coded)
156
+ {
157
+ assert(CHAR_BIT == 8); // not sure this would work otherwise
158
+ assert(len >= 0 && len <= 5);
159
+
160
+ for (int block = 0; block < 8; block++) {
161
+ int octet = get_octet(block); // figure out which octet this block starts in
162
+ int junk = get_offset(block); // how many bits do we drop from this octet?
163
+
164
+ if (octet >= len) { // we hit the end of the buffer
165
+ pad(&coded[block], 8 - block);
166
+ return;
167
+ }
168
+
169
+ unsigned char c = shift_right(plain[octet], junk); // first part
170
+
171
+ if (junk < 0 // is there a second part?
172
+ && octet < len - 1) // is there still something to read?
173
+ {
174
+ c |= shift_right(plain[octet+1], 8 + junk);
175
+ }
176
+ coded[block] = encode_char(c);
177
+ }
178
+ }
179
+
180
+ void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded)
181
+ {
182
+ // All the hard work is done in encode_sequence(),
183
+ // here we just need to feed it the data sequence by sequence.
184
+ for (size_t i = 0, j = 0; i < len; i += 5, j += 8) {
185
+ encode_sequence(&plain[i], (int)min(len - i, 5), &coded[j]);
186
+ }
187
+ }
188
+
189
+ static int decode_sequence(const unsigned char *coded, unsigned char *plain)
190
+ {
191
+ assert(CHAR_BIT == 8);
192
+ assert(coded && plain);
193
+
194
+ plain[0] = 0;
195
+ for (int block = 0; block < 8; block++) {
196
+ int offset = get_offset(block);
197
+ int octet = get_octet(block);
198
+
199
+ int c = decode_char(coded[block]);
200
+ if (c < 0) // invalid char, stop here
201
+ return octet;
202
+
203
+ plain[octet] |= shift_left(c, offset);
204
+ if (offset < 0) { // does this block overflows to next octet?
205
+ assert(octet < 4);
206
+ plain[octet+1] = shift_left(c, 8 + offset);
207
+ }
208
+ }
209
+ return 5;
210
+ }
211
+
212
+ size_t base32_decode(const unsigned char *coded, unsigned char *plain)
213
+ {
214
+ size_t written = 0;
215
+ for (size_t i = 0, j = 0; ; i += 8, j += 5) {
216
+ int n = decode_sequence(&coded[i], &plain[j]);
217
+ written += n;
218
+ if (n < 5)
219
+ return written;
220
+ }
221
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * base32 (de)coder implementation as specified by RFC4648.
3
+ *
4
+ * Copyright (c) 2010 Adrien Kunysz
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ **/
24
+
25
+ #ifndef __BASE32_H_
26
+ #define __BASE32_H_
27
+
28
+ #include <stddef.h> // size_t
29
+
30
+ /**
31
+ * Returns the length of the output buffer required to encode len bytes of
32
+ * data into base32. This is a macro to allow users to define buffer size at
33
+ * compilation time.
34
+ */
35
+ #define BASE32_LEN(len) (((len)/5)*8 + ((len) % 5 ? 8 : 0))
36
+
37
+ /**
38
+ * Returns the length of the output buffer required to decode a base32 string
39
+ * of len characters. Please note that len must be a multiple of 8 as per
40
+ * definition of a base32 string. This is a macro to allow users to define
41
+ * buffer size at compilation time.
42
+ */
43
+ #define UNBASE32_LEN(len) (((len)/8)*5)
44
+
45
+ /**
46
+ * Encode the data pointed to by plain into base32 and store the
47
+ * result at the address pointed to by coded. The "coded" argument
48
+ * must point to a location that has enough available space
49
+ * to store the whole coded string. The resulting string will only
50
+ * contain characters from the [A-Z2-7=] set. The "len" arguments
51
+ * define how many bytes will be read from the "plain" buffer.
52
+ **/
53
+ void base32_encode(const unsigned char *plain, size_t len, unsigned char *coded);
54
+
55
+ /**
56
+ * Decode the null terminated string pointed to by coded and write
57
+ * the decoded data into the location pointed to by plain. The
58
+ * "plain" argument must point to a location that has enough available
59
+ * space to store the whole decoded string.
60
+ * Returns the length of the decoded string. This may be less than
61
+ * expected due to padding. If an invalid base32 character is found
62
+ * in the coded string, decoding will stop at that point.
63
+ **/
64
+ size_t base32_decode(const unsigned char *coded, unsigned char *plain);
65
+
66
+ #endif
@@ -0,0 +1,8 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('b32')
4
+ if find_header 'base32.h', File.expand_path(File.dirname(__FILE__))
5
+ create_makefile('b32')
6
+ else
7
+ raise "Could not find base32.h"
8
+ end
@@ -0,0 +1,3 @@
1
+ module B32
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: b32
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - James Cook
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ description:
42
+ email:
43
+ executables: []
44
+ extensions:
45
+ - ext/b32/extconf.rb
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ext/b32/b32.c
49
+ - ext/b32/base32.c
50
+ - ext/b32/base32.h
51
+ - ext/b32/extconf.rb
52
+ - lib/b32/version.rb
53
+ homepage: https://github.com/jamescook/b32
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">"
64
+ - !ruby/object:Gem::Version
65
+ version: '2.1'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.7.6
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Base32 Ruby C Extension
77
+ test_files: []