private byte[] RSAProcessEncodeOAEP(byte[] M, byte[] P, bool usePrivate) { // +----------+---------+-------+ // DB = | lHash | PS | M | // +----------+---------+-------+ // | // +----------+ V // | seed |--> MGF ---> XOR // +----------+ | // | | // +--+ V | // |00| XOR <----- MGF <-----| // +--+ | | // | | | // V V V // +--+----------+----------------------------+ // EM = |00|maskedSeed| maskedDB | // +--+----------+----------------------------+ int mLen = M.Length; if (mLen > rsaParams.OctetsInModulus - 2 * rsaParams.hLen - 2) { throw new ArgumentException("Message too long."); } else { byte[] PS = new byte[rsaParams.OctetsInModulus - mLen - 2 * rsaParams.hLen - 2]; //4. pHash = Hash(P), byte[] pHash = rsaParams.ComputeHash(P); //5. DB = pHash||PS||01||M. List <byte> _DB = new List <byte>(); _DB.AddRange(pHash); _DB.AddRange(PS); _DB.Add(0x01); _DB.AddRange(M); byte[] DB = _DB.ToArray(); //6. Generate a random octet string seed of length hLen. byte[] seed = new byte[rsaParams.hLen]; rng.GetBytes(seed); //7. dbMask = MGF(seed, k - hLen -1). byte[] dbMask = MGF(seed, rsaParams.OctetsInModulus - rsaParams.hLen - 1); //8. maskedDB = DB XOR dbMask byte[] maskedDB = RSAxUtils.XOR(DB, dbMask); //9. seedMask = MGF(maskedDB, hLen) byte[] seedMask = MGF(maskedDB, rsaParams.hLen); //10. maskedSeed = seed XOR seedMask. byte[] maskedSeed = RSAxUtils.XOR(seed, seedMask); //11. EM = 0x00 || maskedSeed || maskedDB. List <byte> result = new List <byte>(); result.Add(0x00); result.AddRange(maskedSeed); result.AddRange(maskedDB); return(RSAProcess(result.ToArray(), usePrivate)); } }
private byte[] Decrypt(byte[] Message, byte [] Parameters, bool usePrivate, bool fOAEP) { byte[] EM = new byte[0]; try { if ((usePrivate == true) && (UseCRTForPublicDecryption) && (rsaParams.HasCRTInfo)) { EM = RSADecryptPrivateCRT(Message); } else { EM = RSAProcess(Message, usePrivate); } } catch (CryptographicException ex) { throw new CryptographicException("Exception while Decryption: " + ex.Message); } catch { throw new Exception("Exception while Decryption: "); } try { if (fOAEP) //DECODE OAEP { if ((EM.Length == rsaParams.OctetsInModulus) && (EM.Length > (2 * rsaParams.hLen + 1))) { byte[] maskedSeed; byte[] maskedDB; byte[] pHash = rsaParams.ComputeHash(Parameters); if (EM[0] == 0) // RFC3447 Format : http://tools.ietf.org/html/rfc3447 { maskedSeed = EM.ToList().GetRange(1, rsaParams.hLen).ToArray(); maskedDB = EM.ToList().GetRange(1 + rsaParams.hLen, EM.Length - rsaParams.hLen - 1).ToArray(); byte[] seedMask = MGF(maskedDB, rsaParams.hLen); byte[] seed = RSAxUtils.XOR(maskedSeed, seedMask); byte[] dbMask = MGF(seed, rsaParams.OctetsInModulus - rsaParams.hLen - 1); byte[] DB = RSAxUtils.XOR(maskedDB, dbMask); if (DB.Length >= (rsaParams.hLen + 1)) { byte[] _pHash = DB.ToList().GetRange(0, rsaParams.hLen).ToArray(); List <byte> PS_M = DB.ToList().GetRange(rsaParams.hLen, DB.Length - rsaParams.hLen); int pos = PS_M.IndexOf(0x01); if (pos >= 0 && (pos < PS_M.Count)) { List <byte> _01_M = PS_M.GetRange(pos, PS_M.Count - pos); byte[] M; if (_01_M.Count > 1) { M = _01_M.GetRange(1, _01_M.Count - 1).ToArray(); } else { M = new byte[0]; } bool success = true; for (int i = 0; i < rsaParams.hLen; i++) { if (_pHash[i] != pHash[i]) { success = false; break; } } if (success) { return(M); } else { M = new byte[rsaParams.OctetsInModulus]; //Hash Match Failure. throw new CryptographicException("OAEP Decode Error"); } } else { // #3: Invalid Encoded Message Length. throw new CryptographicException("OAEP Decode Error"); } } else { // #2: Invalid Encoded Message Length. throw new CryptographicException("OAEP Decode Error"); } } else // Standard : ftp://ftp.rsasecurity.com/pub/rsalabs/rsa_algorithm/rsa-oaep_spec.pdf { //OAEP : THIS STADNARD IS NOT IMPLEMENTED throw new CryptographicException("OAEP Decode Error"); } } else { // #1: Invalid Encoded Message Length. throw new CryptographicException("OAEP Decode Error"); } } else // DECODE PKCS v1.5 { if (EM.Length >= 11) { if ((EM[0] == 0x00) && (EM[1] == 0x02)) { int startIndex = 2; List <byte> PS = new List <byte>(); for (int i = startIndex; i < EM.Length; i++) { if (EM[i] != 0) { PS.Add(EM[i]); } else { break; } } if (PS.Count >= 8) { int DecodedDataIndex = startIndex + PS.Count + 1; if (DecodedDataIndex < (EM.Length - 1)) { List <byte> DATA = new List <byte>(); for (int i = DecodedDataIndex; i < EM.Length; i++) { DATA.Add(EM[i]); } return(DATA.ToArray()); } else { return(new byte[0]); //throw new CryptographicException("PKCS v1.5 Decode Error #4: No Data"); } } else { // #3: Invalid Key / Invalid Random Data Length throw new CryptographicException("PKCS v1.5 Decode Error"); } } else { // #2: Invalid Key / Invalid Identifiers throw new CryptographicException("PKCS v1.5 Decode Error"); } } else { // #1: Invalid Key / PKCS Encoding throw new CryptographicException("PKCS v1.5 Decode Error"); } } } catch (CryptographicException ex) { throw new CryptographicException("Exception while decoding: " + ex.Message); } catch { throw new CryptographicException("Exception while decoding"); } }