PublicKey.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Mono.Math;
namespace YamRsa
{
class PublicKey
{
private const int HEX = 16;
public readonly BigInteger Module;
public readonly BigInteger Exponent;
public PublicKey(BigInteger m, BigInteger e)
{
Module = m;
Exponent = e;
}
///
/// Requires 0 <= plain < Module
///
///
public BigInteger Encrypt(BigInteger plain)
{
return plain.ModPow(Exponent, Module);
}
public static PublicKey FromString(string me)
{
var pair = me.Split(new[] {'#'}, 2);
if (pair.Length != 2)
throw new ArgumentException("Wrong format", "me");
return new PublicKey(ParseHex(pair[0]), ParseHex(pair[1]));
}
private static BigInteger ParseHex(IEnumerable hexString)
{
return hexString.Aggregate(new BigInteger(),
(integer, @char) => integer*HEX + int.Parse(new string(new[] {@char}), NumberStyles.AllowHexSpecifier));
}
public override string ToString()
{
return string.Format("{0}#{1}", Module.ToString(HEX), Exponent.ToString(HEX));
}
}
}
CryptoProviderRSA.cs
using System;
using System.Linq;
using Mono.Math;
namespace YamRsa
{
public class CryptoProviderRSA
{
private PublicKey _publicKey;
public void ImportPublicKey(string key)
{
_publicKey = PublicKey.FromString(key);
}
private const int MAX_CRYPT_BITS = 1024;
public byte[] Encrypt(byte[] data)
{
// must ensure that any data block would be < key's modulus
// hence -1
int portionLen = (_publicKey.Module.BitCount() - 1) / 8;
var prevCrypted = new byte[portionLen];
return Enumerable
.Range(0, ((data.Length - 1) / portionLen) + 1)
.Select(i => data.Skip(i * portionLen).Take(portionLen))
.SelectMany(portion =>
{
var portbuf = portion.Select((b, i) => (byte)(b ^ prevCrypted[i])).ToArray();
var cp = _publicKey.Encrypt(new BigInteger(portbuf)).GetBytes();
var length = Math.Min(portbuf.Length, cp.Length);
Array.Copy(cp, prevCrypted, length);
Array.Clear(prevCrypted, length, prevCrypted.Length - length);
return BitConverter.GetBytes((ushort)portbuf.Length)
.Concat(BitConverter.GetBytes((ushort)cp.Length))
.Concat(cp)
.ToArray();
})
.ToArray();
}
}
}
Program.cs
using System;
using System.Linq;
using System.Text;
namespace YamRsa
{
class Program
{
static void Main(string[] args)
{
var rsa = new CryptoProviderRSA();
rsa.ImportPublicKey(args[0]);
string data = @"";
var encoded = rsa.Encrypt(Encoding.ASCII.GetBytes(data));
Console.WriteLine(Convert.ToBase64String(encoded));
Console.ReadLine();
}
}
}