Comparison

util/sasl/scram.lua @ 2196:614c839c30c5

Completed SCRAM-SHA-1 implementation to a ready-to-test state.
author Tobias Markmann <tm@ayena.de>
date Tue, 17 Nov 2009 11:03:54 +0100
parent 2194:41d42d253a1d
child 2197:1509cabb8321
comparison
equal deleted inserted replaced
2195:8788c995fcbd 2196:614c839c30c5
15 15
16 local base64 = require "util.encodings".base64; 16 local base64 = require "util.encodings".base64;
17 local xor = require "bit".bxor 17 local xor = require "bit".bxor
18 local hmac_sha1 = require "util.hmac".sha1; 18 local hmac_sha1 = require "util.hmac".sha1;
19 local sha1 = require "util.hashes".sha1; 19 local sha1 = require "util.hashes".sha1;
20 local generate_uuid = require "util.uuid".generate;
20 21
21 module "plain" 22 module "plain"
22 23
23 --========================= 24 --=========================
24 --SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10 25 --SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10
69 local function scram_sha_1(self, message) 70 local function scram_sha_1(self, message)
70 if not self.state then self["state"] = {} end 71 if not self.state then self["state"] = {} end
71 72
72 if not self.state.name then 73 if not self.state.name then
73 -- we are processing client_first_message 74 -- we are processing client_first_message
74 self.state["name"] = string.match(client_first_message, "n=(.+),r=") 75 local client_first_message = message;
75 self.state["clientnonce"] = string.match(client_first_message, "r=([^,]+)") 76 self.state["name"] = client_first_message:match("n=(.+),r=")
77 self.state["clientnonce"] = client_first_message:match("r=([^,]+)")
76 78
77 self.state.name = validate_username(self.state.name); 79 self.state.name = validate_username(self.state.name);
78 if not self.state.name then 80 if not self.state.name or not self.state.clientnonce then
79 return "failure", "malformed-request"; 81 return "failure", "malformed-request";
80 end 82 end
83 self.state["servernonce"] = generate_uuid();
84 self.state["salt"] = generate_uuid();
85
86 local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..default_i;
87 return "challenge", server_first_message
81 else 88 else
82 -- we are processing client_final_message 89 -- we are processing client_final_message
90 local client_final_message = message;
91
92 self.state["proof"] = client_final_message:match("p=(.+)");
93 self.state["nonce"] = client_final_message:match("r=(.+),p=");
94 self.state["channelbinding"] = client_final_message:match("c=(.+),r=");
95 if not self.state.proof or not self.state.nonce or not self.state.channelbinding then
96 return "failure", "malformed-request";
97 end
98
99 local password;
100 if self.profile.plain then
101 password, state = self.profile.plain(self.state.name, self.realm)
102 if state == nil then return "failure", "not-authorized"
103 elseif state == false then return "failure", "account-disabled" end
104 end
105
106 local SaltedPassword = Hi(hmac_sha1, password, self.state.salt, default_i)
107 local ClientKey = hmac_sha1(SaltedPassword, "Client Key")
108 local ServerKey = hmac_sha1(SaltedPassword, "Server Key")
109 local StoredKey = sha1(ClientKey)
110 local AuthMessage = "n=" .. s_match(client_first_message,"n=(.+)") .. "," .. server_first_message .. "," .. s_match(client_final_message, "(.+),p=.+")
111 local ClientSignature = hmac_sha1(StoredKey, AuthMessage)
112 local ClientProof = binaryXOR(ClientKey, ClientSignature)
113 local ServerSignature = hmac_sha1(ServerKey, AuthMessage)
114
115 if base64.encode(ClientProof) == self.state.proof then
116 local server_final_message = "v="..base64.encode(ServerSignature);
117 return "success", server_final_message;
118 else
119 return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated.";
120 end
83 end 121 end
84 end 122 end
85 123
86 function init(registerMechanism) 124 function init(registerMechanism)
87 registerMechanism("SCRAM-SHA-1", {"plain"}, scram_sha_1); 125 registerMechanism("SCRAM-SHA-1", {"plain"}, scram_sha_1);