1 module jwt.algorithms;
2 
3 import std.digest.hmac;
4 import std.digest.sha;
5 import std.string : representation;
6 import std.base64;
7 import std.stdio;
8 
9 import jwt.exceptions;
10 
11 /**
12 * string literal used to represent signing algorithm type
13 */
14 enum JWTAlgorithm : string {
15     NONE  = "none",     // string representation of the none algorithm
16     HS256 = "HS256",   // string representation of hmac algorithm with sha256
17     HS384 = "HS384",  // string representation of hmac algorithm with sha348
18     HS512 = "HS512"  //string representation of hmac algorithm with sha512
19 }
20 
21 /**
22 * an alias for base64 encoding that is url safe and removes the '=' padding character
23 */
24 alias URLSafeBase64 = Base64Impl!('-', '_', Base64.NoPadding);
25 
26 /**
27 * signs the given data with the secret using the given algorithm
28 * Params:
29 *       secret = the secret used to sign the data
30 *       data = the data that is to be signed
31 *       alg = the algorithm to be used to sign the data
32 * Returns: signature of the data
33 */
34 string sign(string secret, string data, JWTAlgorithm alg) {
35 
36     switch(alg) {
37 
38         case JWTAlgorithm.HS256:
39             auto signature = HMAC!SHA256(secret.representation);
40             signature.put(data.representation);
41             return URLSafeBase64.encode(signature.finish());
42 
43         case JWTAlgorithm.HS384:
44             auto signature = HMAC!SHA384(secret.representation);
45             signature.put(data.representation);
46             return URLSafeBase64.encode(signature.finish());
47 
48         case JWTAlgorithm.HS512:
49             auto signature = HMAC!SHA512(secret.representation);
50             signature.put(data.representation);
51             return URLSafeBase64.encode(signature.finish());
52 
53         case JWTAlgorithm.NONE:
54             return "";
55 
56         default:
57             throw new UnsupportedAlgorithmException(alg ~ " algorithm is not supported!");
58 
59     }
60 
61 }
62 ///
63 unittest {
64 
65     string secret = "supersecret";
66 
67     string data = "an unstoppable force crashes into an unmovable body";
68 
69     string signature = sign(secret, data, JWTAlgorithm.HS512);
70 
71     assert(signature.length > 0);
72 
73     signature = sign(secret, data, JWTAlgorithm.NONE);
74 
75     assert(signature.length == 0);
76 
77 }