wamp_auth_utils.hpp
1 //
3 // Copyright (c) Crossbar.io Technologies GmbH and contributors
4 //
5 // Boost Software License - Version 1.0 - August 17th, 2003
6 //
7 // Permission is hereby granted, free of charge, to any person or organization
8 // obtaining a copy of the software and accompanying documentation covered by
9 // this license (the "Software") to use, reproduce, display, distribute,
10 // execute, and transmit the Software, and to prepare derivative works of the
11 // Software, and to permit third-parties to whom the Software is furnished to
12 // do so, all subject to the following:
13 //
14 // The copyright notices in the Software and this entire statement, including
15 // the above license grant, this restriction and the following disclaimer,
16 // must be included in all copies of the Software, in whole or in part, and
17 // all derivative works of the Software, unless such copies or derivative
18 // works are solely in the form of machine-executable object code generated by
19 // a source language processor.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 // DEALINGS IN THE SOFTWARE.
28 //
30 
31 #ifndef WAMP_AUTH_UTILS_HPP
32 #define WAMP_AUTH_UTILS_HPP
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include <exception>
39 
40 //
41 // Execpetion thrown when something gets wrong
42 // creating the derived auth key.....
43 //
44 class derived_key_error : public std::exception
45 {
46  virtual const char* what() const throw()
47  {
48  return "Error occured when calulcate a derived key";
49  }
50 };
51 
52 
54 // - using openssl crypto lib
55 // see openssl at : https://www.openssl.org
57 
58 
59 #include <openssl/evp.h>
60 #include <openssl/hmac.h>
61 #include <openssl/bio.h>
62 #include <openssl/buffer.h>
63 
64 #include <stdint.h>
65 
66 
73 inline std::string base_64_encode(const std::string & data )
74 {
75  BIO *bio, *b64;
76  BUF_MEM *pBuf;
77 
78  b64 = BIO_new(BIO_f_base64());
79  bio = BIO_new(BIO_s_mem());
80  bio = BIO_push(b64, bio);
81 
82  BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
83 
84  BIO_write(bio, (const unsigned char *) data.c_str(), data.size());
85  (void)BIO_flush(bio);
86 
87  BIO_get_mem_ptr(bio, &pBuf);
88  (void)BIO_set_close(bio, BIO_NOCLOSE);
89 
90  std::string str_out;
91  str_out.assign( pBuf->data, pBuf->length );
92 
93  BIO_free_all(bio);
94 
95  return str_out;
96 }
97 
98 
108 inline std::string derive_key(
109  const std::string & passwd,
110  const std::string & salt,
111  int iterations,
112  int keylen
113  )
114 {
115 
116  int passwdLen = passwd.size();
117  const char * pwd = passwd.c_str();
118 
119  int saltLen = salt.size();
120  unsigned char * salt_value = (unsigned char * ) salt.c_str();
121 
122  std::string str_out;
123  str_out.resize( keylen );
124 
125 
126  unsigned char * out = (unsigned char *) str_out.c_str();
127 
128 
129  int result = PKCS5_PBKDF2_HMAC(
130  pwd, passwdLen,
131  salt_value, saltLen,
132  iterations,
133  EVP_sha256(),
134  keylen, out);
135 
136  if ( result != 0 )
137  {
138  return base_64_encode( str_out );
139  }
140  else
141  {
142  throw derived_key_error();
143  }
144 }
145 
146 
154 inline std::string compute_wcs(
155  const std::string & key,
156  const std::string & challenge )
157 {
158 
159  unsigned int len = 32;
160  unsigned char hash[32];
161 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
162  HMAC_CTX hmac;
163  HMAC_CTX_init(&hmac);
164  HMAC_Init_ex(&hmac, key.data(), key.length(), EVP_sha256(), NULL);
165  HMAC_Update(&hmac, (unsigned char*) challenge.data(), challenge.length());
166  HMAC_Final(&hmac, hash, &len);
167  HMAC_CTX_cleanup(&hmac);
168 #else
169  HMAC_CTX *hmac = HMAC_CTX_new();
170  if (!hmac)
171  return "";
172  HMAC_Init_ex(hmac, key.data(), key.length(), EVP_sha256(), NULL);
173  HMAC_Update(hmac, ( unsigned char* ) challenge.data(), challenge.length());
174  HMAC_Final(hmac, hash, &len);
175  HMAC_CTX_free(hmac);
176 #endif
177 
178  std::string str_out;
179  str_out.assign( ( char * ) &hash , 32 );
180 
181  return base_64_encode( str_out );
182 }
183 
184 
185 
198 inline std::string generate_wcs(int length=14){
199 
200  //
201  // The characters from which to generate the secret.
202  //
203  static const char WCS_SECRET_CHARSET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
204 
205  std::string s;
206  for (int i = 0; i < length; ++i) {
207  s.push_back( WCS_SECRET_CHARSET[ rand() % (sizeof(WCS_SECRET_CHARSET) - 1) ] );
208  }
209 
210  return s;
211 }
212 
213 
214 #endif //WAMP_AUTH_UTILS_HPP