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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
public NetMQCertificate() { SecretKey = new byte[32]; PublicKey = new byte[32]; Curve25519XSalsa20Poly1305.KeyPair(SecretKey, PublicKey); }
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); }
public static void CreateKeys(out byte[] publicKey, out byte[] privateKey) { Curve25519XSalsa20Poly1305.KeyPair(out publicKey, out privateKey); }
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(); }