mirror of
				https://github.com/zeromq/libzmq.git
				synced 2025-10-30 21:50:49 +01:00 
			
		
		
		
	Merge pull request #597 from hintjens/master
Problem: working with binary keys is painful
This commit is contained in:
		| @@ -1,12 +1,12 @@ | ||||
| ACLOCAL_AMFLAGS = -I config | ||||
|  | ||||
| if BUILD_PGM | ||||
| SUBDIRS = foreign/openpgm src doc perf tests | ||||
| SUBDIRS = foreign/openpgm src doc perf tests tools | ||||
| else | ||||
| SUBDIRS = src doc perf tests | ||||
| SUBDIRS = src doc perf tests tools | ||||
| endif | ||||
|  | ||||
| DIST_SUBDIRS = foreign/openpgm src doc perf tests builds/msvc | ||||
| DIST_SUBDIRS = foreign/openpgm src doc perf tests tools builds/msvc | ||||
|  | ||||
| EXTRA_DIST = \ | ||||
| 	autogen.sh	\ | ||||
|   | ||||
							
								
								
									
										12
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -428,10 +428,14 @@ AC_SUBST(LIBZMQ_EXTRA_CFLAGS) | ||||
| AC_SUBST(LIBZMQ_EXTRA_CXXFLAGS) | ||||
| AC_SUBST(LIBZMQ_EXTRA_LDFLAGS) | ||||
|  | ||||
| AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile | ||||
|     perf/Makefile src/libzmq.pc \ | ||||
|     builds/msvc/Makefile tests/Makefile \ | ||||
| AC_CONFIG_FILES([Makefile \ | ||||
|     src/Makefile \ | ||||
|     src/libzmq.pc \ | ||||
|     doc/Makefile \ | ||||
|     perf/Makefile \ | ||||
|     tests/Makefile \ | ||||
|     tools/Makefile \ | ||||
|     builds/msvc/Makefile \ | ||||
|     foreign/openpgm/Makefile \ | ||||
|     builds/redhat/zeromq.spec]) | ||||
| AC_OUTPUT | ||||
|  | ||||
|   | ||||
| @@ -37,21 +37,43 @@ long-term key pair. | ||||
| If the server does authentication it will be based on the client's long | ||||
| term public key. | ||||
|  | ||||
| KEY ENCODING | ||||
| ------------ | ||||
| The standard representation for keys in source code is either 32 bytes of | ||||
| base 256 (binary) data, or 40 characters of base 85 data encoded using the | ||||
| Z85 algorithm defined by http://rfc.zeromq.org/spec:32. | ||||
|  | ||||
| The Z85 algorithm is designed to produce printable key strings for use in | ||||
| configuration files, the command line, and code. There is a reference | ||||
| implementation in C at https://github.com/zeromq/rfc/tree/master/src. | ||||
|  | ||||
|      | ||||
| TEST KEY VALUES | ||||
| --------------- | ||||
|  | ||||
| For test cases, the client shall use this long-term key pair: | ||||
| For test cases, the client shall use this long-term key pair (specified | ||||
| as hexadecimal and in Z85): | ||||
|  | ||||
| ---- | ||||
| public: BB88471D65E2659B30C55A5321CEBB5AAB2B70A398645C26DCA2B2FCB43FC518 | ||||
| secret: 7BB864B489AFA3671FBE69101F94B38972F24816DFB01B51656B3FEC8DFD0888 | ||||
| public:  | ||||
|     BB88471D65E2659B30C55A5321CEBB5AAB2B70A398645C26DCA2B2FCB43FC518 | ||||
|     Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID | ||||
|  | ||||
| secret:  | ||||
|     7BB864B489AFA3671FBE69101F94B38972F24816DFB01B51656B3FEC8DFD0888 | ||||
|     D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs | ||||
| ---- | ||||
|  | ||||
| And the server shall use this long-term key pair: | ||||
| And the server shall use this long-term key pair (specified as hexadecimal  | ||||
| and in Z85): | ||||
|  | ||||
| ---- | ||||
| public: 54FCBA24E93249969316FB617C872BB0C1D1FF14800427C594CBFACF1BC2D652 | ||||
| secret: 8E0BDD697628B91D8F245587EE95C5B04D48963F79259877B49CD9063AEAD3B7 | ||||
| public:  | ||||
|     54FCBA24E93249969316FB617C872BB0C1D1FF14800427C594CBFACF1BC2D652 | ||||
|     rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7 | ||||
|  | ||||
| secret:  | ||||
|     8E0BDD697628B91D8F245587EE95C5B04D48963F79259877B49CD9063AEAD3B7 | ||||
|     JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6 | ||||
| ---- | ||||
|  | ||||
| SEE ALSO | ||||
|   | ||||
| @@ -486,8 +486,8 @@ Default value:: -1 (leave to OS default) | ||||
| Applicable socket types:: all, when using TCP transports. | ||||
|  | ||||
|  | ||||
| ZMQ_MECHANISM: Retrieve the current security mechanism | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| ZMQ_MECHANISM: Retrieve current security mechanism | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| The 'ZMQ_MECHANISM' option shall retrieve the current security mechanism | ||||
| for the socket. | ||||
|  | ||||
| @@ -498,8 +498,8 @@ Default value:: ZMQ_NULL | ||||
| Applicable socket types:: all, when using TCP or IPC transports | ||||
|  | ||||
|  | ||||
| ZMQ_PLAIN_SERVER: Retrieve the PLAIN server role | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| ZMQ_PLAIN_SERVER: Retrieve current PLAIN server role | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| Returns the 'ZMQ_PLAIN_SERVER' option, if any, previously set on the socket. | ||||
|  | ||||
| [horizontal] | ||||
| @@ -509,8 +509,8 @@ Default value:: int | ||||
| Applicable socket types:: all, when using TCP or IPC transports | ||||
|  | ||||
|  | ||||
| ZMQ_PLAIN_USERNAME: Retrieve the last username set | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| ZMQ_PLAIN_USERNAME: Retrieve current PLAIN username | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| The 'ZMQ_PLAIN_USERNAME' option shall retrieve the last username set for | ||||
| the PLAIN security mechanism. The returned value shall be a NULL-terminated  | ||||
| string and MAY be empty. The returned size SHALL include the terminating | ||||
| @@ -523,8 +523,8 @@ Default value:: null string | ||||
| Applicable socket types:: all, when using TCP or IPC transports | ||||
|  | ||||
|  | ||||
| ZMQ_PLAIN_PASSWORD: Retrieve the last password set | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| ZMQ_PLAIN_PASSWORD: Retrieve current password | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| The 'ZMQ_PLAIN_PASSWORD' option shall retrieve the last password set for | ||||
| the PLAIN security mechanism. The returned value shall be a NULL-terminated  | ||||
| string and MAY be empty. The returned size SHALL include the terminating | ||||
| @@ -537,6 +537,48 @@ Default value:: null string | ||||
| Applicable socket types:: all, when using TCP or IPC transports | ||||
|  | ||||
|  | ||||
| ZMQ_CURVE_PUBLICKEY: Retrieve current CURVE public key | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Retrieves the current long term public key for the socket. You can | ||||
| provide either a 32 byte buffer, to retrieve the binary key value, or  | ||||
| a 40 byte buffer, to retrieve the key in a printable Z85 format. | ||||
|  | ||||
| [horizontal] | ||||
| Option value type:: binary data or Z85 text string | ||||
| Option value size:: 32 or 40 | ||||
| Default value:: null | ||||
| Applicable socket types:: all, when using TCP transport | ||||
|  | ||||
|  | ||||
| ZMQ_CURVE_SECRETKEY: Retrieve current CURVE secret key | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Retrieves the current long term secret key for the socket. You can | ||||
| provide either a 32 byte buffer, to retrieve the binary key value, or  | ||||
| a 40 byte buffer, to retrieve the key in a printable Z85 format. | ||||
|  | ||||
| [horizontal] | ||||
| Option value type:: binary data or Z85 text string | ||||
| Option value size:: 32 or 40 | ||||
| Default value:: null | ||||
| Applicable socket types:: all, when using TCP transport | ||||
|  | ||||
|  | ||||
| ZMQ_CURVE_SERVERKEY: Retrieve current CURVE server key | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Retrieves the current server key for the client socket. You can | ||||
| provide either a 32 byte buffer, to retrieve the binary key value, or  | ||||
| a 40 byte buffer, to retrieve the key in a printable Z85 format. | ||||
|  | ||||
| [horizontal] | ||||
| Option value type:: binary data or Z85 text string | ||||
| Option value size:: 32 or 40 | ||||
| Default value:: null | ||||
| Applicable socket types:: all, when using TCP transport | ||||
|  | ||||
|  | ||||
| RETURN VALUE | ||||
| ------------ | ||||
| The _zmq_getsockopt()_ function shall return zero if successful. Otherwise it | ||||
|   | ||||
| @@ -596,13 +596,17 @@ ZMQ_CURVE_PUBLICKEY: Set CURVE public key | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Sets the socket's long term public key. You must set this on a CURVE | ||||
| client or server socket, see linkzmq:zmq_curve[7]. The key is 32 bytes. | ||||
| For servers, it must be persisted and shared through some unspecified | ||||
| secure mechanism to clients. | ||||
| client or server socket, see linkzmq:zmq_curve[7]. You can provide the | ||||
| key as 32 binary bytes, or as a 40-character string encoded in the Z85 | ||||
| encoding format. For servers, the public key must be persisted and  | ||||
| shared through some unspecified but secure mechanism to clients. The | ||||
| public key must always be used with the matching secret key generated | ||||
| at the same time. To generate a public/secret key pair, use the  | ||||
| tools/curve_keygen tool. | ||||
|  | ||||
| [horizontal] | ||||
| Option value type:: binary data | ||||
| Option value size:: 32 | ||||
| Option value type:: binary data or Z85 text string | ||||
| Option value size:: 32 or 40 | ||||
| Default value:: NULL | ||||
| Applicable socket types:: all, when using TCP transport | ||||
|  | ||||
| @@ -611,11 +615,13 @@ ZMQ_CURVE_SECRETKEY: Set CURVE secret key | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Sets the socket's long term secret key. You must set this on a CURVE | ||||
| client socket, see linkzmq:zmq_curve[7]. The key is 32 bytes. | ||||
| client socket, see linkzmq:zmq_curve[7]. You can provide the key as  | ||||
| 32 binary bytes, or as a 40-character string encoded in the Z85 encoding  | ||||
| format.  | ||||
|  | ||||
| [horizontal] | ||||
| Option value type:: binary data | ||||
| Option value size:: 32 | ||||
| Option value type:: binary data or Z85 text string | ||||
| Option value size:: 32 or 40 | ||||
| Default value:: NULL | ||||
| Applicable socket types:: all, when using TCP transport | ||||
|  | ||||
| @@ -624,12 +630,14 @@ ZMQ_CURVE_SERVERKEY: Set CURVE server key | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Sets the socket's long term server key. You must set this on a CURVE | ||||
| client socket, see linkzmq:zmq_curve[7]. The key is 32 bytes. This | ||||
| key must be the same as the public key set on the server socket. | ||||
| client socket, see linkzmq:zmq_curve[7]. You can provide the key as  | ||||
| 32 binary bytes, or as a 40-character string encoded in the Z85 encoding  | ||||
| format. This key must be the same as the public key set on the server  | ||||
| socket. | ||||
|  | ||||
| [horizontal] | ||||
| Option value type:: binary data | ||||
| Option value size:: 32 | ||||
| Option value type:: binary data or Z85 text string | ||||
| Option value size:: 32 or 40 | ||||
| Default value:: NULL | ||||
| Applicable socket types:: all, when using TCP transport | ||||
|  | ||||
|   | ||||
| @@ -89,6 +89,7 @@ libzmq_la_SOURCES = \ | ||||
|     xsub.hpp \ | ||||
|     ypipe.hpp \ | ||||
|     yqueue.hpp \ | ||||
|     z85_codec.hpp \ | ||||
|     address.cpp \ | ||||
|     clock.cpp \ | ||||
|     ctx.cpp \ | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
|  | ||||
| #include "options.hpp" | ||||
| #include "err.hpp" | ||||
| #include "z85_codec.hpp" | ||||
|  | ||||
| zmq::options_t::options_t () : | ||||
|     sndhwm (1000), | ||||
| @@ -285,7 +286,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, | ||||
|             } | ||||
|             break; | ||||
|          | ||||
| //  If libsodium isn't installed, these options provoke EINVAL | ||||
|         //  If libsodium isn't installed, these options provoke EINVAL | ||||
| #       ifdef HAVE_LIBSODIUM | ||||
|         case ZMQ_CURVE_SERVER: | ||||
|             if (is_int && (value == 0 || value == 1)) { | ||||
| @@ -301,6 +302,12 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, | ||||
|                 mechanism = ZMQ_CURVE; | ||||
|                 return 0; | ||||
|             } | ||||
|             else | ||||
|             if (optvallen_ == CURVE_KEYSIZE_Z85) { | ||||
|                 Z85_decode (curve_public_key, (char *) optval_); | ||||
|                 mechanism = ZMQ_CURVE; | ||||
|                 return 0; | ||||
|             } | ||||
|             break; | ||||
|              | ||||
|         case ZMQ_CURVE_SECRETKEY: | ||||
| @@ -309,6 +316,12 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, | ||||
|                 mechanism = ZMQ_CURVE; | ||||
|                 return 0; | ||||
|             } | ||||
|             else | ||||
|             if (optvallen_ == CURVE_KEYSIZE_Z85) { | ||||
|                 Z85_decode (curve_secret_key, (char *) optval_); | ||||
|                 mechanism = ZMQ_CURVE; | ||||
|                 return 0; | ||||
|             } | ||||
|             break; | ||||
|              | ||||
|         case ZMQ_CURVE_SERVERKEY: | ||||
| @@ -318,6 +331,13 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, | ||||
|                 mechanism = ZMQ_CURVE; | ||||
|                 return 0; | ||||
|             } | ||||
|             else | ||||
|             if (optvallen_ == CURVE_KEYSIZE_Z85) { | ||||
|                 Z85_decode (curve_server_key, (char *) optval_); | ||||
|                 as_server = 0; | ||||
|                 mechanism = ZMQ_CURVE; | ||||
|                 return 0; | ||||
|             } | ||||
|             break; | ||||
| #       endif | ||||
|     } | ||||
| @@ -531,7 +551,7 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) | ||||
|             } | ||||
|             break; | ||||
|              | ||||
| //  If libsodium isn't installed, these options provoke EINVAL | ||||
|         //  If libsodium isn't installed, these options provoke EINVAL | ||||
| #       ifdef HAVE_LIBSODIUM | ||||
|         case ZMQ_CURVE_SERVER: | ||||
|             if (is_int) { | ||||
| @@ -545,6 +565,11 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) | ||||
|                 memcpy (optval_, curve_public_key, CURVE_KEYSIZE); | ||||
|                 return 0; | ||||
|             } | ||||
|             else | ||||
|             if (*optvallen_ == CURVE_KEYSIZE_Z85) { | ||||
|                 Z85_encode ((char *) optval_, curve_public_key, CURVE_KEYSIZE); | ||||
|                 return 0; | ||||
|             } | ||||
|             break; | ||||
|              | ||||
|         case ZMQ_CURVE_SECRETKEY: | ||||
| @@ -552,6 +577,11 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) | ||||
|                 memcpy (optval_, curve_secret_key, CURVE_KEYSIZE); | ||||
|                 return 0; | ||||
|             } | ||||
|             else | ||||
|             if (*optvallen_ == CURVE_KEYSIZE_Z85) { | ||||
|                 Z85_encode ((char *) optval_, curve_secret_key, CURVE_KEYSIZE); | ||||
|                 return 0; | ||||
|             } | ||||
|             break; | ||||
|              | ||||
|         case ZMQ_CURVE_SERVERKEY: | ||||
| @@ -559,6 +589,11 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_) | ||||
|                 memcpy (optval_, curve_server_key, CURVE_KEYSIZE); | ||||
|                 return 0; | ||||
|             } | ||||
|             else | ||||
|             if (*optvallen_ == CURVE_KEYSIZE_Z85) { | ||||
|                 Z85_encode ((char *) optval_, curve_server_key, CURVE_KEYSIZE); | ||||
|                 return 0; | ||||
|             } | ||||
|             break; | ||||
| #       endif | ||||
|     } | ||||
|   | ||||
| @@ -28,7 +28,10 @@ | ||||
| #include "tcp_address.hpp" | ||||
| #include "../include/zmq.h" | ||||
|  | ||||
| #define CURVE_KEYSIZE    32 | ||||
| //  Normal base 256 key is 32 bytes | ||||
| #define CURVE_KEYSIZE       32 | ||||
| //  Key encoded using Z85 is 40 bytes | ||||
| #define CURVE_KEYSIZE_Z85   40 | ||||
|  | ||||
| namespace zmq | ||||
| { | ||||
|   | ||||
							
								
								
									
										108
									
								
								src/z85_codec.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/z85_codec.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| /* | ||||
|     Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file | ||||
|  | ||||
|     This file is part of 0MQ. | ||||
|  | ||||
|     0MQ is free software; you can redistribute it and/or modify it under | ||||
|     the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation; either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     0MQ is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
|  | ||||
| //  Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding | ||||
|  | ||||
| #ifndef __ZMQ_Z85_CODEC_HPP_INCLUDED__ | ||||
| #define __ZMQ_Z85_CODEC_HPP_INCLUDED__ | ||||
|  | ||||
| //  Maps base 256 to base 85 | ||||
| static char encoder [85 + 1] = { | ||||
|     "0123456789" "abcdefghij" "klmnopqrst" "uvwxyzABCD" | ||||
|     "EFGHIJKLMN" "OPQRSTUVWX" "YZ.-:+=^!/" "*?&<>()[]{"  | ||||
|     "}@%$#" | ||||
| }; | ||||
|  | ||||
| //  Maps base 85 to base 256 | ||||
| //  We chop off lower 32 and higher 128 ranges | ||||
| static uint8_t decoder [96] = { | ||||
|     0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,  | ||||
|     0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,  | ||||
|     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | ||||
|     0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,  | ||||
|     0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,  | ||||
|     0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,  | ||||
|     0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,  | ||||
|     0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,  | ||||
|     0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,  | ||||
|     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,  | ||||
|     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,  | ||||
|     0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 | ||||
| }; | ||||
|  | ||||
| //  -------------------------------------------------------------------------- | ||||
| //  Encode a binary frame as a string; destination string MUST be at least | ||||
| //  size * 5 / 4 bytes long. Returns dest. Size must be a multiple of 4. | ||||
|  | ||||
| char * | ||||
| Z85_encode (char *dest, uint8_t *data, size_t size) | ||||
| { | ||||
|     assert (size % 4 == 0); | ||||
|     uint char_nbr = 0; | ||||
|     uint byte_nbr = 0; | ||||
|     uint32_t value = 0; | ||||
|     while (byte_nbr < size) { | ||||
|         //  Accumulate value in base 256 (binary) | ||||
|         value = value * 256 + data [byte_nbr++]; | ||||
|         if (byte_nbr % 4 == 0) { | ||||
|             //  Output value in base 85 | ||||
|             uint divisor = 85 * 85 * 85 * 85; | ||||
|             while (divisor) { | ||||
|                 dest [char_nbr++] = encoder [value / divisor % 85]; | ||||
|                 divisor /= 85; | ||||
|             } | ||||
|             value = 0; | ||||
|         } | ||||
|     } | ||||
|     assert (char_nbr == size * 5 / 4); | ||||
|     dest [char_nbr] = 0; | ||||
|     return dest; | ||||
| } | ||||
|  | ||||
|      | ||||
| //  -------------------------------------------------------------------------- | ||||
| //  Decode an encoded string into a binary frame; dest must be at least | ||||
| //  strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)  | ||||
| //  must be a multiple of 5. | ||||
|  | ||||
| uint8_t * | ||||
| Z85_decode (uint8_t *dest, char *string) | ||||
| { | ||||
|     assert (strlen (string) % 5 == 0); | ||||
|     uint byte_nbr = 0; | ||||
|     uint char_nbr = 0; | ||||
|     uint32_t value = 0; | ||||
|     while (char_nbr < strlen (string)) { | ||||
|         //  Accumulate value in base 85 | ||||
|         value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32]; | ||||
|         if (char_nbr % 5 == 0) { | ||||
|             //  Output value in base 256 | ||||
|             uint divisor = 256 * 256 * 256; | ||||
|             while (divisor) { | ||||
|                 dest [byte_nbr++] = value / divisor % 256; | ||||
|                 divisor /= 256; | ||||
|             } | ||||
|             value = 0; | ||||
|         } | ||||
|     } | ||||
|     assert (byte_nbr == strlen (string) * 4 / 5); | ||||
|     return dest; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -56,7 +56,7 @@ zap_handler (void *zap) | ||||
| int main (void) | ||||
| { | ||||
| #ifndef HAVE_LIBSODIUM | ||||
|     printf("libsodium not installed, skipping CURVE test\n"); | ||||
|     printf ("libsodium not installed, skipping CURVE test\n"); | ||||
|     return 0; | ||||
| #endif | ||||
|     int rc; | ||||
| @@ -75,43 +75,24 @@ int main (void) | ||||
|     void *client = zmq_socket (ctx, ZMQ_DEALER); | ||||
|     assert (client); | ||||
|  | ||||
|     //  Test keys from the zmq_curve man page | ||||
|     char client_public [] = "Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID"; | ||||
|     char client_secret [] = "D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs"; | ||||
|     char server_public [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7"; | ||||
|     char server_secret [] = "JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6"; | ||||
|          | ||||
|     as_server = 1; | ||||
|     rc = zmq_setsockopt(server, ZMQ_CURVE_SERVER, &as_server, sizeof(int)); | ||||
|     // Test key from the zmq_curve man page. | ||||
|     uint8_t server_secret[32] = { | ||||
|       0x8E, 0x0B, 0xDD, 0x69, 0x76, 0x28, 0xB9, 0x1D, 0x8F, 0x24, | ||||
|       0x55, 0x87, 0xEE, 0x95, 0xC5, 0xB0, 0x4D, 0x48, 0x96, 0x3F, | ||||
|       0x79, 0x25, 0x98, 0x77, 0xB4, 0x9C, 0xD9, 0x06, 0x3A, 0xEA,  | ||||
|       0xD3, 0xB7   | ||||
|     }; | ||||
|     rc = zmq_setsockopt(server, ZMQ_CURVE_SECRETKEY, server_secret, sizeof(server_secret)); | ||||
|     assert(rc == 0); | ||||
|     rc = zmq_setsockopt (server, ZMQ_CURVE_SERVER, &as_server, sizeof (int)); | ||||
|     assert (rc == 0); | ||||
|     rc = zmq_setsockopt (server, ZMQ_CURVE_SECRETKEY, server_secret, 40); | ||||
|     assert (rc == 0); | ||||
|  | ||||
|     // Test client keys from the zmq_curve man page. | ||||
|     uint8_t server_public[32] = { | ||||
|         0x54, 0xFC, 0xBA, 0x24, 0xE9, 0x32, 0x49, 0x96, 0x93, 0x16, | ||||
|         0xFB, 0x61, 0x7C, 0x87, 0x2B, 0xB0, 0xC1, 0xD1, 0xFF, 0x14, | ||||
|         0x80, 0x04, 0x27, 0xC5, 0x94, 0xCB, 0xFA, 0xCF, 0x1B, 0xC2, | ||||
|         0xD6, 0x52 | ||||
|     }; | ||||
|     rc = zmq_setsockopt(client, ZMQ_CURVE_SERVERKEY, server_public, sizeof(server_public)); | ||||
|     assert(rc == 0); | ||||
|     uint8_t client_public[32] = { | ||||
|         0xBB, 0x88, 0x47, 0x1D, 0x65, 0xE2, 0x65, 0x9B, 0x30, 0xC5, | ||||
|         0x5A, 0x53, 0x21, 0xCE, 0xBB, 0x5A, 0xAB, 0x2B, 0x70, 0xA3, | ||||
|         0x98, 0x64, 0x5C, 0x26, 0xDC, 0xA2, 0xB2, 0xFC, 0xB4, 0x3F, | ||||
|         0xC5, 0x18 | ||||
|     }; | ||||
|     rc = zmq_setsockopt(client, ZMQ_CURVE_PUBLICKEY, client_public, sizeof(client_public)); | ||||
|     assert(rc == 0); | ||||
|     uint8_t client_secret[32] = { | ||||
|         0x7B, 0xB8, 0x64, 0xB4, 0x89, 0xAF, 0xA3, 0x67, 0x1F, 0xBE, | ||||
|         0x69, 0x10, 0x1F, 0x94, 0xB3, 0x89, 0x72, 0xF2, 0x48, 0x16, | ||||
|         0xDF, 0xB0, 0x1B, 0x51, 0x65, 0x6B, 0x3F, 0xEC, 0x8D, 0xFD, | ||||
|         0x08, 0x88 | ||||
|     }; | ||||
|     rc = zmq_setsockopt(client, ZMQ_CURVE_SECRETKEY, client_secret, sizeof(client_secret)); | ||||
|     assert(rc == 0); | ||||
|     rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40); | ||||
|     assert (rc == 0); | ||||
|     rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40); | ||||
|     assert (rc == 0); | ||||
|     rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40); | ||||
|     assert (rc == 0); | ||||
|  | ||||
|     // Test the client and server both have the right mechanism. | ||||
|     optsize = sizeof (int); | ||||
|   | ||||
							
								
								
									
										1
									
								
								tools/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tools/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| EXTRA_DIST = curve_keygen.c z85_codec.h | ||||
| @@ -3,6 +3,16 @@ | ||||
|  | ||||
|     This file is part of 0MQ. | ||||
|  | ||||
|     This tool generates a keypair for the libzmq CURVE security mechanism,  | ||||
|     and encodes the keypair to give two printable strings that you can use  | ||||
|     in configuration files or source code. The encoding uses Z85, which is  | ||||
|     a base-85 format that is described in 0MQ RFC 32, and which has an  | ||||
|     implementation in the Z85.c source used by this tool. The keypair  | ||||
|     always works with the secret key held by one party and the public key  | ||||
|     distributed (securely!) to peers wishing to connect to it. CURVE is  | ||||
|     defined by http://rfc.zeromq.org/spec:25. Z85 is defined by  | ||||
|     http://rfc.zeromq.org/spec:32. | ||||
|  | ||||
|     0MQ is free software; you can redistribute it and/or modify it under | ||||
|     the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation; either version 3 of the License, or | ||||
| @@ -21,6 +31,7 @@ | ||||
| #include <stdlib.h> | ||||
| #include <assert.h> | ||||
| #include <sodium.h> | ||||
| #include "z85_codec.h" | ||||
|  | ||||
| int main (void) | ||||
| { | ||||
| @@ -28,20 +39,31 @@ int main (void) | ||||
|     || crypto_box_SECRETKEYBYTES != 32 | ||||
| #   error "libsodium not built correctly" | ||||
| #   endif | ||||
|      | ||||
|     puts ("This tool generates a keypair for the libzmq CURVE security mechanism,"); | ||||
|     puts ("and encodes the keypair to give two printable strings that you can use"); | ||||
|     puts ("in configuration files or source code. The encoding uses Z85, which is"); | ||||
|     puts ("a base-85 format that is described in 0MQ RFC 32, and which has an"); | ||||
|     puts ("implementation in the Z85.c source used by this tool. The keypair"); | ||||
|     puts ("always works with the secret key held by one party and the public key"); | ||||
|     puts ("distributed (securely!) to peers wishing to connect to it. CURVE is"); | ||||
|     puts ("defined by http://rfc.zeromq.org/spec:25. Z85 is defined by"); | ||||
|     puts ("http://rfc.zeromq.org/spec:32."); | ||||
|  | ||||
|     uint8_t public_key [32]; | ||||
|     uint8_t secret_key [32]; | ||||
|  | ||||
|     int rc = crypto_box_keypair (public_key, secret_key); | ||||
|     assert (rc == 0); | ||||
|     int byte_nbr; | ||||
|     printf ("public: "); | ||||
|     for (byte_nbr = 0; byte_nbr < 32; byte_nbr++)  | ||||
|         printf ("%02X", public_key [byte_nbr]); | ||||
|     printf ("\n"); | ||||
|     printf ("secret: "); | ||||
|     for (byte_nbr = 0; byte_nbr < 32; byte_nbr++)  | ||||
|         printf ("%02X", secret_key [byte_nbr]); | ||||
|     printf ("\n"); | ||||
|      | ||||
|     char encoded [40]; | ||||
|     Z85_encode (encoded, public_key, 32); | ||||
|     puts ("\n== CURVE PUBLIC KEY =="); | ||||
|     puts (encoded); | ||||
|      | ||||
|     Z85_encode (encoded, secret_key, 32); | ||||
|     puts ("\n== CURVE SECRET KEY =="); | ||||
|     puts (encoded); | ||||
|  | ||||
|     exit (0); | ||||
| } | ||||
|   | ||||
							
								
								
									
										108
									
								
								tools/z85_codec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								tools/z85_codec.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| /* | ||||
|     Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file | ||||
|  | ||||
|     This file is part of 0MQ. | ||||
|  | ||||
|     0MQ is free software; you can redistribute it and/or modify it under | ||||
|     the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation; either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     0MQ is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
|  | ||||
| //  Z85 codec, taken from 0MQ RFC project, implements RFC32 Z85 encoding | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| //  Maps base 256 to base 85 | ||||
| static char encoder [85 + 1] = { | ||||
|     "0123456789" "abcdefghij" "klmnopqrst" "uvwxyzABCD" | ||||
|     "EFGHIJKLMN" "OPQRSTUVWX" "YZ.-:+=^!/" "*?&<>()[]{"  | ||||
|     "}@%$#" | ||||
| }; | ||||
|  | ||||
| //  Maps base 85 to base 256 | ||||
| //  We chop off lower 32 and higher 128 ranges | ||||
| static uint8_t decoder [96] = { | ||||
|     0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,  | ||||
|     0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,  | ||||
|     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | ||||
|     0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,  | ||||
|     0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,  | ||||
|     0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,  | ||||
|     0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,  | ||||
|     0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,  | ||||
|     0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,  | ||||
|     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,  | ||||
|     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,  | ||||
|     0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 | ||||
| }; | ||||
|  | ||||
| //  -------------------------------------------------------------------------- | ||||
| //  Encode a binary frame as a string; destination string MUST be at least | ||||
| //  size * 5 / 4 bytes long. Returns dest. Size must be a multiple of 4. | ||||
|  | ||||
| char * | ||||
| Z85_encode (char *dest, uint8_t *data, size_t size) | ||||
| { | ||||
|     assert (size % 4 == 0); | ||||
|     uint char_nbr = 0; | ||||
|     uint byte_nbr = 0; | ||||
|     uint32_t value = 0; | ||||
|     while (byte_nbr < size) { | ||||
|         //  Accumulate value in base 256 (binary) | ||||
|         value = value * 256 + data [byte_nbr++]; | ||||
|         if (byte_nbr % 4 == 0) { | ||||
|             //  Output value in base 85 | ||||
|             uint divisor = 85 * 85 * 85 * 85; | ||||
|             while (divisor) { | ||||
|                 dest [char_nbr++] = encoder [value / divisor % 85]; | ||||
|                 divisor /= 85; | ||||
|             } | ||||
|             value = 0; | ||||
|         } | ||||
|     } | ||||
|     assert (char_nbr == size * 5 / 4); | ||||
|     dest [char_nbr] = 0; | ||||
|     return dest; | ||||
| } | ||||
|  | ||||
|      | ||||
| //  -------------------------------------------------------------------------- | ||||
| //  Decode an encoded string into a binary frame; dest must be at least | ||||
| //  strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)  | ||||
| //  must be a multiple of 5. | ||||
|  | ||||
| uint8_t * | ||||
| Z85_decode (uint8_t *dest, char *string) | ||||
| { | ||||
|     assert (strlen (string) % 5 == 0); | ||||
|     uint byte_nbr = 0; | ||||
|     uint char_nbr = 0; | ||||
|     uint32_t value = 0; | ||||
|     while (char_nbr < strlen (string)) { | ||||
|         //  Accumulate value in base 85 | ||||
|         value = value * 85 + decoder [(uint8_t) string [char_nbr++] - 32]; | ||||
|         if (char_nbr % 5 == 0) { | ||||
|             //  Output value in base 256 | ||||
|             uint divisor = 256 * 256 * 256; | ||||
|             while (divisor) { | ||||
|                 dest [byte_nbr++] = value / divisor % 256; | ||||
|                 divisor /= 256; | ||||
|             } | ||||
|             value = 0; | ||||
|         } | ||||
|     } | ||||
|     assert (byte_nbr == strlen (string) * 4 / 5); | ||||
|     return dest; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Ian Barber
					Ian Barber