@@ -65,6 +65,7 @@ namespace fs = boost::filesystem;
6565#if 1
6666
6767inline h128 fromUUID (std::string const & _uuid) { return h128 (boost::replace_all_copy (_uuid, " -" , " " )); }
68+ inline std::string toUUID (h128 const & _uuid) { std::string ret = toHex (_uuid.ref ()); for (unsigned i: {20 , 16 , 12 , 8 }) ret.insert (ret.begin () + i, ' -' ); return ret; }
6869
6970class KeyManager : public Worker
7071{
@@ -74,31 +75,48 @@ class KeyManager: public Worker
7475
7576 Secret secret (h128 const & _uuid, function<std::string()> const & _pass)
7677 {
77- auto rit = m_ready .find (_uuid);
78- if (rit != m_ready .end ())
78+ auto rit = m_cached .find (_uuid);
79+ if (rit != m_cached .end ())
7980 return rit->second ;
8081 auto it = m_keys.find (_uuid);
8182 if (it == m_keys.end ())
8283 return Secret ();
8384 Secret ret (decrypt (it->second , _pass ()));
8485 if (ret)
85- m_ready [_uuid] = ret;
86+ m_cached [_uuid] = ret;
8687 return ret;
8788 }
8889
89- h128 create ( std::string const & _pass)
90+ h128 import (Secret const & _s, std::string const & _pass)
9091 {
91- auto s = Secret::random ( );
92- h128 r ( sha3 (s)) ;
93- m_ready [r] = s ;
94- m_keys[r] = encrypt (s. asBytes (), _pass );
92+ h128 r ( sha3 (_s) );
93+ m_cached[r] = _s ;
94+ m_keys [r] = encrypt (_s. asBytes (), _pass) ;
95+ writeKeys ( );
9596 return r;
9697 }
9798
99+ h128 create (std::string const & _pass)
100+ {
101+ return import (Secret::random (), _pass);
102+ }
103+
104+ void clearCache () const { m_cached.clear (); }
105+
98106private:
99107 void writeKeys (std::string const & _keysPath = getDataDir(" web3" ) + "/keys")
100108 {
101- (void )_keysPath;
109+ fs::path p (_keysPath);
110+ boost::filesystem::create_directories (p);
111+ for (auto const & k: m_keys)
112+ {
113+ std::string uuid = toUUID (k.first );
114+ js::mObject v;
115+ v[" crypto" ] = k.second ;
116+ v[" id" ] = uuid;
117+ v[" version" ] = 2 ;
118+ writeFile ((p / uuid).string () + " .json" , js::write_string (js::mValue (v), true ));
119+ }
102120 }
103121
104122 void readKeys (std::string const & _keysPath = getDataDir(" web3" ) + "/keys")
@@ -126,9 +144,42 @@ class KeyManager: public Worker
126144
127145 static js::mValue encrypt (bytes const & _v, std::string const & _pass)
128146 {
129- (void )_v;
130- (void )_pass;
131- return js::mValue ();
147+ js::mObject ret;
148+
149+ // KDF info
150+ unsigned dklen = 16 ;
151+ unsigned iterations = 262144 ;
152+ bytes salt = h256::random ().asBytes ();
153+ ret[" kdf" ] = " pbkdf2" ;
154+ {
155+ js::mObject params;
156+ params[" prf" ] = " hmac-sha256" ;
157+ params[" c" ] = (int )iterations;
158+ params[" salt" ] = toHex (salt);
159+ params[" dklen" ] = (int )dklen;
160+ ret[" kdfparams" ] = params;
161+ }
162+ bytes derivedKey = pbkdf2 (_pass, salt, iterations, dklen);
163+
164+ // cipher info
165+ ret[" cipher" ] = " aes-128-cbc" ;
166+ h128 key (sha3 (h128 (derivedKey, h128::AlignRight)), h128::AlignRight);
167+ h128 iv = h128::random ();
168+ {
169+ js::mObject params;
170+ params[" iv" ] = toHex (iv.ref ());
171+ ret[" cipherparams" ] = params;
172+ }
173+
174+ // cipher text
175+ bytes cipherText = encryptSymNoAuth (key, iv, &_v);
176+ ret[" ciphertext" ] = toHex (cipherText);
177+
178+ // and mac.
179+ h256 mac = sha3 (bytesConstRef (&derivedKey).cropped (derivedKey.size () - 16 ).toBytes () + cipherText);
180+ ret[" mac" ] = toHex (mac.ref ());
181+
182+ return ret;
132183 }
133184
134185 static bytes decrypt (js::mValue const & _v, std::string const & _pass)
@@ -167,32 +218,29 @@ class KeyManager: public Worker
167218 }
168219
169220 // decrypt
170- bytes ret;
171221 if (o[" cipher" ].get_str () == " aes-128-cbc" )
172222 {
173223 auto params = o[" cipherparams" ].get_obj ();
174224 h128 key (sha3 (h128 (derivedKey, h128::AlignRight)), h128::AlignRight);
175225 h128 iv (params[" iv" ].get_str ());
176- decryptSymNoAuth (key, iv, &cipherText, ret );
226+ return decryptSymNoAuth (key, iv, &cipherText);
177227 }
178228 else
179229 {
180230 cwarn << " Unknown cipher" << o[" cipher" ].get_str () << " not supported." ;
181231 return bytes ();
182232 }
183-
184- return ret;
185233 }
186234
187- mutable std::map<h128, Secret> m_ready ;
235+ mutable std::map<h128, Secret> m_cached ;
188236 std::map<h128, js::mValue > m_keys;
189237};
190238
191239int main ()
192240{
193- cdebug << toHex (pbkdf2 (" password" , asBytes (" salt" ), 1 , 20 ));
194241 KeyManager keyman;
195- cdebug << " Secret key for 0498f19a-59db-4d54-ac95-33901b4f1870 is " << keyman.secret (fromUUID (" 0498f19a-59db-4d54-ac95-33901b4f1870" ), [](){ return " foo" ; });
242+ auto id = fromUUID (" 441193ae-a767-f1c3-48ba-dd6610db5ed0" );
243+ cdebug << " Secret key for " << toUUID (id) << " is" << keyman.secret (id, [](){ return " bar" ; });
196244}
197245
198246#elif 0
0 commit comments