Пример #1
0
        PushMsgResult ProcessWelcome(ref Msg msg)
        {
            if (msg.Size != 168)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> welcomeNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> welcomePlaintext = stackalloc byte[128];
            Span <byte> welcomeBox       = msg.Slice(24, 144);

            WelcomeNoncePrefix.CopyTo(welcomeNonce);
            msg.Slice(8, 16).CopyTo(welcomeNonce.Slice(8));

            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey);
            bool isDecrypted = box.TryDecrypt(welcomePlaintext, welcomeBox, welcomeNonce);

            if (!isDecrypted)
            {
                return(PushMsgResult.Error);
            }

            m_cnServerKey = welcomePlaintext.Slice(0, 32).ToArray();
            m_cnCookie    = welcomePlaintext.Slice(32, 16 + 80).ToArray();

            // Create the curve box
            m_box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnServerKey);

            m_state = State.SendInitiate;

            return(PushMsgResult.Ok);
        }
Пример #2
0
        PullMsgResult ProduceWelcome(ref Msg msg)
        {
            Span <byte> cookieNonce      = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> cookiePlaintext  = stackalloc byte[64];
            Span <byte> cookieCiphertext = stackalloc byte[64 + XSalsa20Poly1305.TagLength];

            //  Create full nonce for encryption
            //  8-byte prefix plus 16-byte random nonce
            CookieNoncePrefix.CopyTo(cookieNonce);
            using var rng = RandomNumberGenerator.Create();
#if NETSTANDARD2_1
            rng.GetBytes(cookieNonce.Slice(8));
#else
            byte[] temp = new byte[16];
            rng.GetBytes(temp);
            temp.CopyTo(cookieNonce.Slice(8));
#endif

            // Generate cookie = Box [C' + s'](t)
            m_cnClientKey.CopyTo(cookiePlaintext);
            m_cnSecretKey.CopyTo(cookiePlaintext.Slice(32));

            // Generate fresh cookie key
            rng.GetBytes(m_cookieKey);

            // Encrypt using symmetric cookie key
            using var secretBox = new XSalsa20Poly1305(m_cookieKey);
            secretBox.Encrypt(cookieCiphertext, cookiePlaintext, cookieNonce);
            cookiePlaintext.Clear();

            Span <byte> welcomeNonce      = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> welcomePlaintext  = stackalloc byte[128];
            Span <byte> welcomeCiphertext = stackalloc byte[128 + Curve25519XSalsa20Poly1305.TagLength];

            //  Create full nonce for encryption
            //  8-byte prefix plus 16-byte random nonce
            WelcomeNoncePrefix.CopyTo(welcomeNonce);
#if NETSTANDARD2_1
            rng.GetBytes(welcomeNonce.Slice(8));
#else
            rng.GetBytes(temp);
            temp.CopyTo(welcomeNonce.Slice(8));
#endif

            // Create 144-byte Box [S' + cookie](S->C')
            m_cnPublicKey.CopyTo(welcomePlaintext);
            cookieNonce.Slice(8).CopyTo(welcomePlaintext.Slice(32));
            cookieCiphertext.CopyTo(welcomePlaintext.Slice(48));
            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey);
            box.Encrypt(welcomeCiphertext, welcomePlaintext, welcomeNonce);
            welcomePlaintext.Clear();

            msg.InitPool(168); // TODO: we can save some allocation here by allocating this earlier
            Span <byte> welcome = msg;
            WelcomeLiteral.CopyTo(welcome);
            welcomeNonce.Slice(8, 16).CopyTo(welcome.Slice(8));
            welcomeCiphertext.CopyTo(welcome.Slice(24));

            return(PullMsgResult.Ok);
        }
Пример #3
0
        PullMsgResult ProduceInitiate(ref Msg msg)
        {
            int metadataLength = BasicPropertiesLength;

            byte[] metadataPlaintext = new byte[metadataLength];
            AddBasicProperties(metadataPlaintext);
            msg.InitPool(113 + 128 + metadataLength + Curve25519XSalsa20Poly1305.TagLength);

            Span <byte> vouchNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> vouchPlaintext = stackalloc byte[64];
            Span <byte> vouchBox       = stackalloc byte[Curve25519XSalsa20Poly1305.TagLength + 64];

            //  Create vouch = Box [C',S](C->S')
            m_cnPublicKey.CopyTo(vouchPlaintext);
            m_serverKey.CopyTo(vouchPlaintext.Slice(32));

            VouchNoncePrefix.CopyTo(vouchNonce);
            using var rng = RandomNumberGenerator.Create();
#if NETSTANDARD2_1
            rng.GetBytes(vouchNonce.Slice(8));
#else
            byte[] temp = new byte[16];
            rng.GetBytes(temp);
            temp.CopyTo(vouchNonce.Slice(8));
#endif

            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnServerKey);
            box.Encrypt(vouchBox, vouchPlaintext, vouchNonce);

            Span <byte> initiate          = msg;
            Span <byte> initiateNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> initiatePlaintext = new byte[128 + metadataLength];
            Span <byte> initiateBox       = initiate.Slice(113);

            //  Create Box [C + vouch + metadata](C'->S')
            m_publicKey.CopyTo(initiatePlaintext);
            vouchNonce.Slice(8).CopyTo(initiatePlaintext.Slice(32));
            vouchBox.CopyTo(initiatePlaintext.Slice(48));
            metadataPlaintext.CopyTo(initiatePlaintext.Slice(48 + 80));
            Array.Clear(metadataPlaintext, 0, metadataPlaintext.Length);

            InitiatieNoncePrefix.CopyTo(initiateNonce);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, initiateNonce.Slice(16));

            using var box2 = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnServerKey);
            box2.Encrypt(initiateBox, initiatePlaintext, initiateNonce);

            InitiateLiteral.CopyTo(initiate);

            //  Cookie provided by the server in the WELCOME command
            m_cnCookie.CopyTo(initiate.Slice(9, 96));

            //  Short nonce, prefixed by "CurveZMQINITIATE"
            initiateNonce.Slice(16).CopyTo(initiate.Slice(105));

            m_nonce++;

            return(PullMsgResult.Ok);
        }
Пример #4
0
 public CurveServerMechanism(SessionBase session, Options options) :
     base(session, options, "CurveZMQMESSAGES", "CurveZMQMESSAGEC")
 {
     m_secretKey   = (byte[])options.CurveSecretKey.Clone();
     m_cnClientKey = new byte[Curve25519XSalsa20Poly1305.KeyLength];
     m_cookieKey   = new byte[Curve25519XSalsa20Poly1305.KeyLength];
     Curve25519XSalsa20Poly1305.KeyPair(out m_cnSecretKey, out m_cnPublicKey);
 }
Пример #5
0
 public CurveClientMechanism(SessionBase session, Options options) :
     base(session, options, "CurveZMQMESSAGEC", "CurveZMQMESSAGES")
 {
     m_secretKey = (byte[])options.CurveSecretKey.Clone();
     m_publicKey = (byte[])options.CurvePublicKey.Clone();
     m_serverKey = (byte[])options.CurveServerKey.Clone();
     Curve25519XSalsa20Poly1305.KeyPair(out m_cnSecretKey, out m_cnPublicKey);
 }
Пример #6
0
 public byte[] Decrypt(byte[] cipher, byte[] nonce)
 {
     byte[] message = new byte[cipher.Length];
     Curve25519XSalsa20Poly1305.Open(message, cipher, nonce, RemotePublicKey, PrivateKey);
     byte[] decrypted = new byte[cipher.Length - 32];
     Buffer.BlockCopy(message, 32, decrypted, 0, cipher.Length - 32);
     return(decrypted);
 }
Пример #7
0
        public bool DecodeEndVerify(EncryptedVote vote, out byte[] decoded)
        {
            Curve25519XSalsa20Poly1305 box = new Curve25519XSalsa20Poly1305(_privateKey, vote.PublicKey.ParseHexEncodedValue());
            var encryptedMessage           = vote.Message.ParseHexEncodedValue();
            var decryptedMessage           = new byte[encryptedMessage.Length - XSalsa20Poly1305.TagLength];
            var ret = box.TryDecrypt(decryptedMessage, encryptedMessage, vote.Nonce.ParseHexEncodedValue());

            decoded = decryptedMessage;
            return(ret);
        }
Пример #8
0
        public byte[] Encrypt(byte[] message, int index, int length, out byte[] nonce)
        {
            byte[] payload = new byte[length + 32];
            Buffer.BlockCopy(message, index, payload, 32, length);

            byte[] cipher = new byte[length - index + 32];
            nonce = NewNonce();
            Curve25519XSalsa20Poly1305.Box(cipher, payload, nonce, RemotePublicKey, PrivateKey);
            return(cipher);
        }
Пример #9
0
        PushMsgResult ProcessHello(ref Msg msg)
        {
            if (!CheckBasicCommandStructure(ref msg))
            {
                return(PushMsgResult.Error);
            }

            Span <byte> hello = msg;

            if (!IsCommand("HELLO", ref msg))
            {
                return(PushMsgResult.Error);
            }

            if (hello.Length != 200)
            {
                return(PushMsgResult.Error);
            }

            byte major = hello[6];
            byte minor = hello[7];

            if (major != 1 || minor != 0)
            {
                // client HELLO has unknown version number
                return(PushMsgResult.Error);
            }

            // Save client's short-term public key (C')
            hello.Slice(80, 32).CopyTo(m_cnClientKey);

            Span <byte> helloNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            HelloNoncePrefix.CopyTo(helloNonce);
            hello.Slice(112, 8).CopyTo(helloNonce.Slice(16));
            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(hello, 112);

            using var box = new Curve25519XSalsa20Poly1305(m_secretKey, m_cnClientKey);

            Span <byte> helloPlaintext = stackalloc byte[80];
            bool        isDecrypted    = box.TryDecrypt(helloPlaintext, hello.Slice(120, 80), helloNonce);

            if (!isDecrypted)
            {
                return(PushMsgResult.Error);
            }

            helloPlaintext.Clear();

            m_state = State.SendingWelcome;
            return(PushMsgResult.Ok);
        }
Пример #10
0
        public static byte[] BoxUnbox(byte[] test)
        {
            byte[] alicePK, aliceSK, bobPK, bobSK;
            Curve25519XSalsa20Poly1305.KeyPair(out alicePK, out aliceSK);
            Curve25519XSalsa20Poly1305.KeyPair(out bobPK, out bobSK);
            byte[] nonce            = NewNonce();
            byte[] cipher           = new byte[test.Length + 32];
            byte[] message          = new byte[test.Length + 32];
            byte[] messageDecrypted = new byte[test.Length + 32];
            Buffer.BlockCopy(test, 0, message, 32, test.Length);

            Curve25519XSalsa20Poly1305.Box(cipher, message, nonce, bobPK, aliceSK);
            Curve25519XSalsa20Poly1305.Open(messageDecrypted, cipher, nonce, alicePK, bobSK);

            byte[] clear = new byte[messageDecrypted.Length - 32];
            Buffer.BlockCopy(messageDecrypted, 32, clear, 0, messageDecrypted.Length - 32);
            return(clear);
        }
Пример #11
0
        public static double EncryptRateTest(int messageSize)
        {
            int count = 1000;

            byte[] alicePK, aliceSK, bobPK, bobSK;
            Curve25519XSalsa20Poly1305.KeyPair(out alicePK, out aliceSK);
            Curve25519XSalsa20Poly1305.KeyPair(out bobPK, out bobSK);
            byte[] message = new byte[messageSize + 32];
            byte[] cipher  = new byte[messageSize + 32];

            RandomBytes.generate(message);
            Stopwatch sw = new Stopwatch();

            sw.Start();
            for (int i = 0; i < count; i++)
            {
                Curve25519XSalsa20Poly1305.Box(cipher, message, NewNonce(), bobPK, aliceSK);
            }
            sw.Stop();
            return(count / sw.Elapsed.TotalSeconds);
        }
Пример #12
0
        PullMsgResult ProduceHello(ref Msg msg)
        {
            msg.InitPool(200);

            Span <byte> helloNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> helloPlaintext = stackalloc byte[64];
            Span <byte> helloBox       = msg.Slice(120);

            // Prepare the full nonce
            HelloNoncePrefix.CopyTo(helloNonce);
            NetworkOrderBitsConverter.PutUInt64(m_nonce, helloNonce.Slice(16));

            // Create Box [64 * %x0](C'->S)
            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_serverKey);
            box.Encrypt(helloBox, helloPlaintext, helloNonce);

            Span <byte> hello = msg;

            HelloLiteral.CopyTo(hello);

            //  CurveZMQ major and minor version numbers
            hello[6] = 1;
            hello[7] = 0;

            // 8-80 are left zeros for anti-amplification padding

            //  Client public connection key
            m_cnPublicKey.CopyTo(hello.Slice(80));

            //  Short nonce, prefixed by "CurveZMQHELLO---"
            helloNonce.Slice(16).CopyTo(hello.Slice(112));

            m_nonce++;

            return(PullMsgResult.Ok);
        }
Пример #13
0
 public NetMQCertificate()
 {
     SecretKey = new byte[32];
     PublicKey = new byte[32];
     Curve25519XSalsa20Poly1305.KeyPair(SecretKey, PublicKey);
 }
Пример #14
0
        PushMsgResult ProcessInitiate(ref Msg msg)
        {
            if (!CheckBasicCommandStructure(ref msg))
            {
                return(PushMsgResult.Error);
            }

            Span <byte> initiate = msg;

            if (!IsCommand("INITIATE", ref msg))
            {
                return(PushMsgResult.Error);
            }

            if (initiate.Length < 257)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> cookieNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> cookiePlaintext = stackalloc byte[64];
            Span <byte> cookieBox       = initiate.Slice(25, 80);

            CookieNoncePrefix.CopyTo(cookieNonce);
            initiate.Slice(9, 16).CopyTo(cookieNonce.Slice(8));

            using var secretBox = new XSalsa20Poly1305(m_cookieKey);
            bool decrypted = secretBox.TryDecrypt(cookiePlaintext, cookieBox, cookieNonce);

            if (!decrypted)
            {
                return(PushMsgResult.Error);
            }

            //  Check cookie plain text is as expected [C' + s']
            if (!SpanUtility.Equals(m_cnClientKey, cookiePlaintext.Slice(0, 32)) ||
                !SpanUtility.Equals(m_cnSecretKey, cookiePlaintext.Slice(32, 32)))
            {
                return(PushMsgResult.Error);
            }

            Span <byte> initiateNonce = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];

            byte[] initiatePlaintext = new byte[msg.Size - 113];
            var    initiateBox       = initiate.Slice(113);

            InitiatieNoncePrefix.CopyTo(initiateNonce);
            initiate.Slice(105, 8).CopyTo(initiateNonce.Slice(16));
            m_peerNonce = NetworkOrderBitsConverter.ToUInt64(initiate, 105);

            using var box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnClientKey);
            bool decrypt = box.TryDecrypt(initiatePlaintext, initiateBox, initiateNonce);

            if (!decrypt)
            {
                return(PushMsgResult.Error);
            }

            Span <byte> vouchNonce     = stackalloc byte[Curve25519XSalsa20Poly1305.NonceLength];
            Span <byte> vouchPlaintext = stackalloc byte[64];
            Span <byte> vouchBox       = new Span <byte>(initiatePlaintext, 48, 80);
            var         clientKey      = new Span <byte>(initiatePlaintext, 0, 32);

            VouchNoncePrefix.CopyTo(vouchNonce);
            new Span <byte>(initiatePlaintext, 32, 16).CopyTo(vouchNonce.Slice(8));

            using var box2 = new Curve25519XSalsa20Poly1305(m_cnSecretKey, clientKey);
            decrypt        = box2.TryDecrypt(vouchPlaintext, vouchBox, vouchNonce);
            if (!decrypt)
            {
                return(PushMsgResult.Error);
            }

            //  What we decrypted must be the client's short-term public key
            if (!SpanUtility.Equals(vouchPlaintext.Slice(0, 32), m_cnClientKey))
            {
                return(PushMsgResult.Error);
            }

            //  Create the session box
            m_box = new Curve25519XSalsa20Poly1305(m_cnSecretKey, m_cnClientKey);

            //  This supports the Stonehouse pattern (encryption without authentication).
            m_state = State.SendingReady;

            if (!ParseMetadata(new Span <byte>(initiatePlaintext, 128, initiatePlaintext.Length - 128 - 16)))
            {
                return(PushMsgResult.Error);
            }

            vouchPlaintext.Clear();
            Array.Clear(initiatePlaintext, 0, initiatePlaintext.Length);

            return(PushMsgResult.Ok);
        }
Пример #15
0
 public static void CreateKeys(out byte[] publicKey, out byte[] privateKey)
 {
     Curve25519XSalsa20Poly1305.KeyPair(out publicKey, out privateKey);
 }
Пример #16
0
        public static void Main()
        {
            Byte[]   skx = { 0xb5, 0xe8, 0xa, 0x23, 0xe5, 0xb1, 0x89, 0x4e, 0x1, 0x71, 0x6d, 0xc6, 0xd3, 0xaa, 0x87, 0xec, 0x8, 0x19, 0x1b, 0x17, 0x91, 0xcb, 0x9e, 0x7f, 0x81, 0x80, 0x4d, 0xb2, 0xd2, 0x2, 0x6f, 0x77 };
            Byte[]   pkx = null;
            DateTime dt  = DateTime.Now;

            for (int i = 0; i < 10; i++)
            {
                Curve25519XSalsa20Poly1305.GetPublicKey(out pkx, skx);
            }
            Console.WriteLine("Time: " + DateTime.Now.Subtract(dt).TotalMilliseconds.ToString());

            Console.Write("SECRET: ");
            for (int i = 0; i < Curve25519XSalsa20Poly1305.SECRETKEYBYTES; i++)
            {
                Console.Write(skx[i].ToString("x2"));
            }
            Console.WriteLine();

            Console.Write("PUBLIC: ");
            for (int i = 0; i < Curve25519XSalsa20Poly1305.SECRETKEYBYTES; i++)
            {
                Console.Write(pkx[i].ToString("x2"));
            }
            Console.WriteLine();
            //Console.ReadLine();
            //return;

            //curve25519xsalsa20poly1305 cb = new curve25519xsalsa20poly1305();
            Byte[] pk1, sk1, pk2, sk2;
            Curve25519XSalsa20Poly1305.KeyPair(out pk1, out sk1);
            Curve25519XSalsa20Poly1305.KeyPair(out pk2, out sk2);

            Console.WriteLine("Two key pairs:");

            Console.Write("SERCET 1: ");
            for (int i = 0; i < Curve25519XSalsa20Poly1305.SECRETKEYBYTES; i++)
            {
                Console.Write(sk1[i].ToString("x2"));
            }
            Console.WriteLine();

            Console.Write("PUBLIC 1: ");
            for (int i = 0; i < Curve25519XSalsa20Poly1305.PUBLICKEYBYTES; i++)
            {
                Console.Write(pk1[i].ToString("x2"));
            }
            Console.WriteLine();

            Console.Write("SERCET 2: ");
            for (int i = 0; i < Curve25519XSalsa20Poly1305.SECRETKEYBYTES; i++)
            {
                Console.Write(sk2[i].ToString("x2"));
            }
            Console.WriteLine();

            Console.Write("PUBLIC 2: ");
            for (int i = 0; i < Curve25519XSalsa20Poly1305.PUBLICKEYBYTES; i++)
            {
                Console.Write(pk2[i].ToString("x2"));
            }
            Console.WriteLine();

            Console.ReadLine();

            Byte[] n = new Byte[24];
            Byte[] c = new Byte[32 + 32];
            Byte[] m = new Byte[32 + 32];
            Byte[] r = new Byte[32 + 32];

            int mlen = 64;

            (new Random()).NextBytes(m);
            for (int i = 0; i < 32; i++)
            {
                m[i] = 0;
            }

            Console.Write("INPUT:  ");
            for (int i = 32; i < 64; i++)
            {
                Console.Write(m[i].ToString("x2"));
            }
            Console.WriteLine();

            int o1, o2;

            //Byte[] before1 = curve25519xsalsa20poly1305.crypto_box_beforenm(pk2, sk1);
            //Byte[] before2 = curve25519xsalsa20poly1305.crypto_box_beforenm(pk1, sk2);


            //o1 = curve25519xsalsa20poly1305.crypto_box_afternm(c, m, n, before1);
            //o2 = curve25519xsalsa20poly1305.crypto_box_open_afternm(r, c, n, before2);

            o1 = Curve25519XSalsa20Poly1305.Box(c, 0, m, 0, mlen, n, pk2, sk1);
            o2 = Curve25519XSalsa20Poly1305.Open(r, 0, c, 0, mlen, n, pk1, sk2);

            fixed(Byte *pk1p = pk1, sk1p = sk1, np = n, cp = c, mp = m, pk2p = pk2, sk2p = sk2, rp = r)
            {
                //o1 = curve25519xsalsa20poly1305.crypto_box(cp, mp, (ulong)mlen, np, pk2p, sk1p);
                //o2 = curve25519xsalsa20poly1305.crypto_box_open(rp, cp, (ulong)mlen, np, pk1p, sk2p);
            }

            Console.Write("OUTPUT: ");
            for (int i = 32; i < 64; i++)
            {
                Console.Write(r[i].ToString("x2"));
            }
            Console.WriteLine();

            Console.WriteLine("RESULT: {0} {1}", o1, o2);

            Console.ReadLine();
        }