git.fiddlerwoaroof.com
Browse code

Refactor generate_token to use vectors internally

Ed Langley authored on 13/06/2017 20:34:47
Showing 3 changed files
... ...
@@ -15,8 +15,12 @@
15 15
 #include <openssl/hmac.h>
16 16
 #include <openssl/evp.h>
17 17
 
18
+#include "base32.h"
18 19
 namespace
19 20
 {
21
+class hmac_failed_exception : public std::exception
22
+{};
23
+
20 24
 int ipow (int base, int exp)
21 25
 {
22 26
     int result = 1;
... ...
@@ -62,7 +66,8 @@ class token_generator_impl : public token_generator_ifc
62 66
 {
63 67
 private:
64 68
     const sys_time clock;
65
-    unsigned int code_digits;
69
+    const unsigned int code_digits;
70
+    const base32 codec;
66 71
 
67 72
 private:
68 73
     std::string zero_fill (unsigned long result, int digits) const
... ...
@@ -82,13 +87,18 @@ private:
82 87
         return bytesToInt (offsetBytes) & 0x7fffffff;
83 88
     }
84 89
 
85
-    std::string hotp (const std::string &key, const unsigned char *data,
90
+    std::string hotp (const std::vector<uint8_t> &key,
91
+                      const unsigned char *data,
86 92
                       size_t data_size, const int digits=6) const
87 93
     {
88 94
         // TODO: see if I can use sha256/etc. with google auth...
89
-        unsigned char *digest = HMAC (EVP_sha1(), key.c_str(), key.size(), data,
95
+        unsigned char *digest = HMAC (EVP_sha1(), key.data(), key.size(), data,
90 96
                                       data_size, NULL, NULL);
91 97
 
98
+        if (digest == nullptr) {
99
+            throw hmac_failed_exception();
100
+        }
101
+
92 102
         std::string digest_s = std::string (reinterpret_cast<const char *> (digest),
93 103
                                             20); //TODO: use vectors
94 104
 
... ...
@@ -103,7 +113,16 @@ public:
103 113
         clock (clock), code_digits (code_digits)
104 114
     {}
105 115
 
106
-    std::string generate_token (const std::string &key) const override
116
+    std::string generate_token (const std::string &key_string) const override
117
+    {
118
+        // std::cout << "KEY SIZE: " << key_string.size() << std::endl;
119
+        // std::vector<uint8_t> key = codec.decode(key_string);
120
+        // std::cout << "LENGTH: " << key.size() << " '" << key_string << "'" << std::endl;
121
+        std::vector<uint8_t> key (key_string.begin(), key_string.end());
122
+        return generate_token (key);
123
+    }
124
+
125
+    std::string generate_token (const std::vector<uint8_t> key) const
107 126
     {
108 127
         // Assuming time is > 0, integer division produces the result we want.
109 128
         const time_t &time_chunk = clock.time (nullptr) / 30;
... ...
@@ -123,3 +142,4 @@ totp_generator::totp_generator (
123 142
     const int code_digits) :
124 143
     delegate_ (std::make_shared<token_generator_impl> (clock, code_digits))
125 144
 {}
145
+
... ...
@@ -18,6 +18,7 @@
18 18
 #include <iomanip>
19 19
 #include <cmath>
20 20
 #include <ctime>
21
+#include <iostream>
21 22
 
22 23
 #include "sys_stdlib.h"
23 24
 #include "sys_time.h"
... ...
@@ -33,20 +34,20 @@ public:
33 34
 
34 35
 class totp_generator
35 36
 {
36
- public:
37
+public:
37 38
     using delegate = std::shared_ptr<token_generator_ifc>;
38 39
 
39
- private:
40
+private:
40 41
     delegate delegate_;
41 42
 
42
- public:
43
+public:
43 44
     std::string generate_token (const std::string &key) const
44
-        {
45
-            return delegate_->generate_token(key);
46
-        }
45
+    {
46
+        return delegate_->generate_token (key);
47
+    }
47 48
 
48 49
     totp_generator (delegate delegate_) :
49
-    delegate_ (delegate_)
50
+        delegate_ (delegate_)
50 51
     {}
51 52
 
52 53
     totp_generator (const sys_time clock,
... ...
@@ -54,3 +55,4 @@ class totp_generator
54 55
 };
55 56
 
56 57
 #endif
58
+
... ...
@@ -81,7 +81,8 @@ int given_digits()
81 81
     auto generator = totp_generator (stdtime, 6);
82 82
 
83 83
     // when
84
-    auto actual = generator.generate_token("\x00");
84
+    std::string key { 0 };
85
+    auto actual = generator.generate_token (key);
85 86
 
86 87
     // then
87 88
     check (actual.size() == 6, "size is wrong");
... ...
@@ -101,8 +102,9 @@ int modulated_source_modulates_tokens()
101 102
     auto generator = totp_generator (stdtime, 6);
102 103
 
103 104
     // when
104
-    auto actual1 = generator.generate_token("\x00");
105
-    auto actual2 = generator.generate_token("\x00");
105
+    std::string key ("\x00", 1);
106
+    auto actual1 = generator.generate_token (key);
107
+    auto actual2 = generator.generate_token (key);
106 108
 
107 109
     // then
108 110
     check (actual1 != actual2, "tokens should be different");
... ...
@@ -117,9 +119,10 @@ int int_max()
117 119
 
118 120
     sys_time stdtime (test_stdtime);
119 121
     auto generator = totp_generator (stdtime, 6);
122
+    std::string key ("\x00", 1);
120 123
 
121 124
     // when
122
-    auto actual = generator.generate_token("\x00");
125
+    auto actual = generator.generate_token (key);
123 126
 
124 127
     // then
125 128
     check (actual.size() == 6, "size is wrong");
... ...
@@ -134,12 +137,13 @@ int int_min()
134 137
     // given
135 138
     std::initializer_list<time_t> samples { INT_MIN };
136 139
     auto test_stdtime = std::make_shared<fake_time> (samples);
140
+    std::string key ("\x00", 1);
137 141
 
138 142
     sys_time stdtime (test_stdtime);
139 143
     auto generator = totp_generator (stdtime, 6);
140 144
 
141 145
     // when
142
-    auto actual = generator.generate_token("\x00");
146
+    auto actual = generator.generate_token (key);
143 147
 
144 148
     // then
145 149
     check (actual.size() == 6, "size is wrong");
... ...
@@ -165,7 +169,7 @@ int int_precomputed()
165 169
     std::string expected = "258675";
166 170
 
167 171
     // when
168
-    auto actual = generator.generate_token(key);
172
+    auto actual = generator.generate_token (key);
169 173
 
170 174
     // then
171 175
     check (actual.size() == 6, "size is wrong");
... ...
@@ -188,3 +192,4 @@ int main (int argc, char *argv[])
188 192
 {
189 193
     return !run_tests();
190 194
 }
195
+