public void TestClone() { var message = "hello, how are you good sir?"; var s1 = new Strobe("myHash", 128); var s2 = s1.Clone() as Strobe; s1.Operate(false, Operation.Ad, Encoding.ASCII.GetBytes(message), 0, false); var state1 = s1.DebugPrintState(); var out1 = s1.Prf(32).ToHexString(); var state12 = s1.DebugPrintState(); s2.Operate(false, Operation.Ad, Encoding.ASCII.GetBytes(message), 0, false); var state2 = s2.DebugPrintState(); var out2 = s2.Prf(32).ToHexString(); var state22 = s2.DebugPrintState(); System.Diagnostics.Debug.WriteLine(out1); System.Diagnostics.Debug.WriteLine(out2); if (out1 != out2 || state1 != state2 || state12 != state22) { throw new Exception("strobe cannot stream correctly"); } }
public void TestStream2() { var s = new Strobe("custom string number 2, that's a pretty long string", 128); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); var key = Encoding.ASCII.GetBytes("0101010100100101010101010101001001"); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); s.Operate(false, Operation.Key, key, 0, false); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); s.Operate(false, Operation.Key, key, 0, true); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); var message = Encoding.ASCII.GetBytes(("hello, how are you good sir? ????")); s.Operate(false, Operation.Ad, message, 0, false); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); s.Operate(false, Operation.Ad, message, 0, true); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); s.Operate(false, Operation.Ad, message, 0, false); System.Diagnostics.Debug.WriteLine(s.DebugPrintState()); if (!string.Equals(s.DebugPrintState(), "5117b46c2d842655c1be2a69f64f16aaaad2c0050fe2ac5446afe44345a9b10d0" + "44c8b3ec8005a9e362c0a431ab5c4d8228c2f890ae56ad3fef4404aa6cc76704b503d627553ae9635d329c" + "dfa86ed29ec0dd79787ff3fcefdee7463c053ef3b4a4fa7c8eb89a6372df2c4ccfc7469d7447bd19a67940" + "642334706e5ff6b1ef58514e55c6b5c6921c58eb7cb5c57978c92c42e598926fcfdcd9705fb948ed6fe902" + "7c65fb0659c98a9c9668d523dfa2b27bde76224944503b686901c989fedac34994dd16daedf00", StringComparison.InvariantCultureIgnoreCase)) { throw new Exception("this is not working"); } }
public Strobe TranscriptCommit(string sth, byte[] message) { var obj = new Strobe("Merlin", 128); obj.Ad(true, message); return(obj); }
public static void SetStrobe(Light l, Strobe s) { if (l == Light.LIGHT1) { LightThread.Light1.StrobeVal = s; } if (l == Light.LIGHT2) { LightThread.Light2.StrobeVal = s; } }
public static void SetAll(Light l, Color c, Gobo g, Strobe s, Int32 pan, Int32 panf, Int32 tilt, Int32 tiltf) { LightOnOff(l, true); SetColor(l, c); SetGobo(l, g); SetStrobe(l, s); SetPan(l, pan); SetPanFine(l, panf); SetTilt(l, tilt); SetTiltFine(l, tiltf); }
/// <summary> /// Output (extract) data from strobe state /// </summary> /// <param name="outputLength">Expected output length</param> public Hash(int outputLength) { if (outputLength < Symmetric.HashSize) { throw new Exception( $"disco: an output length smaller than {Symmetric.HashSize*8}-bit " + $"({Symmetric.HashSize} bytes) has security consequences"); } this.strobeState = new Strobe("DiscoHash", Symmetric.SecurityParameter); this.outputLen = outputLength; }
static void Main() { // Create strobe object, setting init string and security var strobe = new Strobe("MyStrobe", 128); var messageByte = Encoding.ASCII.GetBytes("Hello gentlemens"); strobe.Ad(false, messageByte); var prfBytes = strobe.Prf(16); Console.WriteLine(BitConverter.ToString(prfBytes).Replace("-", "")); }
/// <summary> /// Hash allows you to hash an input of any length and obtain an output /// of length greater or equal to 256 bits (32 bytes). /// </summary> /// <returns>Resulted Hash</returns> public static byte[] Hash(byte[] input, int outputLength) { if (outputLength < Symmetric.HashSize) { throw new Exception( $"discoNet: an output length smaller than {Symmetric.HashSize*8}-bit " + $"({Symmetric.HashSize} bytes) has security consequences"); } var hash = new Strobe("DiscoHash", Symmetric.SecurityParameter); hash.Ad(false, input); return(hash.Prf(outputLength)); }
private void RunTestVector(string vectorName) { var vector = this.TestVectors.TestVectors.Find(tv => tv.Name == vectorName); Strobe strobe = null; foreach (var operation in vector.Operations) { if (operation.Name == "init") { strobe = new Strobe(operation.CustomString, operation.Security); if (!string.Equals( strobe.DebugPrintState(), operation.StateAfter, StringComparison.InvariantCultureIgnoreCase)) { throw new Exception(); } continue; } if (strobe == null) { throw new ArgumentNullException(nameof(strobe)); } var result = strobe.Operate( operation.Meta ?? false, operation.GetStrobeOperation(), operation.InputData?.ToByteArray(), operation.InputLength, operation.Stream ?? false); if (!string.Equals( strobe.DebugPrintState(), operation.StateAfter, StringComparison.InvariantCultureIgnoreCase)) { throw new Exception(); } if (operation.Output != null && !string.Equals( operation.Output, result.ToHexString(), StringComparison.InvariantCultureIgnoreCase)) { throw new Exception(); } } }
/// <summary> /// Derive key data /// </summary> /// <param name="keyMaterial">Derivation material</param> /// <param name="keyLen">Length of expected output</param> /// <returns>Derived data</returns> public static byte[] DeriveKeys(byte[] keyMaterial, int keyLen) { if (keyMaterial.Length < Symmetric.KeySize) { throw new Exception( $"disco: deriving keys from a value smaller than {Symmetric.KeySize * 8}-bit " + $"({Symmetric.KeySize} bytes) has security consequences"); } var hash = new Strobe("DiscoKDF", Symmetric.SecurityParameter); hash.Ad(false, keyMaterial); return(hash.Prf(keyLen)); }
/// <summary> /// Protect integrity of unencrypted text /// </summary> /// <param name="key">Symmetric key for MAC</param> /// <param name="plaintext">Plaintext to protect</param> /// <returns>Plaintext with MAC tag</returns> public static byte[] ProtectIntegrity(byte[] key, byte[] plaintext) { if (key.Length < Symmetric.KeySize) { throw new Exception( $"disco: using a key smaller than {Symmetric.KeySize * 8}-bit " + $"({Symmetric.KeySize} bytes) has security consequences"); } var hash = new Strobe("DiscoMAC", Symmetric.SecurityParameter); hash.Ad(false, key); hash.Ad(false, plaintext); return(plaintext.Concat(hash.SendMac(false, Symmetric.TagSize)).ToArray()); }
/// <summary> /// Encrypt a plaintext message with a key of any size greater than 128 bits (16 bytes). /// </summary> /// <param name="key"> /// Symmetric key for encryption /// </param> /// <param name="plaintext"> /// Plaintext to encrypt /// </param> /// <returns>Encrypted data</returns> public static byte[] Encrypt(byte[] key, byte[] plaintext) { if (key.Length < Symmetric.KeySize) { throw new Exception( $"disco: using a key smaller than {Symmetric.KeySize * 8}-bit " + $"({Symmetric.KeySize} bytes) has security consequences"); } var ae = new Strobe("DiscoAE", Symmetric.SecurityParameter); // Absorb the key ae.Ad(false, key); // Generate 192-bit nonce var random = new RNGCryptoServiceProvider(); var nonce = new byte[Symmetric.NonceSize]; # if !DEBUG_DETERMINISTIC
// place a light with a ceiling floor or wall void placeLight(GameObject obj, int y, int z, float brightness, string inColor, float time) { Vector3 spawnPosition = new Vector3(0, (y * spawnOffset) + transform.position.y, (z * spawnOffset) + transform.position.z); GameObject outObj = Instantiate(obj, spawnPosition, Quaternion.identity); Strobe strobe = outObj.GetComponent <Strobe>(); Color outColor = new Color(); switch (inColor) { case "g": outColor.r = 0; outColor.g = 255; outColor.b = 0; break; case "r": outColor.r = 255; outColor.g = 0; outColor.b = 0; break; case "b": outColor.r = 0; outColor.g = 0; outColor.b = 255; break; default: outColor.r = 255; outColor.g = 255; outColor.b = 255; break; } strobe.StrobeTime = time; strobe.intensityMax = brightness; strobe.color = outColor; }
private bool handleStrobeValue(HALHandleContext ctx) { Strobe t = ctx.Value as Strobe; if (t == null) { return(false); } this._lastStrobeContext = ctx; if (this._strobeEmulator == null) { this._strobeEmulator = new StrobeEmulator("RGB-Color-Strobe"); this._strobeEmulator.StrobeOff += handleEmulatorStrobeOff; this._strobeEmulator.StrobeOn += handleEmulatorStrobeOn; } this.StrobeValue = t.Speed; ctx.AddHandleBag(new PropertyValueHandleBag(ctx.Property, (Strobe)this.StrobeValue, this.HandlerName, this.getDependencies())); return(true); }
/// <summary> /// Retrieve and Verify plaintext from unencrypted message /// </summary> /// <param name="key"> /// Symmetric MAC key /// </param> /// <param name="plaintextAndTag"> /// Plaintext with MAC tag to verify /// </param> /// <returns>Plaintext</returns> public static byte[] VerifyIntegrity(byte[] key, byte[] plaintextAndTag) { if (key.Length < Symmetric.KeySize) { throw new Exception( $"disco: using a key smaller than {Symmetric.KeySize * 8}-bit " + $"({Symmetric.KeySize} bytes) has security consequences"); } if (plaintextAndTag.Length < Symmetric.TagSize) { throw new Exception("disco: plaintext does not contain an integrity tag"); } var plainTextLen = plaintextAndTag.Length - Symmetric.TagSize; var plainText = new byte[plainTextLen]; Array.Copy(plaintextAndTag, 0, plainText, 0, plainTextLen); var tag = new byte[Symmetric.TagSize]; Array.Copy(plaintextAndTag, plainTextLen, tag, 0, Symmetric.TagSize); // Getting the tag var hash = new Strobe("DiscoMAC", Symmetric.SecurityParameter); hash.Ad(false, key); hash.Ad(false, plainText); // verifying the tag if (!hash.RecvMac(false, tag)) { throw new Exception("disco: the plaintext has been modified"); } return(plainText); }
internal SymmetricState(string protocolName) { this.strobeState = new Strobe(protocolName, Symmetric.SecurityParameter); }
/// <summary> /// Read handshake message and output payload /// </summary> /// <param name="message">Noise message</param> /// <param name="payloadBuffer">payload buffer</param> /// <returns>Tuple of strobe state for initiator and responder</returns> public (Strobe initiatorState, Strobe responderState) ReadMessage(byte[] message, out byte[] payloadBuffer) { Strobe initiatorState = null; Strobe responderState = null; payloadBuffer = new byte[] { }; // is it our turn to read? if (this.ShouldWrite) { throw new Exception("disco: unexpected call to ReadMessage should be WriteMessage"); } // do we have a token to process? if (this.MessagePatterns.Length == 0 || this.MessagePatterns[0].Tokens.Count == 0) { throw new Exception("disco: no more tokens or message patterns to write"); } // process the patterns var offset = 0; foreach (var pattern in this.MessagePatterns[0]) { switch (pattern) { case Tokens.TokenE: { if (message.Length - offset < Asymmetric.DhLen) { throw new Exception("disco: the received ephemeral key is to short"); } this.Re = new KeyPair { PublicKey = message.Skip(offset).Take(Asymmetric.DhLen).ToArray() }; offset += Asymmetric.DhLen; this.SymmetricState.MixHash(this.Re.PublicKey); if (this.Psk?.Length > 0) { this.SymmetricState.MixKey(this.Re.PublicKey); } break; } case Tokens.TokenS: { var tagLen = 0; if (this.SymmetricState.IsKeyed) { tagLen = Symmetric.TagSize; } if (message.Length - offset < Asymmetric.DhLen + tagLen) { throw new Exception("disco: the received static key is to short"); } var decrypted = this.SymmetricState.DecryptAndHash( message.Skip(offset).Take(Asymmetric.DhLen + tagLen).ToArray()); // if we already know the remote static, compare this.Rs = new KeyPair { PublicKey = decrypted }; offset += Asymmetric.DhLen + tagLen; break; } case Tokens.TokenEE: { this.SymmetricState.MixKey(Asymmetric.Dh(this.E, this.Re.PublicKey)); break; } case Tokens.TokenES: { if (this.Initiator) { this.SymmetricState.MixKey(Asymmetric.Dh(this.E, this.Rs.PublicKey)); } else { this.SymmetricState.MixKey(Asymmetric.Dh(this.S, this.Re.PublicKey)); } break; } case Tokens.TokenSE: { if (this.Initiator) { this.SymmetricState.MixKey(Asymmetric.Dh(this.S, this.Re.PublicKey)); } else { this.SymmetricState.MixKey(Asymmetric.Dh(this.E, this.Rs.PublicKey)); } break; } case Tokens.TokenSS: { this.SymmetricState.MixKey(Asymmetric.Dh(this.S, this.Rs.PublicKey)); break; } case Tokens.TokenPsk: { this.SymmetricState.MixKeyAndHash(this.Psk); break; } } } // Appends decrpyAndHash(payload) to the buffer var plaintext = this.SymmetricState.DecryptAndHash(message.Skip(offset).ToArray()); payloadBuffer = payloadBuffer.Concat(plaintext).ToArray(); // remove the pattern from the messagePattern if (this.MessagePatterns.Length == 1) { this.MessagePatterns = null; // If there are no more message patterns returns two new CipherState object (initiatorState, responderState) = this.SymmetricState.Split(); } else { this.MessagePatterns = this.MessagePatterns.Skip(1).ToArray(); } // change the direction this.ShouldWrite = true; return(initiatorState, responderState); }
/// <summary> /// Perform handshake protocol if it has not been already run. /// </summary> /// <remarks> /// Most uses of this package need not call Handshake explicitly: /// the first Read or Write will call it automatically. /// </remarks> internal void HandShake() { // Locking the handshakeMutex this.handshakeMutex.WaitOne(); HandshakeState handshakeState = null; try { Strobe c1; Strobe c2; byte[] receivedPayload = null; // did we already go through the handshake? if (this.handshakeComplite) { return; } KeyPair remoteKeyPair = null; if (this.config.RemoteKey != null) { if (this.config.RemoteKey.Length != Asymmetric.DhLen) { throw new Exception($"disco: the provided remote key is not {Asymmetric.DhLen}-byte"); } remoteKeyPair = new KeyPair { PublicKey = new byte[this.config.RemoteKey.Length] }; Array.Copy(this.config.RemoteKey, remoteKeyPair.PublicKey, this.config.RemoteKey.Length); } handshakeState = DiscoHelper.InitializeDisco( this.config.HandshakePattern, this.isClient, this.config.Prologue, this.config.KeyPair, null, remoteKeyPair, null); // pre-shared key handshakeState.Psk = this.config.PreSharedKey; do { // start handshake if (handshakeState.ShouldWrite) { // we're writing the next message pattern // if it's the message pattern and we're sending a static key, we also send a proof // TODO: is this the best way of sending a proof :/ ? byte[] bufToWrite; if (handshakeState.MessagePatterns.Length <= 2 && this.config.StaticPublicKeyProof != null) { (c1, c2) = handshakeState.WriteMessage(this.config.StaticPublicKeyProof, out bufToWrite); } else { (c1, c2) = handshakeState.WriteMessage(new byte[] { }, out bufToWrite); } // header (length) var length = new[] { (byte)(bufToWrite.Length >> 8), (byte)(bufToWrite.Length % 256) }; // write var dataToWrite = length.Concat(bufToWrite).ToArray(); this.connectionStream.Write(dataToWrite, 0, dataToWrite.Length); } else { var bufHeader = this.ReadFromUntil(this.connectionStream, 2); var length = (bufHeader[0] << 8) | bufHeader[1]; if (length > Config.NoiseMessageLength) { throw new Exception("disco: Disco message received exceeds DiscoMessageLength"); } var noiseMessage = this.ReadFromUntil(this.connectionStream, length); (c1, c2) = handshakeState.ReadMessage(noiseMessage, out receivedPayload); } }while (c1 == null); // Has the other peer been authenticated so far? if (!this.isRemoteAuthenticated && this.config.PublicKeyVerifier != null) { byte isRemoteStaticKeySet = 0; // test if remote static key is empty foreach (var val in handshakeState.Rs.PublicKey) { isRemoteStaticKeySet |= val; } if (isRemoteStaticKeySet != 0) { // a remote static key has been received. Verify it if (!this.config.PublicKeyVerifier(handshakeState.Rs.PublicKey, receivedPayload)) { throw new Exception("disco: the received public key could not be authenticated"); } this.isRemoteAuthenticated = true; this.RemotePublicKey = handshakeState.Rs.PublicKey; } } // Processing the final handshake message returns two CipherState objects // the first for encrypting transport messages from initiator to responder // and the second for messages in the other direction. if (c2 != null) { if (this.isClient) { (this.strobeOut, this.strobeIn) = (c1, c2); } else { (this.strobeOut, this.strobeIn) = (c2, c1); } } else { this.IsHalfDuplex = true; this.strobeIn = c1; this.strobeOut = c1; } // TODO: preserve c.hs.symmetricState.h // At that point the HandshakeState should be deleted except for the hash value h, which may be used for post-handshake channel binding (see Section 11.2). handshakeState.Dispose(); // no errors :) this.handshakeComplite = true; } finally { handshakeState?.Dispose(); this.handshakeMutex.ReleaseMutex(); } }
public Transcript(byte[] label) { _obj = new Strobe(MERLIN_PROTOCOL_LABEL, 128); AppendMessage(Encoding.UTF8.GetBytes("dom-sep"), label); }
private Transcript(Strobe obj) { _obj = obj.Clone() as Strobe; }
/// <summary> /// Write payload with handshake message using current state /// </summary> /// <param name="payload">payload to write</param> /// <param name="messageBuffer">output message buffer</param> /// <returns>Tuple of strobe state for initiator and responder</returns> internal (Strobe initiatorState, Strobe responderState) WriteMessage(byte[] payload, out byte[] messageBuffer) { Strobe initiatorState = null; Strobe responderState = null; messageBuffer = new byte[] { }; // is it our turn to write? if (!this.ShouldWrite) { throw new Exception("disco: unexpected call to WriteMessage should be ReadMessage"); } // do we have a token to process? if (this.MessagePatterns.Length == 0 || this.MessagePatterns[0].Tokens.Count == 0) { throw new Exception("disco: no more tokens or message patterns to write"); } // process the patterns foreach (var pattern in this.MessagePatterns[0]) { switch (pattern) { case Tokens.TokenE: { // debug if (this.DebugEphemeral != null) { this.E = this.DebugEphemeral; } else { this.E = Asymmetric.GenerateKeyPair(); } messageBuffer = messageBuffer.Concat(this.E.PublicKey).ToArray(); this.SymmetricState.MixHash(this.E.PublicKey); if (this.Psk?.Length > 0) { this.SymmetricState.MixKey(this.E.PublicKey); } break; } case Tokens.TokenS: { var encrypted = this.SymmetricState.EncryptAndHash(this.S.PublicKey); messageBuffer = messageBuffer.Concat(encrypted).ToArray(); break; } case Tokens.TokenEE: { this.SymmetricState.MixKey(Asymmetric.Dh(this.E, this.Re.PublicKey)); break; } case Tokens.TokenES: { if (this.Initiator) { this.SymmetricState.MixKey(Asymmetric.Dh(this.E, this.Rs.PublicKey)); } else { this.SymmetricState.MixKey(Asymmetric.Dh(this.S, this.Re.PublicKey)); } break; } case Tokens.TokenSE: { if (this.Initiator) { this.SymmetricState.MixKey(Asymmetric.Dh(this.S, this.Re.PublicKey)); } else { this.SymmetricState.MixKey(Asymmetric.Dh(this.E, this.Rs.PublicKey)); } break; } case Tokens.TokenSS: { this.SymmetricState.MixKey(Asymmetric.Dh(this.S, this.Rs.PublicKey)); break; } case Tokens.TokenPsk: { this.SymmetricState.MixHash(this.Psk); break; } default: { throw new Exception("Disco: token not recognized"); } } } // Appends EncryptAndHash(payload) to the buffer var ciphertext = this.SymmetricState.EncryptAndHash(payload); messageBuffer = messageBuffer.Concat(ciphertext).ToArray(); // are there more message patterns to process? if (this.MessagePatterns.Length == 1) { this.MessagePatterns = null; // If there are no more message patterns returns two new CipherState objects (initiatorState, responderState) = this.SymmetricState.Split(); } else { // remove the pattern from the messagePattern this.MessagePatterns = this.MessagePatterns.Skip(1).ToArray(); } // change the direction this.ShouldWrite = false; return(initiatorState, responderState); }