@@ -44,18 +44,20 @@ func NewKeyPair() (*KeyPair, error) {
4444
4545// security implements the CURVE security mechanism. 
4646type  security  struct  {
47- 	serverPubKey  [keySize ]byte  // Long-term server public key 
48- 	keys          * KeyPair        // Long-term client key pair (optional for client, required for server) 
49- 	asServer      bool           // True if this is a server 
47+ 	serverPubKey  [keySize ]byte                             // Long-term server public key 
48+ 	keys          func ( conn   * zmq4. Conn ) ( * KeyPair ,  error )  // Long-term client key pair (optional for client, required for server) 
49+ 	asServer      bool                                      // True if this is a server 
5050}
5151
5252// SecurityForClient returns a CURVE security mechanism for a client. 
5353// The client must know the server's public key. 
5454func  SecurityForClient (serverKey  [keySize ]byte , clientKeys  * KeyPair ) zmq4.Security  {
5555	sec  :=  & security {
5656		serverPubKey : serverKey ,
57- 		keys :         clientKeys ,
58- 		asServer :     false ,
57+ 		keys : func (_  * zmq4.Conn ) (* KeyPair , error ) {
58+ 			return  clientKeys , nil 
59+ 		},
60+ 		asServer : false ,
5961	}
6062	return  sec 
6163}
@@ -64,7 +66,19 @@ func SecurityForClient(serverKey [keySize]byte, clientKeys *KeyPair) zmq4.Securi
6466// The server must have its own key pair. 
6567func  SecurityForServer (serverKeys  * KeyPair ) zmq4.Security  {
6668	sec  :=  & security {
67- 		keys :     serverKeys ,
69+ 		keys : func (_  * zmq4.Conn ) (* KeyPair , error ) {
70+ 			return  serverKeys , nil 
71+ 		},
72+ 		asServer : true ,
73+ 	}
74+ 	return  sec 
75+ }
76+ 
77+ // SecurityForServerFunc returns a CURVE security mechanism for a server. 
78+ // The server must have its own key pair. 
79+ func  SecurityForServerFunc (getServerKeys  func (_  * zmq4.Conn ) (* KeyPair , error )) zmq4.Security  {
80+ 	sec  :=  & security {
81+ 		keys :     getServerKeys ,
6882		asServer : true ,
6983	}
7084	return  sec 
@@ -108,7 +122,12 @@ func (sec *security) clientHandshake(conn *zmq4.Conn, ephemeral *KeyPair) error
108122		return  fmt .Errorf ("security/curve: failed WELCOME: %w" , err )
109123	}
110124
111- 	err  =  sec .doInitiate (conn , servCookie , & nonce , secretKey , ephemeral )
125+ 	keys , err  :=  sec .keys (conn )
126+ 	if  err  !=  nil  {
127+ 		return  fmt .Errorf ("security/curve: could not generate keys: %w" , err )
128+ 	}
129+ 
130+ 	err  =  sec .doInitiate (conn , servCookie , & nonce , keys , secretKey , ephemeral )
112131	if  err  !=  nil  {
113132		return  fmt .Errorf ("security/curve: failed INITIATE: %w" , err )
114133	}
@@ -136,7 +155,13 @@ func (sec *security) clientHandshake(conn *zmq4.Conn, ephemeral *KeyPair) error
136155func  (sec  * security ) serverHandshake (conn  * zmq4.Conn ) error  {
137156	var  nonce  Nonce 
138157	var  cookieKey  [32 ]byte 
139- 	clientTransPubKey , err  :=  sec .doServerHello (& nonce , conn )
158+ 
159+ 	keys , err  :=  sec .keys (conn )
160+ 	if  err  !=  nil  {
161+ 		return  fmt .Errorf ("security/curve: could not generate keys: %w" , err )
162+ 	}
163+ 
164+ 	clientTransPubKey , err  :=  sec .doServerHello (& nonce , conn , keys )
140165	if  err  !=  nil  {
141166		return  fmt .Errorf ("security/curve: Client hello failed: %w" , err )
142167	}
@@ -145,7 +170,7 @@ func (sec *security) serverHandshake(conn *zmq4.Conn) error {
145170	if  err  !=  nil  {
146171		panic (fmt .Sprintf ("Failed creaing cookie key: %s" , err .Error ()))
147172	}
148- 	err  =  sec .doServerWelcome (& nonce , conn , & clientTransPubKey , & cookieKey , kp )
173+ 	err  =  sec .doServerWelcome (& nonce , conn , keys ,  & clientTransPubKey , & cookieKey , kp )
149174	if  err  !=  nil  {
150175		return  fmt .Errorf ("security/curve: Failed sending welcome: %w" , err )
151176	}
@@ -266,7 +291,7 @@ func (sec *security) doWelcome(nonce *Nonce, conn *zmq4.Conn, ephemeral *KeyPair
266291	return  welcomeBox [32 :], & secretKey , nil 
267292}
268293
269- func  (sec  * security ) doInitiate (conn  * zmq4.Conn , servCookie  []byte , nonce  * Nonce , secretKey  * [32 ]byte , ephemeral  * KeyPair ) error  {
294+ func  (sec  * security ) doInitiate (conn  * zmq4.Conn , servCookie  []byte , nonce  * Nonce , keys   * KeyPair ,  secretKey  * [32 ]byte , ephemeral  * KeyPair ) error  {
270295	meta , err  :=  conn .Meta .MarshalZMTP ()
271296	if  err  !=  nil  {
272297		return  fmt .Errorf ("security/curve: could not marshal metadata: %w" , err )
@@ -281,10 +306,10 @@ func (sec *security) doInitiate(conn *zmq4.Conn, servCookie []byte, nonce *Nonce
281306	copy (vouch , ephemeral .Public [:])
282307	copy (vouch [32 :], sec .serverPubKey [:])
283308	vouchBox  :=  make ([]byte , 80 )
284- 	box .Seal (vouchBox [0 :0 ], vouch , nonce .N (), secretKey , & sec . keys .Private )
309+ 	box .Seal (vouchBox [0 :0 ], vouch , nonce .N (), secretKey , & keys .Private )
285310
286311	initBox  :=  make ([]byte , 128 + len (meta ))
287- 	copy (initBox , sec . keys .Public [:])
312+ 	copy (initBox , keys .Public [:])
288313	copy (initBox [32 :48 ], nonce [8 :])
289314	copy (initBox [48 :128 ], vouchBox )
290315	copy (initBox [128 :], meta )
@@ -317,7 +342,7 @@ func (sec *security) doReady(conn *zmq4.Conn, nonce *Nonce, secretKey *[32]byte,
317342	return  servMeta , nil 
318343}
319344
320- func  (sec  * security ) doServerHello (nonce  * Nonce , conn  * zmq4.Conn ) (clientTransPubKey  [32 ]byte , err  error ) {
345+ func  (sec  * security ) doServerHello (nonce  * Nonce , conn  * zmq4.Conn ,  keys   * KeyPair ) (clientTransPubKey  [32 ]byte , err  error ) {
321346	cmd , err  :=  conn .RecvCmd ()
322347	if  err  !=  nil  {
323348		return  clientTransPubKey , err 
@@ -343,7 +368,7 @@ func (sec *security) doServerHello(nonce *Nonce, conn *zmq4.Conn) (clientTransPu
343368		return 
344369	}
345370	var  out  [64 ]byte 
346- 	_ , ok  :=  box .Open (out [0 :0 ], cmd .Body [114 :], nonce .N (), & clientTransPubKey , & sec . keys .Private )
371+ 	_ , ok  :=  box .Open (out [0 :0 ], cmd .Body [114 :], nonce .N (), & clientTransPubKey , & keys .Private )
347372	if  ! ok  {
348373		err  =  fmt .Errorf ("security/curve: Invalid signature in hello command" )
349374		return 
@@ -358,7 +383,7 @@ func (sec *security) doServerHello(nonce *Nonce, conn *zmq4.Conn) (clientTransPu
358383	return 
359384}
360385
361- func  (sec  * security ) doServerWelcome (nonce  * Nonce , conn  * zmq4.Conn , clientTransPubKey , cookieKey  * [32 ]byte , kp  * KeyPair ) error  {
386+ func  (sec  * security ) doServerWelcome (nonce  * Nonce , conn  * zmq4.Conn , keys   * KeyPair ,  clientTransPubKey , cookieKey  * [32 ]byte , kp  * KeyPair ) error  {
362387	welcomeBody  :=  make ([]byte , 160 )
363388	var  cookie  [64 ]byte 
364389	copy (cookie [:], clientTransPubKey [:])
@@ -375,7 +400,7 @@ func (sec *security) doServerWelcome(nonce *Nonce, conn *zmq4.Conn, clientTransP
375400	copy (welcomeBox [32 :], cookieData )
376401	nonce .Long ("WELCOME-" )
377402	copy (welcomeBody , nonce [8 :])
378- 	box .Seal (welcomeBody [16 :16 ], welcomeBox , nonce .N (), clientTransPubKey , & sec . keys .Private )
403+ 	box .Seal (welcomeBody [16 :16 ], welcomeBox , nonce .N (), clientTransPubKey , & keys .Private )
379404	return  conn .SendCmd (zmq4 .CmdWelcome , welcomeBody )
380405}
381406
0 commit comments