"
+ + "" + ( Bi2Base64(n_value ) ) + ""
+ + "" + ( Bi2Base64(e_value ) ) + ""
+ + "" + ( Bi2Base64(p_value ) ) + "
"
+ + "" + ( Bi2Base64(q_value ) ) + "
"
+ + "" + ( Bi2Base64(dp_value ) ) + ""
+ + "" + ( Bi2Base64(dq_value ) ) + ""
+ + "" + ( Bi2Base64(InverseQ_value ) ) + ""
+ + "" + ( Bi2Base64(d_value ) ) + ""
+ + "" //and replace to .
+ //This means was been generated as co-prime number and not last five Fermat's prime-number.
+ ;
+
+ xml_privKey = xml_privKey //format this string, as multiString, and replce
+ .Replace("<", "\n\t<")
+ .Replace(">",">\n\t\t")
+ .Replace("\t\t\n","")
+ .Replace("\t\n\t\t","")
+ .Replace("\n\t"
+ + "" + ( Bi2Base64(n_value ) ) + ""
+ + "" + ( Bi2Base64(e_value ) ) + ""
+ + "" //and replace to .
+ //This means was been generated as co-prime number and not last five Fermat's prime-number.
+ ;
+
+ xml_pubKey = xml_pubKey //format this string, as multiString, and replce
+ .Replace("<", "\n\t<")
+ .Replace(">",">\n\t\t")
+ .Replace("\t\t\n","")
+ .Replace("\t\n\t\t","")
+ .Replace("\n\t λ(n)) can be true.
+
+ // if( bi_e <= bi_d ){ //if e lesser or equals d
+ // BigInteger temp = bi_d; bi_d = bi_e; bi_e = temp; //swap bi_e <-> bi_d
+ // } //to return e, lesser than d, to keep secret a longer d.
+
+ BigInteger bi_dp = bi_d % (bi_p - 1); //dp = ( d mod (p−1) )
+ BigInteger bi_dq = bi_d % (bi_q - 1); //dq = ( d mod (q−1) )
+ BigInteger bi_InverseQ = bi_q.modInverse(bi_p); //inverseQ = ( q^(−1) mod p )
+
+ //Try to save this generated valued into rsa, pa_Priv, pa_Pub, or into BigIntegers.
+ //
+ // XML RSA-keys format:
+ //
+ // Base64-encoded-number
+ // Base64-encoded-number
+ // Base64-encoded-number
+ // Base64-encoded-number
+ // Base64-encoded-number
+ // Base64-encoded-number
+ // Base64-encoded-number
+ // Base64-encoded-number
+ //
+ //
+ // n - Modulus
+ // e - Exponent
+ // p - P
+ // q - Q
+ // d - D
+ //
+ // dp - DP, this is ( d mod (p−1) ),
+ // dq - DQ, this is ( d mod (q−1) ),
+ // InverseQ - this is ( q^(−1) mod p ).
+ //
+ // These are used in applying the Chinese Remainder Theorem to RSA decryption, which is an optimization technique.
+ //
+
+ try{
+ //Generate xml-string with RSA-privKey
+ string xmlString = ""
+ + ""
+ + "" + ( Bi2Base64( bi_n ) ) + ""
+ + "" + ( Bi2Base64( bi_e ) ) + ""
+ + "" + ( Bi2Base64( bi_p ) ) + "
"
+ + "" + ( Bi2Base64( bi_q ) ) + "
"
+ + "" + ( Bi2Base64( bi_dp ) ) + ""
+ + "" + ( Bi2Base64( bi_dq ) ) + ""
+ + "" + ( Bi2Base64( bi_InverseQ ) ) + ""
+ + "" + ( Bi2Base64( bi_d ) ) + ""
+ + ""
+ ;
+ //Format this as a multistring.
+ xmlString = xmlString
+ .Replace("<", "\n\t<")
+ .Replace(">",">\n\t\t")
+ .Replace("\t\t\n","")
+ .Replace("\t\n\t\t","")
+ .Replace("\n\t")) //if KeyFile, this is a string with key
+ ? KeyFile //use this string as xmlString
+ : System.IO.File.ReadAllText(KeyFile) //or open file and read XML-key from file with xml.
+ );
+ UseBigInteger = (xmlString.Contains("RSAKeyValueBigInteger")) ? true : UseBigInteger;
+
+ if(
+ !xmlString.Contains("RSAKeyValueBigInteger") //if BigInteger not been used to generate this key in xmlString
+ && UseBigInteger == false //and if no need to UseBigInteger, to load key into BigIntegers
+ ){ //Load this key into (rsa, pa_Priv, and pa_Pub)-values.
+
+ //extract public key from "key"-file with xmlString.
+ rsa.FromXmlString(xmlString); //and load key there, in RSACryptoServiceProvider rsa.
+
+ if(xmlString.Contains("")){ //if this was been a privkey, and this contains -value of privKey (d, n)
+ pa_Priv = rsa.ExportParameters(true); //export privateKey from this to pa_Priv
+ }
+ pa_Pub = rsa.ExportParameters(false); // (or/and) export the publicKey from this to pa_Pub.
+
+ //then, leave empty values for all those BigInteger:
+ n_value = new BigInteger();
+ e_value = new BigInteger();
+ p_value = new BigInteger();
+ q_value = new BigInteger();
+ dp_value = new BigInteger();
+ dq_value = new BigInteger();
+ InverseQ_value = new BigInteger();
+ d_value = new BigInteger();
+ }
+ else if ( //else if
+ xmlString.Contains("RSAKeyValueBigInteger") //BigInteger not been used to generate this key in xmlString
+ || UseBigInteger == true //or if need to load this key into BigInteger-values
+ //(for example, to do encrypt-by-priv, and decrypt-by-pub, using extended methods)
+ )
+ {
+ //Then, load this key, into BigInteger-values:
+
+ //Load values from xml-string
+ var LoadedKey = XElement.Parse(xmlString); //need to "using System.Xml";
+
+ if(xmlString.Contains("")){ //if this was been a privKey, and this contains -value
+ //decode values from base64 fields of XML - and import this into BigIntegers
+ n_value = B64ToBi((string)LoadedKey.Element("Modulus")); // n
+ e_value = B64ToBi((string)LoadedKey.Element("Exponent")); // e
+ p_value = B64ToBi((string)LoadedKey.Element("P")); // p
+ q_value = B64ToBi((string)LoadedKey.Element("Q")); // q
+ dp_value = B64ToBi((string)LoadedKey.Element("DP")); // dp
+ dq_value = B64ToBi((string)LoadedKey.Element("DQ")); // dq
+ InverseQ_value = B64ToBi((string)LoadedKey.Element("InverseQ")); // InverseQ
+ d_value = B64ToBi((string)LoadedKey.Element("D")); // d
+ }
+ else{ //else if this was been pubKey
+ e_value = B64ToBi((string)LoadedKey.Element("Exponent")); // e
+ n_value = B64ToBi((string)LoadedKey.Element("Modulus")); // n - (e, n)-only is a pubKey.
+ p_value = new BigInteger(); // and leave
+ q_value = new BigInteger(); // this values
+ dp_value = new BigInteger(); // all
+ dq_value = new BigInteger(); // as
+ InverseQ_value = new BigInteger(); // an empty
+ d_value = new BigInteger(); // values
+ }
+ }
+// Console.WriteLine("LoadKeyFile. KeyFile"+KeyFile+", SaveXMLKeys(UseBigInteger), UseBigInteger: "+UseBigInteger);
+ SaveXMLKeys(UseBigInteger);
+ //After all, key from keyFile, or from xmlString, is loaded into (rsa, pa_Priv, pa_Pub)-values, or into BigIntegers.
+ }
+
+
+//
+// EncryptFile, will encrypt file [src], into file [dest],
+// EncryptBytes, will encrypt bytearray [src], into bytearray [dest],
+// both will encrypt [src] to [dest]
+// by using pubkey from file [key],
+// or by using pubkey, which was been extracted from privkey in file [key],
+// or by using privKey from file [key], when byPriv == true (sign the message, and generate the digital signature).
+//
+// (d, n) - privkey, (e, n) - pubkey; e - public exponent, d - private exponent, n - modulus, c - ciphertext,
+// c = m ^ (e or d) mod n; - encryption by pubkey or privkey (sign),
+// m' = c ^ (d or e) mod n; - decryption by privkey or pubkey (extract message from signature to verify it),
+//
+// cypherBytelength = ( ( ( n_bitlength - ( n_bitlength % 8 ) ) / 8 ) + ((( n_bitlength % 8 ) > 0)?1:0) );
+// File will be splitted by blocks with ( cypherBytelength - 1 ) bytes.
+// This blocks will be encrypted by pubkey from "key", or pubkey which is extracted from prikey "key".
+// Pubkey - is (e, n), where n, this is a modulus - a big number with specified n_bitlength.
+// The result ciphertext have n_bitlength bits, or cypherBytelength bytes, and will be writted by blocks in encrypted file.
+//
+// Last block will be encrypted as is, but after encrypted block will be added ulong-value (8 bytes) with LastBlockLength.
+//
+
+ public static int SubtractBytes, block_size, block_length; //define this variables.
+
+ public static int bitLength(BigInteger value){
+// Console.WriteLine("bitLength - value:"+value.ToString());
+ int bitLength = 0;
+ do
+ {
+ bitLength++;
+ value /= 2;
+ } while(value != 0);
+// Console.WriteLine("bitLength - bitLength:"+bitLength);
+// Console.WriteLine("bitLength - value.byteLength:"+value.getBytes().Length);
+ return bitLength;
+ }
+
+ private static void set_lengths( //set lengths of blocks to read-write
+ int n_bitlength //bitlength of modulus n from KeyFile
+ , bool UseBigInteger = false //Use BigInteger to encrypt-decrypt-data or not? true/false
+ )
+ {
+// Console.WriteLine("set_lengths - n_bitlength: "+n_bitlength);
+ //
+ // For rsa.Encrypt() and rsa.Decrypt():
+ // Having looked at some of the information on RSA encryption modes,
+ // it would appear that PKCS#1 v1.5 (which is calling as rsa.Encrypt(..., false), and rsa.Decrypt(..., false))
+ // "...can operate on messages of length up to k - 11 octets (k is the octet length of the RSA modulus)"
+ //
+ // For BigInteger.EncryptFile(), BigInteger.EncryptBytes(), BigInteger.DecryptFile(), BigInteger.DecryptBytes():
+ // dest_maxBitLength = n_bitlength;
+ // dest_maxBitLength = ( ( ( n_bitlength - ( n_bitlength % 8 ) ) / 8 ) + ((( n_bitlength % 8 ) > 0)?1:0) );
+ // where "dest_maxBitLength" - n_bitlength of modulus n-value in key.
+ //
+ // src_maxBitlength = dest_maxBitLength - 1;
+ // src_maxByteLength = dest_maxBitLength - 1;
+ //
+
+ //set this values:
+ SubtractBytes = ((UseBigInteger == true ) ? 1 : 11); //select how many bytes need to subtract from each block.
+
+ block_size = ( //block length for destination file = n_bytelength (+ 1, when n_bitlength%8 > 0).
+ (
+ (
+ n_bitlength
+ -
+ ( n_bitlength % 8 )
+ )
+ /
+ 8
+ )
+ +
+ (
+ (
+ ( n_bitlength % 8 ) > 0
+ )
+ ? 1
+ : 0
+ )
+ );
+ block_length = block_size-SubtractBytes; //block length for source file
+
+ return; //and return, then.
+ }
+
+//
+// Encrypt file [src], into file [dest], by using pubkey from file [key],
+// or by using pubkey, which was been extracted from privkey in file [key].
+// (d, n) - privkey, (e, n) - pubkey;
+// c = m ^ e mod n; - encryption by public key
+// m' = c ^ d mod n; - decryption by private key.
+//
+// File will be splitted by blocks with ((bitlength/8) - 1) bytes.
+// This blocks will be encrypted by pubkey from "key", or pubkey which is extracted from prikey "key".
+// Pubkey - is (e, n), where n, this is a modulus - a big number with specified n_bitlength.
+// The result ciphertext have n_bitlength bits, and will be writted by blocks in encrypted file.
+//
+// Last block will be encrypted as is, but after encrypted block will be added ulong-value (8 bytes) with LastBlockLength.
+//
+
+
+ //
+ // Encryption file or bytearray:
+ // 1. Read file by blocks (KeyLength-SubtractBytes)
+ // 2. Encrypt each block by pub or priv, and write this in the block with KeyLength.
+ // 3. Block-by-block, up to the end of file.
+ // 4. Add ulong value (8 bytes) with length of last block, in the end of encrypted data.
+ // 6. Write this all in file, or in bytearray.
+ //
+ // Three methods used to encrypt data:
+ // public static void EncryptFullBlockOrLastBlock - encrypt one block, and write this in ref.
+ // public static byte[] EncryptFullBlockOrLastBlock - return bytearray.
+ // public static void EncryptFile - encrypt, and write as file
+ // private static void EncryptBytes - encrypt and write bytearray by ref
+ // public static byte[] EncryptBytes - encrypt, and return bytearray.
+ //
+
+
+ //
+ // Encrypt one block from "buffer", with "block_size", in each iteration of read "data",
+ // or encrypt last block in "buffer" with length "c",
+ // and save the encrypted ciphertext in "encbuffer", by reference (ref).
+ // Encrypt this by pubkey, which is contains in "rsa",
+ // and encrypt with rsa.Encrypt(), or BigInteger modPow method - UseBigInteger (true/false);
+ //
+ // This method will be called on each iteratio of reading blocks of "source data",
+ // as from an FileStream, or MemoryStream.
+ //
+ // Encrypted data will contains in "encbuffer".
+ //
+
+
+ public static void EncryptFullBlockOrLastBlock( //encrypt full block or last block inside the cycles.
+ ref RSACryptoServiceProvider rsa //RSACryptoServiceProvider, with imported pubKey
+ , ref byte[] buffer //readed buffer from the source file
+ , ref byte[] encbuffer //already defined encbuffer, as reference
+ , ref int block_size //already defined block_size, as reference
+ , ref int c //number of readed bytes, as reference
+ , ref bool UseBigInteger //use BigInteger or not? true/false
+ , ref BigInteger ed //(if UseBigInteger = true, then) ed - e or d. e (public exponent), if encrypt by pubkey (e, n); or d (secret exponent), if encrypt by privkey (d, n)
+ , ref BigInteger n //(if UseBigInteger = true, then) n - modulus
+ )
+ {
+// Console.WriteLine("ed: "+ed.ToString());
+// Console.WriteLine("n: "+n.ToString());
+ encbuffer = new byte[block_size]; //create new encbuffer with block_size.
+ if (c == buffer.Length) //if this was been readed a full block, and not a last block - just encrypt it.
+ {
+ if(UseBigInteger == false){ //if no need to use BigInteger modPow to encrypt
+ encbuffer = rsa.Encrypt(buffer, false); //just encrypt by using rsa.Encrypt()
+ }else{ //else
+// Console.WriteLine("(new BigInteger (buffer))"+(new BigInteger (buffer)));
+
+ //use BigInteger
+ byte[] encryptedBuffer; //define new bytearray for encryptedBuffer (this can have a different bytelength)
+ encryptedBuffer = ( //and encrypt there
+ (new BigInteger (buffer)) //the buffer
+ .modPow ( //by using modPow method
+ ed, //to encrypt this buffer, into BigInteger, by e or d
+ n //and modulus n
+ )
+ )
+ .getBytes() //and getBytes from this result-BigInteger.
+ ;
+// Console.WriteLine("(new BigInteger (encryptedBuffer))"+(new BigInteger (encryptedBuffer)));
+ //independent of bytelength of result bytearray, write this in the encbuffer
+ Buffer.BlockCopy(encryptedBuffer, 0, encbuffer, (encbuffer.Length-encryptedBuffer.Length), encryptedBuffer.Length);
+ }
+ }
+ else //else if last block, and readed bytes not equals of buffer length.
+ {
+ //slice this buffer up to c-value:
+ byte[] buffer2 = new byte[c];
+ for (int i = 0; i < c; i++){
+ buffer2[i] = buffer[i];
+ }
+
+ if(UseBigInteger == false){ //if no need to use BigInteger to encrypt
+ encbuffer = rsa.Encrypt(buffer2, false); //just use rsa.Encrypt()
+ }else{ //else
+// Console.WriteLine("(new BigInteger (buffer2))"+(new BigInteger (buffer2)));
+ //use BigInteger
+ byte[] encryptedBuffer; //define new encrypted buffer for result, this can have different length
+ encryptedBuffer = ( //and encrypt
+ (new BigInteger (buffer2)) //buffer2
+ .modPow (ed, n) //by using BigInteger modPow method
+ )
+ .getBytes() //and get bytes from result BigInteger, then.
+ ;
+// Console.WriteLine("(new BigInteger (encryptedBuffer))"+(new BigInteger (encryptedBuffer)));
+
+ //after this, write bytes of result BigInteger with cypher, into encbuffer, independent of bytelength of this result.
+ Buffer.BlockCopy(encryptedBuffer, 0, encbuffer, (encbuffer.Length-encryptedBuffer.Length), encryptedBuffer.Length);
+ }
+
+ //After encryption of last block of the source data, add ulong with the length of this block, in the end of encrypted result.
+ if(UseBigInteger == true){ //only if BigInteger modPow used for encryption
+ ulong number = Convert.ToUInt64(c); //the number of readed data bytes
+ byte[] LastBlockLength = new byte[8]; //create bytearray with 8 bytes
+ LastBlockLength = BitConverter.GetBytes(number); //convert ulong to bytearray
+ if (BitConverter.IsLittleEndian){ //if this bytes was been LittleEndian
+ Array.Reverse(LastBlockLength); //Reverse the bytearray
+ }
+
+ encbuffer = Combine(encbuffer, LastBlockLength); //and append this 8 bytes with ulong value in the end of encrypted data
+ }
+ }
+ //after this all, encbuffer by that reference, will contains an encrypted ciphertext, and this can be writted.
+ }
+
+ public static byte[] EncryptFullBlockOrLastBlock( //The same, but this method will return encbuffer, as bytearray.
+ ref RSACryptoServiceProvider rsa //RSACryptoServiceProvider, where pubKey is already imported.
+ , ref byte[] buffer //readed buffer
+ , ref int block_size //block_size of this
+ , ref int c //length of readed buffer
+ , ref bool UseBigInteger //encrypt with BigInteger modPow method - true, or with rsa.Encrypt() - false;
+ , ref BigInteger ed
+ , ref BigInteger n
+ )
+ {
+ byte[] encbuffer = new byte[block_size]; //define encbuffer, as a bytearray
+
+ EncryptFullBlockOrLastBlock( //encrypt
+ ref rsa,
+ ref buffer,
+ ref encbuffer, //and save result in encbuffer by reference
+ ref block_size,
+ ref c,
+ ref UseBigInteger,
+ ref ed,
+ ref n
+ );
+
+ return encbuffer; //return encbuffer.
+ }
+
+ public static void EncryptFile( //Encrypt src-file to dest-file by pubKey or privKey
+ string key="" //key for encrypt - the file/xml-string pub, or with xml-priv, to get pub from it, if byPriv == false, else with priv.
+ , string src = "" //src - input file to encrypt
+ , string dest = "" //dest - output file save encryted ciphertext
+ , bool UseBigInteger = false //true - use, false - use rsa.Encrypt() and rsa.Decrypt()
+ , bool byPriv = false //default encryption, by publicKey - false, else - true, and encrypt by priv, to decrypt by pub (sign the message, to verify result cipher as signature).
+ )
+ {
+ LoadKeyFile(key); //extract public key from "key"-file with xml.
+
+ int n_bitlength = 0;
+
+ if(UseBigInteger == false){
+ n_bitlength = rsa.KeySize; //then, get n_bitlength of modulus from RSA-key.
+ }
+ else{
+ //n_bitlength = n_value.dataLength * 32;
+ n_bitlength = bitLength(n_value);
+ }
+
+ //create two FileStreams
+ System.IO.FileStream fin = System.IO.File.Open(src, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //FileStream for input file
+ System.IO.FileStream fout = System.IO.File.Open(dest, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.Write); //FileStream for output file
+
+ //and try to encrypt the source file "src", with this pubkey.
+ try
+ {
+ set_lengths(n_bitlength, UseBigInteger);
+
+ System.IO.FileInfo finfo = new System.IO.FileInfo( src ); //get file info of src-file
+
+ byte[] buffer = new byte[ block_length ]; //set size of block to read the source file
+ byte[] encbuffer = new byte[ block_size ]; //set size of block to write in destination encrypted file
+ int c = 0; //srart value of count = 0
+
+ BigInteger ed = null;
+ BigInteger n = null;
+
+ if(UseBigInteger == false){ //if no need to use BigInteger
+ ed = (
+ (byPriv == true) //if byPriv == true
+ ? new BigInteger (pa_Priv.D) //then, d -> to BigInteger
+ : new BigInteger (pa_Pub.Exponent) //else, e -> to BigInteger
+ );
+ n = (new BigInteger (pa_Pub.Modulus)); //n -> to BigInteger
+ }else{ //else, if UseBigInteger:
+ ed = (
+ (byPriv == true) //if byPriv == true
+ ? d_value //then, d -> to BigInteger
+ : e_value //else, e -> to BigInteger
+ );
+ n = n_value; //n -> to BigInteger
+ }
+ while ((c = fin.Read(buffer, 0, block_length )) > 0) //for each block of readed source file, including the last block
+ {
+ //encrypt by pub into the encbuffer, using rsa.Encrypt() or BigInteger.
+ encbuffer = EncryptFullBlockOrLastBlock(ref rsa, ref buffer, ref block_size, ref c, ref UseBigInteger, ref ed, ref n);
+ fout.Write(encbuffer, 0, encbuffer.Length); //and write encbuffer into the destination file.
+ }
+ fin.Close(); //after all, close input file
+ fout.Close(); //and close output file
+ }
+ catch (Exception ex) //if try fails, show throw exception
+ {
+ fin.Close();
+ fout.Close();
+ Console.WriteLine( "\nError:" + ex);
+ }
+ }
+
+
+ // Encrypt bytearray from src to dest, by using pubkey in key, and encrypt it with BigInteger modPow, or with rsa.Encrypt();
+
+ private static void EncryptBytes( //The same but encrypt bytearrays, anc create MemoryStreams, instead of FileStreams
+ string key //key - pub, for encrypt, or priv, to get pub from it, and encrypt then, if byPriv == false. This can be xml-string with key too.
+ , ref byte[] src //reference to bytearray with source data
+ , ref byte[] dest //reference to bytearray with destination cipher data
+ , bool UseBigInteger = false //Need use BigInteger, or use rsa.Encrypt()? true/false
+ , bool byPriv = false //encrypt by privKey to sing the message, and decrypt by pubKey, then.
+ )
+ {
+ LoadKeyFile(key, UseBigInteger); //extract public key from "key"-file with xml.
+ int n_bitlength = 0;
+
+ if(UseBigInteger == false){
+ n_bitlength = rsa.KeySize; //then, get n_bitlength of RSA-key.
+ }
+ else{
+ //n_bitlength = n_value.dataLength * 32;
+ n_bitlength = bitLength(n_value);
+ }
+
+ MemoryStream fin = new MemoryStream(src); //Create new MemoryStream for src
+ MemoryStream fout = new MemoryStream(); //Create new MemoryStream for dest
+
+ try
+ {
+ set_lengths(n_bitlength, UseBigInteger);
+
+ byte[] buffer = new byte[ block_length ];
+ byte[] encbuffer = new byte[ block_size ];
+ int c = 0;
+
+ BigInteger ed = null;
+ BigInteger n = null;
+
+ if(UseBigInteger == false){ //if no need to use BigInteger
+ ed = (
+ (byPriv == true) //if byPriv == true
+ ? new BigInteger (pa_Priv.D) //then, d -> to BigInteger
+ : new BigInteger (pa_Pub.Exponent) //else, e -> to BigInteger
+ );
+ n = (new BigInteger (pa_Pub.Modulus)); //n -> to BigInteger
+ }else{ //else, if UseBigInteger:
+ ed = (
+ (byPriv == true) //if byPriv == true
+ ? d_value //then, d -> to BigInteger
+ : e_value //else, e -> to BigInteger
+ );
+ n = n_value; //n -> to BigInteger
+ }
+
+ while ((c = fin.Read(buffer, 0, block_length )) > 0)
+ {
+ Console.WriteLine("enc: buffer: "+BitConverter.ToString(buffer).Replace("-", string.Empty)+" "+buffer.Length);
+ //encrypt by pub or priv into the encbuffer, using rsa.Encrypt() or BigInteger.
+ encbuffer = EncryptFullBlockOrLastBlock(ref rsa, ref buffer, ref block_size, ref c, ref UseBigInteger, ref ed, ref n);
+ fout.Write(encbuffer, 0, encbuffer.Length); //and write encbuffer into the destination file.
+ Console.WriteLine("enc: encbuffer: "+BitConverter.ToString(encbuffer).Replace("-", string.Empty)+" "+encbuffer.Length);
+ buffer = new byte[ block_length ];
+ }
+ fin.Close();
+ dest = fout.ToArray();
+ fout.Close();
+ }
+ catch (Exception ex)
+ {
+ fin.Close();
+ dest = fout.ToArray();
+ fout.Close();
+ Console.WriteLine( "\nError:" + ex);
+ }
+ }
+
+
+ // return "dest"-bytearray
+
+ public static byte[] EncryptBytes( //The same, but return "dest"-bytearray with encrypted-cipher
+ string key
+ , byte[] src
+ , bool UseBigInteger = false
+ , bool byPriv = false
+ )
+ {
+ byte[] dest = new byte[0];
+ EncryptBytes(
+ key
+ , ref src
+ , ref dest
+ , UseBigInteger
+ , byPriv
+ );
+ return dest;
+ }
+
+
+
+ //
+ // Decryption file or bytearray:
+ // 1. Read file by blocks with KeyLength
+ // 2. Decrypt each block by pub or priv, and write this in the block with (KeyLength-SubtractBytes).
+ // 3. Block-by-block, up to the end of file.
+ // 4. skip ulong value (8 bytes) with length of last block, in the end of encrypted data.
+ // 6. Write this all in file, or in bytearray.
+ //
+ // Three methods used to encrypt data:
+ // public static void DecryptFullBlockOrLastBlock - decrypt one block, and write this in ref.
+ // public static byte[] DecryptFullBlockOrLastBlock - return bytearray.
+ // public static void DecryptFile - decrypt file, and write as file.
+ // private static void DecryptBytes - decrypt bytearray, and write bytearray by ref
+ // public static byte[] DecryptBytes - decrypt and return bytearray
+ //
+
+
+
+ //
+ // Decrypt one block from "buffer", with "block_size", in each iteration of read "cipherdata",
+ // or encrypt last block in "buffer" with length "c",
+ // and save the encrypted ciphertext in "encbuffer", by reference (ref).
+ // Encrypt this by pubkey, which is contains in "rsa",
+ // and encrypt with rsa.Encrypt(), or BigInteger modPow method - UseBigInteger (true/false);
+ //
+ // This method will be called on each iteration of reading blocks of "source data",
+ // as from an FileStream, or MemoryStream.
+ //
+ // Encrypted data will contains in "encbuffer".
+ //
+
+ public static void DecryptFullBlockOrLastBlock( //Decrypt full block or last block inside the cycle.
+ ref RSACryptoServiceProvider rsa //RSACryptoServiceProvider, with imported pubKey
+ , ref byte[] buffer //readed buffer from the source file
+ , ref byte[] decbuffer //already defined decbuffer, as reference
+ , ref int block_size //already defined block_size, as reference
+ , ref int c //number of readed bytes, as reference
+ , ref bool isNextUlong //is next value ulong or not? true/false
+ , bool UseBigInteger = false //use BigInteger or not? true/false
+ , int dataLength = 0 //Length of data
+ , BigInteger de = null //de - d or e. d (secret exponent) - if decrypt by priv (d, n), (by default); or e (pubic exponent) - if decrypt by pub (verify signature)
+ , BigInteger n = null //n - modulus
+ , int current_block = 0 //number of the current block
+ , int max_blocks = 0 //number of the max block to decrypt
+ , ulong length__ = 0 //length of last block
+ )
+ {
+ if(UseBigInteger == true){
+ //rewrite buffer, when this is a last block, and have no block_length size.
+ if (c != block_size)
+ {
+ byte[] buffer2 = new byte[c];
+ for (int i = 0; i < c; i++){
+ buffer2[i] = buffer[i];
+ }
+ buffer = buffer2;
+ }
+
+ int rest = (int)( dataLength - ( current_block * block_size ) );
+ if ( rest <= 0 ){
+ //here is full ulong, in this block
+
+ //slice buffer on 8 bytes, and cut ulong-value
+ byte[] NewBuffer = new byte[buffer.Length-8];
+ Buffer.BlockCopy(buffer, 0, NewBuffer, 0, NewBuffer.Length);
+ buffer = NewBuffer;
+ }
+ else if ( rest < 8 ){
+ //here is the partial of ulong, in this block, and partial in the next block.
+
+ int PartOfLenHere = 8 - rest; //number of bytes in this block
+
+ //slice buffer on PartOfLenHere bytes, and cut ulong-value
+ byte[] NewBuffer = new byte[buffer.Length-PartOfLenHere];
+ Buffer.BlockCopy(buffer, 0, NewBuffer, 0, NewBuffer.Length);
+ buffer = NewBuffer;
+ isNextUlong = true;
+ }
+ else if ( rest == 8 ){
+ return;
+ }
+ }
+
+ if(UseBigInteger == false){
+ decbuffer = rsa.Decrypt(buffer, false);
+ }
+ else{
+ int BufferLength = ( ( current_block == max_blocks-1 ) ? (int)length__ : ( block_size - SubtractBytes ) ); //length__ !
+ byte[] decryptedBuffer = new byte[ BufferLength ];
+ decbuffer = new byte[ BufferLength ];
+
+ decryptedBuffer = (
+ (new BigInteger (buffer))
+ .modPow(de, n)
+ )
+ .getBytes()
+ ;
+
+ Buffer.BlockCopy(decryptedBuffer, 0, decbuffer, (decbuffer.Length-decryptedBuffer.Length), decryptedBuffer.Length);
+ }
+ //after this all, decrypted value will contains in decbuffer by reference.
+ }
+
+
+ // This method will return encbuffer, as bytearray.
+
+ public static byte[] DecryptFullBlockOrLastBlock( //decrypt full block or last block inside the cycle.
+ ref RSACryptoServiceProvider rsa //RSACryptoServiceProvider, with imported pubKey
+ , ref byte[] buffer //readed buffer from the source file
+ , ref int block_size //already defined block_size, as reference
+ , ref int c //number of readed bytes, as reference
+ , ref bool isNextUlong //is next value ulong or not? true/false
+ , bool UseBigInteger = false //use BigInteger or not? true/false
+ , int dataLength = 0 //Length of data
+ , BigInteger de = null //de - d or e. d (secret exponent) - if decrypt by priv (d, n), (by default); or e (pubic exponent) - if decrypt by pub (verify signature)
+ , BigInteger n = null //n - modulus
+ , int current_block = 0 //number of the current block
+ , int max_blocks = 0 //number of the max block to decrypt
+ , ulong length__ = 0 //length of last block
+ )
+ {
+ byte[] decbuffer = new byte[0]; //define encbuffer, as a bytearray
+
+ //encrypt full block or last block inside the cycle.
+ DecryptFullBlockOrLastBlock(
+ ref rsa //RSACryptoServiceProvider, with imported pubKey
+ , ref buffer //readed buffer from the source file
+ , ref decbuffer //already defined decbuffer, as reference
+ , ref block_size //already defined block_size, as reference
+ , ref c //number of readed bytes, as reference
+ , ref isNextUlong //is next value ulong or not? true/false
+ , UseBigInteger //use BigInteger or not? true/false
+ , dataLength //Length of data
+ , de //de - d or e. d (secret exponent) - if decrypt by priv (d, n), (by default); or e (pubic exponent) - if decrypt by pub (verify signature)
+ , n //n - modulus
+ , current_block //number of the current block
+ , max_blocks //number of the max block to decrypt
+ , length__ //length of last block
+ );
+ return decbuffer; //return decbuffer.
+ }
+
+
+ //
+ // Decrypt encrypted file, by priv.
+ // (d, n) - privkey, where n have n_bitlength size, and n_bytelength.
+ // encrypted file readed by blocks with n_bytelength,
+ // this block will be decrypted, then result will writted to blocks with bytelength (n_bytelenght - 1).
+ // Last 8 bytes of encrypted file, this is ulong value with bytelength of last block.
+ // This value will be readed at beginning, and then this value need to skip, and slice the bytes of last block, then.
+ //
+ public static void DecryptFile(
+ string key = "" //privKey to decrypt by default, or pubKey of owners, to verify the signature, by encrypting the message by owner's privKey
+ , string src = ""
+ , string dest = ""
+ , bool UseBigInteger = false
+ , bool byPub = false
+ )
+ {
+ ulong length__ = 0; //define this ulong as 0
+
+ if(UseBigInteger == true) //if BigInteger modPow used for decryption, then this was been encrypted with modPow.
+ {
+ //read 8 bytes with last block length from the end of file.
+ byte[] LastBlockLength = new byte[8]; //8 bytes
+ using (BinaryReader reader = new BinaryReader(new FileStream(src , FileMode.Open))) //open file
+ {
+ reader.BaseStream.Seek( ( ( new System.IO.FileInfo( src ) ).Length - 8 ), SeekOrigin.Begin); //and read from the end
+ reader.Read(LastBlockLength, 0, 8); //8 bytes
+ reader.Close(); //then close file
+ reader.Dispose();
+ }
+ BigInteger LastBlockLength_Bi = (new BigInteger (LastBlockLength)); //convert LastBlockLength to BigInteger
+ length__ = Convert.ToUInt64(LastBlockLength_Bi.ToString()); //then convert this to ulong.
+ }
+ //else, ulong value with last block length, is not contains in the end of file, in last 8 bytes.
+
+ //open src and dest files as FileStreams
+ System.IO.FileStream fin = System.IO.File.Open ( src, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //src
+ System.IO.FileStream fout = System.IO.File.Open ( dest, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.Write); //dest
+
+ //and try to decrypt src
+ try
+ {
+
+ LoadKeyFile(key, UseBigInteger); //extract public key from "key"-file with xml.
+ int n_bitlength = 0;
+ if(UseBigInteger == false){
+ n_bitlength = rsa.KeySize; //then, get n_bitlength of modulus from RSA-key.
+ }
+ else{
+ //n_bitlength = n_value.dataLength * 32;
+ n_bitlength = bitLength(n_value);
+ }
+
+ set_lengths(n_bitlength, UseBigInteger);
+
+ System.IO.FileInfo finfo = new System.IO.FileInfo(src); //create FileInfo for encrypted-file, to get length of this.
+ int dataLength = (int)finfo.Length; //get length of file.
+
+ byte[] buffer = new byte[block_size]; //define buffer with length of block for reading encrypted file
+ byte[] decbuffer = new byte[block_length]; //define decbuffer with length of block for write decrypted file
+
+ BigInteger de, n;
+ if(UseBigInteger == false)
+ {
+ de = (
+ (byPub == true)
+ ? new BigInteger (pa_Pub.Exponent)
+ : new BigInteger (pa_Priv.D)
+ ); //extract secret exponent, and convert to BigInteger.
+ n = (
+ new BigInteger (
+ (
+ (byPub == true)
+ ? pa_Pub
+ : pa_Priv
+ ).Modulus
+ )
+ ); //extract modulus and confert to BigInteger.
+ }
+ else{
+ de = ( (byPub == true) ? e_value : d_value);
+ n = n_value;
+ }
+
+ int max_blocks = (int)(finfo.Length / block_size);
+ int current_block = 0;
+
+ int c = 0;
+
+ bool isNextUlong = false;
+
+ while ((c = fin.Read(buffer, 0, block_size)) > 0) //читать файл блоками по block_size
+ {
+ if(UseBigInteger == true && isNextUlong == true){
+ break;
+ }
+
+ decbuffer = DecryptFullBlockOrLastBlock(
+ ref rsa
+ , ref buffer
+ , ref block_size
+ , ref c
+ , ref isNextUlong
+ , UseBigInteger
+ , dataLength
+ , de
+ , n
+ , current_block
+ , max_blocks
+ , length__
+ );
+
+ fout.Write(decbuffer, 0, decbuffer.Length); //write this later.
+ current_block += 1;
+ }
+ fin.Close();
+ fout.Close();
+ }
+ catch (ArgumentException e)// when (e.ParamName == "…")
+ {
+ fin.Close();
+ fout.Close();
+ Console.WriteLine(e.ParamName);
+ }
+ catch (Exception ex)
+ {
+ fin.Close();
+ fout.Close();
+ Console.WriteLine(ex);
+ }
+ }
+
+ //
+ // Decrypt encrypted bytearray with cipher, by priv.
+ // (d, n) - privkey, where n have n_bitlength size, and n_bytelength.
+ // encrypted file readed by blocks with n_bytelength,
+ // this block will be decrypted, then result will writted to blocks with bytelength (n_bytelenght - 1).
+ // Last 8 bytes of encrypted file, this is ulong value with bytelength of last block.
+ // This value will be readed at beginning, and then this value need to skip, and slice the bytes of last block, then.
+ //
+ private static void DecryptBytes(
+ string key //file with priv or pub
+ , ref byte[] src //reference on src-bytes
+ , ref byte[] dest //reference on dest-bytes
+ , bool UseBigInteger = false //UseBigInteger or not? true/false
+ , bool byPub = false
+ )
+ {
+ ulong length__ = 0;
+ if(UseBigInteger == true)
+ {
+ //read 8 bytes with last block length from the end of file.
+ byte[] LastBlockLength = new byte[8];
+
+ Buffer.BlockCopy(src, src.Length-8, LastBlockLength, 0, 8);
+
+ BigInteger LastBlockLength_Bi = (new BigInteger (LastBlockLength));
+
+ length__ = Convert.ToUInt64(LastBlockLength_Bi.ToString());
+ }
+
+ int dataLength = src.Length; //get length of src.
+
+ MemoryStream fin = new MemoryStream(src);
+ MemoryStream fout = new MemoryStream();
+
+ try
+ {
+ LoadKeyFile(key, UseBigInteger); //extract public key from "key"-file with xml.
+
+ int n_bitlength = 0;
+ if(UseBigInteger == false){
+ n_bitlength = rsa.KeySize; //then, get n_bitlength of modulus from RSA-key.
+ }
+ else{
+ //n_bitlength = n_value.dataLength * 32;
+ n_bitlength = bitLength(n_value);
+ }
+
+ set_lengths(n_bitlength, UseBigInteger);
+
+
+ byte[] buffer = new byte[block_size];
+ byte[] decbuffer = new byte[block_length];
+
+ BigInteger de, n;
+ if(UseBigInteger == false)
+ {
+ de = (
+ (byPub == true)
+ ? new BigInteger (pa_Pub.Exponent)
+ : new BigInteger (pa_Priv.D)
+ ); //extract secret exponent, and convert to BigInteger.
+ n = (
+ new BigInteger (
+ (
+ (byPub == true)
+ ? pa_Pub
+ : pa_Priv
+ ).Modulus
+ )
+ ); //extract modulus and confert to BigInteger.
+ }
+ else{
+ de = ( (byPub == true) ? e_value : d_value);
+ n = n_value;
+ }
+
+ int max_blocks = (int)(src.Length / block_size);
+ int current_block = 0;
+
+ int c = 0;
+
+ bool isNextUlong = false;
+ while ((c = fin.Read(buffer, 0, block_size)) > 0) //читать файл блоками по block_size
+ {
+
+// Console.WriteLine("dec: buffer: "+BitConverter.ToString(buffer).Replace("-", string.Empty)+" "+buffer.Length);
+
+ decbuffer = DecryptFullBlockOrLastBlock(
+ ref rsa
+ , ref buffer
+ , ref block_size
+ , ref c
+ , ref isNextUlong
+ , UseBigInteger
+ , dataLength
+ , de
+ , n
+ , current_block
+ , max_blocks
+ , length__
+ );
+
+ if(UseBigInteger == true && isNextUlong == true){
+ break;
+ }
+
+ fout.Write(decbuffer, 0, decbuffer.Length); //write this later.
+ current_block += 1;
+
+// Console.WriteLine("dec: decbuffer: "+BitConverter.ToString(decbuffer).Replace("-", string.Empty)+" "+decbuffer.Length);
+
+ }
+ fin.Close();
+ dest = fout.ToArray();
+ fout.Close();
+ }
+ catch (ArgumentException)// e)// when (e.ParamName == "…")
+ {
+ fin.Close();
+ dest = fout.ToArray();
+ fout.Close();
+ //Console.WriteLine(e + ", "+e.ParamName);
+ }
+ catch (Exception ex)
+ {
+ fin.Close();
+ dest = fout.ToArray();
+ fout.Close();
+ Console.WriteLine(ex);
+ }
+ }
+
+ //return "dest"-bytearray
+ public static byte[] DecryptBytes(
+ string key
+ , byte[] src
+ , bool UseBigInteger = false
+ , bool byPub = false
+ )
+ {
+ byte[] dest = new byte[0];
+
+ try{
+ DecryptBytes(
+ key
+ , ref src
+ , ref dest
+ , UseBigInteger
+ , byPub
+ );
+ }
+ catch(Exception ex){
+ Console.WriteLine(ex);
+ }
+ return dest;
+ }
+ //--------------------END RSABigInteger.--------------------
+
}
+
+public static class RsaExtensions
+{
+//
+// The following extensions for RSACryptoServiceProvider, allow to encrypt data by priv, and decrypt by pub, without UseBigIngeter = true;
+//
+// RSACryptoServiceProvider.Encrypt() can encrypt only by pub.
+// RSACryptoServiceProvider.Decrypt() can decrypt only by priv.
+// encryption by priv, and decryption by pub - is not supported.
+// rsa.Decrypt() can not find priv to decrypt, when trying to decrypt by pub.
+// Encryption by priv, and decryption by pub - this is signing and verify RSA-operations.
+// But, using RSACryptoServiceProvider's methods, this working with hash of data, not with data.
+// Signing, and verify digital RSA signature, have the following scheme:
+// s = m ^ d mod n; - (compute signature): "encrypt" by priv "(d, n)" the message "m", into sinature "s"
+// send (m, s)
+// m_ = s ^ e mod n; - (extract message): "decrypt" by pub (e, n) the signature s, into message m_
+// compare m and m_ - (verify signature): "compare" an existing "m", and "m_".
+//
+// //Usage:
+// // BigInteger.LoadKeyFile("privateKeyXmlFile.txt"); //load privkey to (rsa, pa_Priv, pa_pub)-values, or BigIntegers.
+// // byte[] encryptByPriv = (BigInteger.rsa).EncryptByPrivateKey(sourceBytes); //return bytes
+// // byte[] decryptByPub = (BigInteger.rsa).DecryptByPublicKey(encryptByPriv); //return bytes
+// // Console.WriteLine("CompareBytes: "+BigInteger.CompareBytes(decryptByPub, sourceBytes)); //must to be true.
+//
+//
+
+ //Usage: byte[] EncryptedBytes = (BigInteger.rsa).EncryptByPrivateKey(sourceBytes); //return EncryptedBytes
+ public static byte[] EncryptByPrivateKey(
+ this RSACryptoServiceProvider rsaWithPriv
+ , byte[] data
+ , string key = ""
+ )
+ {
+ if (data == null){
+ throw new ArgumentNullException("data");
+ }
+ if (
+ (
+ ( key == "" )
+ && (rsaWithPriv.PublicOnly)
+ )
+ ||
+ (
+ (key != "")
+ && (!key.Contains(""))
+ )
+ ){
+ throw new InvalidOperationException("Private key is not loaded");
+ }
+ byte[] encryptBytesByBigIntegerPriv = BigInteger.EncryptBytes(
+ (
+ (key != "")
+ ? key
+ : rsaWithPriv.ToXmlString(true)
+ ),
+ data, true, true
+ )
+ ;
+ return encryptBytesByBigIntegerPriv;
+ }
+
+ //Usage: byte[] DecryptedBytes = (BigInteger.rsa).DecryptByPublicKey(sourceBytes); //return DecryptedBytes
+ public static byte[] DecryptByPublicKey(
+ this RSACryptoServiceProvider rsaWithPrivPub
+ , byte[] cipherData
+ , string key = ""
+ )
+ {
+ if (cipherData == null){
+ throw new ArgumentNullException("cipherData");
+ }
+
+ byte[] decryptBytesByBigIntegerPub = new byte[0];
+ try{
+ decryptBytesByBigIntegerPub = BigInteger
+ .DecryptBytes
+ (
+ (
+ (key != "")
+ ? key
+ : rsaWithPrivPub.ToXmlString(true) //rsa with priv
+ )
+ , cipherData //decrypt
+ , true //UseBigInteger
+ , true //byPub
+ )
+ ;
+ }
+ catch(Exception ex){
+ Console.WriteLine(ex);
+ }
+ return decryptBytesByBigIntegerPub;
+ }
+} //end extended RSA-methods to encrypt by priv, and decrypt by pub (sign and restore the message from signature, to verify this signature).