/// <summary> /// Create new entity cyrpto context structure /// Copy constructor - needed to clone key material /// </summary> /// <param name="old">old structure</param> public EntityContext(EntityContext old) { Algorithm = old.Algorithm; BaseIV = (byte[])old.BaseIV.Clone(); Key = (byte[])old.Key.Clone(); Id = (byte[])old.Id.Clone(); ReplayWindow = new ReplayWindow(0, 256); SequenceNumber = old.SequenceNumber; SigningKey = old.SigningKey; }
private void Button_Click(object sender, RoutedEventArgs e) { bool to_close; ReplayWindow replayWindow = new ReplayWindow(out to_close); if (!to_close) { replayWindow.Show(); } }
/// <summary> /// Given the set of inputs, perform the crptographic operations that are needed /// to build a security context for a single sender and recipient. /// </summary> /// <param name="masterSecret">pre-shared key</param> /// <param name="senderId">name assigned to sender</param> /// <param name="recipientId">name assigned to recipient</param> /// <param name="masterSalt">salt value</param> /// <param name="algAEAD">encryption algorithm</param> /// <param name="algKeyAgree">key agreement algorithm</param> /// <returns></returns> public static SecurityContext DeriveContext(byte[] masterSecret, byte[] senderId, byte[] recipientId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null) { SecurityContext ctx = new SecurityContext(); if (algAEAD == null) { ctx.Sender.Algorithm = AlgorithmValues.AES_CCM_64_64_128; } else { ctx.Sender.Algorithm = algAEAD; } ctx.Sender.Id = senderId ?? throw new ArgumentNullException(nameof(senderId)); ctx.Recipient = new EntityContext { Algorithm = ctx.Sender.Algorithm, Id = recipientId ?? throw new ArgumentNullException(nameof(recipientId)), ReplayWindow = new ReplayWindow(0, 64) }; CBORObject info = CBORObject.NewArray(); info.Add(senderId); // 0 info.Add(ctx.Sender.Algorithm); // 1 info.Add("Key"); // 2 info.Add(128 / 8); // 3 in bytes IDigest sha256; if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256)) { sha256 = new Sha256Digest(); } else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512)) { sha256 = new Sha512Digest(); } else { throw new ArgumentException("Unrecognized key agreement algorithm"); } IDerivationFunction hkdf = new HkdfBytesGenerator(sha256); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Sender.Key = new byte[128 / 8]; hkdf.GenerateBytes(ctx.Sender.Key, 0, ctx.Sender.Key.Length); info[0] = CBORObject.FromObject(recipientId); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Recipient.Key = new byte[128 / 8]; hkdf.GenerateBytes(ctx.Recipient.Key, 0, ctx.Recipient.Key.Length); info[2] = CBORObject.FromObject("IV"); info[3] = CBORObject.FromObject(56 / 8); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Recipient.BaseIV = new byte[56 / 8]; hkdf.GenerateBytes(ctx.Recipient.BaseIV, 0, ctx.Recipient.BaseIV.Length); info[0] = CBORObject.FromObject(senderId); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Sender.BaseIV = new byte[56 / 8]; hkdf.GenerateBytes(ctx.Sender.BaseIV, 0, ctx.Sender.BaseIV.Length); // Give a unique context number for doing comparisons ctx.ContextNo = _ContextNumber; _ContextNumber += 1; return(ctx); }
/// <summary> /// Given the set of inputs, perform the crptographic operations that are needed /// to build a security context for a single sender and recipient. /// </summary> /// <param name="masterSecret">pre-shared key</param> /// <param name="senderContext">context for the ID</param> /// <param name="senderId">name assigned to sender</param> /// <param name="recipientId">name assigned to recipient</param> /// <param name="masterSalt">salt value</param> /// <param name="algAEAD">encryption algorithm</param> /// <param name="algKeyAgree">key agreement algorithm</param> /// <returns></returns> public static SecurityContext DeriveContext(byte[] masterSecret, byte[] senderContext, byte[] senderId, byte[] recipientId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null) { int cbKey; int cbIV; SecurityContext ctx = new SecurityContext(); if (algAEAD == null) { ctx.Sender.Algorithm = AlgorithmValues.AES_CCM_16_64_128; } else { ctx.Sender.Algorithm = algAEAD; } if (ctx.Sender.Algorithm.Type != CBORType.Number) { throw new CoAPException("Unsupported algorithm"); } switch ((AlgorithmValuesInt)ctx.Sender.Algorithm.AsInt32()) { case AlgorithmValuesInt.AES_CCM_16_64_128: cbKey = 128 / 8; cbIV = 13; break; case AlgorithmValuesInt.AES_CCM_64_64_128: cbKey = 128 / 8; cbIV = 56 / 8; break; case AlgorithmValuesInt.AES_CCM_64_128_128: cbKey = 128 / 8; cbIV = 56 / 8; break; case AlgorithmValuesInt.AES_CCM_16_128_128: cbKey = 128 / 8; cbIV = 13; break; case AlgorithmValuesInt.AES_GCM_128: cbKey = 128 / 8; cbIV = 96 / 8; break; default: throw new CoAPException("Unsupported algorithm"); } ctx.Sender.Id = senderId ?? throw new ArgumentNullException(nameof(senderId)); ctx.Recipient = new EntityContext { Algorithm = ctx.Sender.Algorithm, Id = recipientId ?? throw new ArgumentNullException(nameof(recipientId)), ReplayWindow = new ReplayWindow(0, 64) }; CBORObject info = CBORObject.NewArray(); info.Add(senderId); // 0 info.Add(senderContext); // 1 info.Add(ctx.Sender.Algorithm); // 2 info.Add("Key"); // 3 info.Add(cbKey); // 4 in bytes IDigest sha256; if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256)) { sha256 = new Sha256Digest(); } else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512)) { sha256 = new Sha512Digest(); } else { throw new ArgumentException("Unrecognized key agreement algorithm"); } IDerivationFunction hkdf = new HkdfBytesGenerator(sha256); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Sender.Key = new byte[cbKey]; hkdf.GenerateBytes(ctx.Sender.Key, 0, ctx.Sender.Key.Length); info[0] = CBORObject.FromObject(recipientId); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Recipient.Key = new byte[cbKey]; hkdf.GenerateBytes(ctx.Recipient.Key, 0, ctx.Recipient.Key.Length); info[0] = CBORObject.FromObject(new byte[0]); info[3] = CBORObject.FromObject("IV"); info[4] = CBORObject.FromObject(cbIV); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Recipient.BaseIV = new byte[cbIV]; hkdf.GenerateBytes(ctx.Recipient.BaseIV, 0, ctx.Recipient.BaseIV.Length); ctx.Sender.BaseIV = (byte[])ctx.Recipient.BaseIV.Clone(); int iIv = cbIV - 5 - senderId.Length; if (cbIV - 6 < senderId.Length) { throw new CoAPException("Sender Id too long"); } ctx.Sender.BaseIV[0] ^= (byte)senderId.Length; for (int i = 0; i < senderId.Length; i++) { ctx.Sender.BaseIV[iIv + i] ^= senderId[i]; } iIv = cbIV - 5 - recipientId.Length; if (cbIV - 6 < recipientId.Length) { throw new CoAPException("Recipient Id too long"); } ctx.Recipient.BaseIV[0] ^= (byte)recipientId.Length; for (int i = 0; i < recipientId.Length; i++) { ctx.Recipient.BaseIV[iIv + i] ^= recipientId[i]; } // Give a unique context number for doing comparisons ctx.ContextNo = _contextNumber; _contextNumber += 1; return(ctx); }