private byte[] Decrypt(byte[] message, byte [] parameters, bool usePrivate, bool fOAEP) { byte[] em; if (usePrivate && UseCRTForPublicDecryption && rsaParams.HasCRTInfo) { em = RSADecryptPrivateCRT(message); } else { em = RSAProcess(message, usePrivate); } if (fOAEP) //DECODE OAEP { if (em.Length == rsaParams.OctetsInModulus && em.Length > 2 * rsaParams.HLen + 1) { byte[] pHash = rsaParams.ComputeHash(parameters); if (em[0] == 0) // RFC3447 Format : http://tools.ietf.org/html/rfc3447 { var maskedSeed = em.ToList().GetRange(1, rsaParams.HLen).ToArray(); var maskedDB = em.ToList().GetRange(1 + rsaParams.HLen, em.Length - rsaParams.HLen - 1).ToArray(); var seedMask = MGF(maskedDB, rsaParams.HLen); var seed = RSAxUtils.XOR(maskedSeed, seedMask); var dbMask = MGF(seed, rsaParams.OctetsInModulus - rsaParams.HLen - 1); var db = RSAxUtils.XOR(maskedDB, dbMask); if (db.Length >= rsaParams.HLen + 1) { byte[] pHashInner = db.ToList().GetRange(0, rsaParams.HLen).ToArray(); List <byte> psM = db.ToList().GetRange(rsaParams.HLen, db.Length - rsaParams.HLen); int pos = psM.IndexOf(0x01); if (pos >= 0 && pos < psM.Count) { List <byte> list01M = psM.GetRange(pos, psM.Count - pos); byte[] m; if (list01M.Count > 1) { m = list01M.GetRange(1, list01M.Count - 1).ToArray(); } else { m = new byte[0]; } bool success = true; for (int i = 0; i < rsaParams.HLen; i++) { if (pHashInner[i] != pHash[i]) { success = false; break; } } if (success) { return(m); } throw new CryptographicException("OAEP Decode Error"); } // #3: Invalid Encoded Message Length. throw new CryptographicException("OAEP Decode Error"); } // #2: Invalid Encoded Message Length. throw new CryptographicException("OAEP Decode Error"); } // 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"); } // #1: Invalid Encoded Message Length. throw new CryptographicException("OAEP Decode Error"); } // 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()); } return(new byte[0]); //throw new CryptographicException("PKCS v1.5 Decode Error #4: No Data"); } // #3: Invalid Key / Invalid Random Data Length throw new CryptographicException("PKCS v1.5 Decode Error"); } // #2: Invalid Key / Invalid Identifiers throw new CryptographicException("PKCS v1.5 Decode Error"); } // #1: Invalid Key / PKCS Encoding throw new CryptographicException("PKCS v1.5 Decode Error"); }
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> dblist = new List <byte>(); dblist.AddRange(pHash); dblist.AddRange(ps); dblist.Add(0x01); dblist.AddRange(m); byte[] db = dblist.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. var result = new byte[] { 0x00 }.Concat(maskedSeed).Concat(maskedDB).ToArray(); return(RSAProcess(result, usePrivate)); } }