Skip to content

Instantly share code, notes, and snippets.

@QuiltMeow
Created December 21, 2021 20:29
Show Gist options
  • Select an option

  • Save QuiltMeow/dffb81ae77f3c0e4880ee710384bc5f9 to your computer and use it in GitHub Desktop.

Select an option

Save QuiltMeow/dffb81ae77f3c0e4880ee710384bc5f9 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Cryptography
{
public struct RSAKeyPairString
{
public string publicKey; // 公鑰
public string privateKey; // 金鑰組 (公鑰 + 私鑰)
public void saveKeyPair(string publicKeyPath, string privateKeyPath)
{
File.WriteAllText(publicKeyPath, publicKey);
File.WriteAllText(privateKeyPath, privateKey);
}
}
// 一般而言不太會使用這種方法 除非你要拿來加密別人硬碟 然後跟他要一些錢錢之類的 w
public sealed class RSALargeData : IDisposable
{
public const int ITERATION = 1500;
public static readonly byte[] SALT = new byte[] // TO DO : (Legacy) Change This
{
0x41, 0x6B, 0x61, 0x74, 0x73, 0x75,
0x6B, 0x69, 0x4A, 0x69, 0x61, 0x49,
0x73, 0x56, 0x65, 0x72, 0x79, 0x43,
0x75, 0x74, 0x65
};
public int blockSize
{
get;
private set;
}
public int encryptOutputSize
{
get;
private set;
}
public byte[] iv // RSA CBC 模式
{
get;
private set;
}
public RSACryptoServiceProvider rsa
{
get;
private set;
}
public RSALargeData(string xmlKey) // 可傳入公鑰或金鑰組
{
initRSA(xmlKey);
}
public RSALargeData(Stream xmlKey)
{
using (StreamReader sr = new StreamReader(xmlKey))
{
initRSA(sr.ReadToEnd());
}
}
private void initRSA(string xmlKey)
{
rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlKey);
blockSize = (rsa.KeySize - 384) / 8 + 6;
encryptOutputSize = rsa.ExportParameters(false).Modulus.Length;
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(rsa.ExportCspBlob(false), SALT, ITERATION);
iv = rfc2898.GetBytes(blockSize);
}
public void Dispose()
{
rsa.PersistKeyInCsp = false;
rsa.Clear();
rsa.Dispose();
}
public static RSAKeyPairString generateKeyPair(int length = 4096)
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(length))
{
string publicKey = rsa.ToXmlString(false);
string privateKey = rsa.ToXmlString(true);
rsa.PersistKeyInCsp = false;
rsa.Clear();
return new RSAKeyPairString()
{
publicKey = publicKey,
privateKey = privateKey
};
}
}
public void encrypt(Stream input, Stream output) // 僅公鑰即可加密
{
byte[] currentIV = (byte[])iv.Clone();
byte[] buffer = new byte[blockSize];
int readByte;
while ((readByte = input.Read(buffer, 0, blockSize)) > 0)
{
byte[] data = new byte[readByte];
Buffer.BlockCopy(buffer, 0, data, 0, readByte);
for (int i = 0; i < readByte; ++i)
{
data[i] ^= currentIV[i];
}
byte[] encryptBlock = rsa.Encrypt(data, true);
output.Write(encryptBlock, 0, encryptBlock.Length);
for (int i = 0; i < blockSize; ++i) // IV 更新 : 多餘部分捨棄
{
currentIV[i] = encryptBlock[i];
}
}
}
public void decrypt(Stream input, Stream output) // 需要金鑰組才可進行解密 (解密消耗時間較長 請考慮多執行緒)
{
byte[] currentIV = (byte[])iv.Clone();
byte[] buffer = new byte[encryptOutputSize];
int readByte;
while ((readByte = input.Read(buffer, 0, encryptOutputSize)) > 0)
{
if (readByte != encryptOutputSize)
{
throw new Exception($"無效的密文長度 : {readByte} 預期 : {encryptOutputSize}");
}
byte[] decryptBlock = rsa.Decrypt(buffer, true);
int decryptLength = decryptBlock.Length;
for (int i = 0; i < decryptLength; ++i)
{
decryptBlock[i] ^= currentIV[i];
}
output.Write(decryptBlock, 0, decryptLength);
for (int i = 0; i < blockSize; ++i)
{
currentIV[i] = buffer[i];
}
}
}
public byte[] encryptString(string input, Encoding encode)
{
return encryptByteArray(encode.GetBytes(input));
}
public string decryptString(byte[] input, Encoding encode)
{
return encode.GetString(decryptByteArray(input));
}
public byte[] encryptByteArray(byte[] data)
{
using (Stream input = new MemoryStream(data))
using (MemoryStream output = new MemoryStream())
{
encrypt(input, output);
return output.ToArray();
}
}
public byte[] decryptByteArray(byte[] data)
{
using (Stream input = new MemoryStream(data))
using (MemoryStream output = new MemoryStream())
{
decrypt(input, output);
return output.ToArray();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment