我想要写一个完整的diffie示例,用于弹跳城堡,包括密钥生成、密钥交换、加密和解密。我还想验证一下,如果Alice正在与Bob建立连接,那么她应该发送她的公钥、参数P和参数G。
这也是一个很好的参考。
命名空间:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Agreement.Kdf;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Asn1.X509;
using System.Diagnostics;
using Org.BouncyCastle.OpenSsl;此测试用例的一些常量:
const string Algorithm = "ECDH"; //What do you think about the other algorithms?
const int KeyBitSize = 256;
const int NonceBitSize = 128;
const int MacBitSize = 128;
const int DefaultPrimeProbability = 30;启动配对并处理验证加密的Main方法:
public static void TestMethod() {
//BEGIN SETUP ALICE
IAsymmetricCipherKeyPairGenerator aliceKeyGen = GeneratorUtilities.GetKeyPairGenerator (Algorithm);
DHParametersGenerator aliceGenerator = new DHParametersGenerator ();
aliceGenerator.Init (KeyBitSize, DefaultPrimeProbability, new SecureRandom ());
DHParameters aliceParameters = aliceGenerator.GenerateParameters ();
KeyGenerationParameters aliceKGP = new DHKeyGenerationParameters (new SecureRandom (), aliceParameters);
aliceKeyGen.Init (aliceKGP);
AsymmetricCipherKeyPair aliceKeyPair = aliceKeyGen.GenerateKeyPair ();
IBasicAgreement aliceKeyAgree = AgreementUtilities.GetBasicAgreement (Algorithm);
aliceKeyAgree.Init (aliceKeyPair.Private);
//END SETUP ALICE
/////AT THIS POINT, Alice's Public Key, Alice's Parameter P and Alice's Parameter G are sent unsecure to BOB
//BEGIN SETUP BOB
IAsymmetricCipherKeyPairGenerator bobKeyGen = GeneratorUtilities.GetKeyPairGenerator (Algorithm);
DHParameters bobParameters = new DHParameters( aliceParameters.P, aliceParameters.G );
KeyGenerationParameters bobKGP = new DHKeyGenerationParameters (new SecureRandom (), bobParameters);
bobKeyGen.Init (bobKGP);
AsymmetricCipherKeyPair bobKeyPair = bobKeyGen.GenerateKeyPair ();
IBasicAgreement bobKeyAgree = AgreementUtilities.GetBasicAgreement (Algorithm);
bobKeyAgree.Init (bobKeyPair.Private);
//END SETUP BOB
BigInteger aliceAgree = aliceKeyAgree.CalculateAgreement (bobKeyPair.Public);
BigInteger bobAgree = bobKeyAgree.CalculateAgreement (aliceKeyPair.Public);
if (!aliceAgree.Equals (bobAgree)) {
throw new Exception ("Keys do not match.");
}
byte[] nonSecretMessage = GetBytes ("HeaderMessageForASDF");
byte[] secretMessage = GetBytes ("Secret message contents");
byte[] decNonSecretBytes;
KeyParameter sharedKey = new KeyParameter (aliceAgree.ToByteArrayUnsigned ());
var encMessage = EncryptMessage( sharedKey, nonSecretMessage, secretMessage );
var decMessage = DecryptMessage( sharedKey, encMessage, out decNonSecretBytes );
var decNonSecretMessage = GetString( decNonSecretBytes );
var decSecretMessage = GetString( decMessage );
Debug.WriteLine( decNonSecretMessage + " - " + decSecretMessage );
return;
}用给定数据加密消息的包装方法:
public static byte[] EncryptMessage (string sharedKey, string nonSecretMessage, string secretMessage)
{
return EncryptMessage( new KeyParameter( Convert.FromBase64String( sharedKey ) ), GetBytes( nonSecretMessage ), GetBytes( secretMessage ) );
}使用给定数据加密消息的助手方法
public static byte[] EncryptMessage( KeyParameter sharedKey, byte[] nonSecretMessage, byte[] secretMessage ) {
if( nonSecretMessage != null && nonSecretMessage.Length > 255 ) throw new Exception( "Non Secret Message Too Long!" );
byte nonSecretLength = nonSecretMessage == null ? (byte)0 : (byte)nonSecretMessage.Length;
var nonce = new byte[NonceBitSize / 8];
var rand = new SecureRandom();
rand.NextBytes(nonce, 0, nonce.Length);
var cipher = new GcmBlockCipher(new AesFastEngine());
var aeadParameters = new AeadParameters(sharedKey, MacBitSize, nonce, nonSecretMessage );
cipher.Init(true, aeadParameters);
//Generate Cipher Text With Auth Tag
var cipherText = new byte[cipher.GetOutputSize(secretMessage.Length)];
var len = cipher.ProcessBytes(secretMessage, 0, secretMessage.Length, cipherText, 0);
cipher.DoFinal(cipherText, len);
using (var combinedStream = new MemoryStream())
{
using (var binaryWriter = new BinaryWriter(combinedStream))
{
//Prepend Authenticated Payload
binaryWriter.Write(nonSecretLength);
binaryWriter.Write(nonSecretMessage);
//Prepend Nonce
binaryWriter.Write(nonce);
//Write Cipher Text
binaryWriter.Write(cipherText);
}
return combinedStream.ToArray();
}
} 用于解密消息的包装器方法
public static string DecryptMessage (string sharedKey, byte[] encryptedMessage, out string nonSecretPayload)
{
byte[] nonSecretPayloadBytes;
byte[] payload = DecryptMessage( new KeyParameter( Convert.FromBase64String( sharedKey ) ), encryptedMessage, out nonSecretPayloadBytes );
nonSecretPayload = GetString( nonSecretPayloadBytes );
return GetString( payload );
}帮助方法解密消息。
public static byte[] DecryptMessage( KeyParameter sharedKey, byte[] encryptedMessage, out byte[] nonSecretPayloadBytes )
{
using (var cipherStream = new MemoryStream(encryptedMessage))
using (var cipherReader = new BinaryReader(cipherStream))
{
//Grab Payload
int nonSecretLength = (int)cipherReader.ReadByte();
nonSecretPayloadBytes = cipherReader.ReadBytes(nonSecretLength);
//Grab Nonce
var nonce = cipherReader.ReadBytes(NonceBitSize / 8);
var cipher = new GcmBlockCipher(new AesFastEngine());
var parameters = new AeadParameters(sharedKey, MacBitSize, nonce, nonSecretPayloadBytes);
cipher.Init(false, parameters);
//Decrypt Cipher Text
var cipherText = cipherReader.ReadBytes(encryptedMessage.Length - nonSecretLength - nonce.Length);
var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
try
{
var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
cipher.DoFinal(plainText, len);
}
catch (InvalidCipherTextException)
{
//Return null if it doesn't authenticate
return null;
}
return plainText;
}
}返回给定字符串的字节数据:
static byte[] GetBytes(string str)
{
if( str == null ) return null;
return System.Text.Encoding.Unicode.GetBytes( str );
}返回给定字节数据的字符串:
static string GetString(byte[] bytes)
{
if( bytes == null ) return null;
return System.Text.Encoding.Unicode.GetString( bytes, 0, bytes.Length );
}发布于 2015-11-17 10:33:25
这只是一个小小的回顾,因为赫斯拉赫已经涵盖了我想要表达的大部分观点,但我对你对var的使用持异议。
正如赫斯拉赫所言,您在这里使用var是错误的:
var len = cipher.ProcessBytes(secretMessage, 0, secretMessage.Length, cipherText, 0);因为
任务的右侧返回的内容并不明显。
但是,在这里您也忽略了var的有用用途:
int nonSecretLength = (int)cipherReader.ReadByte();也在这里:
DHParametersGenerator aliceGenerator = new DHParametersGenerator ();还有很多其他的案例。
使用var的关键规则是在变量声明的右侧使其类型明显时使用var。
发布于 2020-02-27 17:53:30
我总是鼓励对页面顶部的用法进行清理,所以当我查看代码时,我大致知道我将要进入什么。
https://codereview.stackexchange.com/questions/110952
复制相似问题