123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- using PCC.App.BinaryFormatter;
- using System.Security;
- using System.Security.Cryptography;
- using System.Text;
- namespace PCC.App.Security;
- public static class RsaUtility
- {
- public static (string pub, string pri) GeneratePem(int bits)
- {
- var rsa = RSA.Create(bits);
- var pub = rsa.ExportRSAPublicKeyPem();
- var pri = rsa.ExportRSAPrivateKeyPem();
- return (pub, pri);
- }
- public static (byte[] pub, byte[] pri) GeneratePKCS1(int bits)
- {
- var rsa = RSA.Create(bits);
- var pub = rsa.ExportRSAPublicKey();
- var pri = rsa.ExportRSAPrivateKey();
- return (pub, pri);
- }
- public static RSA FromPKCS1PrivateKey(byte[] privateKey)
- {
- var rsa = RSA.Create();
- rsa.ImportRSAPrivateKey(privateKey, out _);
- return rsa;
- }
- public static RSA FromPKCS1PublicKey(byte[] publicKey)
- {
- var rsa = RSA.Create();
- rsa.ImportRSAPublicKey(publicKey, out _);
- return rsa;
- }
- public static RSA FromPem(string pub)
- {
- var rsa = RSA.Create();
- rsa.ImportFromPem(pub);
- return rsa;
- }
- public static byte[] Encrypt(RSA encPub, byte[] payload, int skSize = 256, int ivSize = 128) => EncryptAndSignature(encPub, payload, null, skSize, ivSize);
- public static byte[] EncryptAndSignature(RSA encPub, ReadOnlySpan<byte> payload, RSA? sigPri, int skSize = 256, int ivSize = 128)
- {
-
-
-
-
- var sk = RandomNumberGenerator.GetBytes(skSize / 8);
- var iv = RandomNumberGenerator.GetBytes(ivSize / 8);
-
-
- using var aes = Aes.Create();
- aes.Mode = CipherMode.CBC;
- aes.Padding = PaddingMode.PKCS7;
- aes.KeySize = skSize;
- aes.BlockSize = ivSize;
- aes.Key = sk;
- aes.IV = iv;
-
- byte[] ek;
- {
- var msSkIv = new MemoryStream();
- var bw = new BinaryWriter(msSkIv, Encoding.UTF8, true);
- bw.WriteBlock(sk);
- bw.WriteBlock(iv);
- bw.Close();
- var skIv = msSkIv.ToArray();
- ek = encPub.Encrypt(skIv, RSAEncryptionPadding.Pkcs1);
- }
-
- byte[] ed;
- {
- var msEd = new MemoryStream();
- using var cryptoTransform = aes.CreateEncryptor();
- var es = new CryptoStream(msEd, cryptoTransform, CryptoStreamMode.Write);
- var eBw = new BinaryWriter(es, Encoding.UTF8, true);
- eBw.WriteBlock(payload);
- if (sigPri != null)
- {
- var sign = sigPri.SignData(payload, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
- eBw.WriteBlock(sign);
- }
- eBw.Close();
- es.Close();
- ed = msEd.ToArray();
- }
-
- byte[] ret;
- {
- var msRet = new MemoryStream();
- var bw = new BinaryWriter(msRet, Encoding.UTF8, true);
- bw.WriteBlock(ek);
- bw.WriteBlock(ed);
- bw.Close();
- ret = msRet.ToArray();
- }
- return ret;
- }
- public static byte[] Decrypt(RSA decPri, byte[] dataToDecrypt) => DecryptAndVerifySignature(decPri, dataToDecrypt, null);
- public static byte[] DecryptAndVerifySignature(RSA decPri, byte[] dataToDecrypt, RSA? verPub)
- {
-
- byte[] ek, ed;
- {
- var ms = new MemoryStream(dataToDecrypt);
- var br = new BinaryReader(ms);
- ek = br.ReadBlock();
- ed = br.ReadBlock();
- }
- byte[] sk, iv;
- {
-
- var skIv = decPri.Decrypt(ek, RSAEncryptionPadding.Pkcs1);
- var msSkIv = new MemoryStream(skIv);
- var br = new BinaryReader(msSkIv);
- sk = br.ReadBlock();
- iv = br.ReadBlock();
- }
-
-
-
- byte[] decData;
- {
-
- var aes = Aes.Create();
- aes.Mode = CipherMode.CBC;
- aes.Padding = PaddingMode.PKCS7;
- aes.KeySize = 128;
- aes.BlockSize = 128;
- aes.Key = sk;
- aes.IV = iv;
- var msEd = new MemoryStream(ed);
- var msDec = new MemoryStream();
- var ds = new CryptoStream(msEd, aes.CreateDecryptor(), CryptoStreamMode.Read);
- ds.CopyTo(msDec);
- ds.Close();
- decData = msDec.ToArray();
- }
-
- byte[] payload;
- byte[]? signature = null;
- {
- var ms = new MemoryStream(decData);
- var br = new BinaryReader(ms);
- payload = br.ReadBlock();
- if (verPub != null)
- {
- if (ms.Position != ms.Length) signature = br.ReadBlock();
- else throw new SecurityException("Missing signature");
- }
- }
- if (signature == null || verPub == null) return payload;
-
- var r = verPub.VerifyData(payload, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
- if (r == false) throw new SecurityException("Signature verify fail");
-
- return payload;
- }
- }
|