protected virtual void UpdateHASH(byte[] LSub) { OcbBlockCipher.Xor(this.OffsetHASH, LSub); OcbBlockCipher.Xor(this.hashBlock, this.OffsetHASH); this.hashCipher.ProcessBlock(this.hashBlock, 0, this.hashBlock, 0); OcbBlockCipher.Xor(this.Sum, this.hashBlock); }
protected virtual byte[] GetLSub(int n) { while (n >= this.L.Count) { this.L.Add(OcbBlockCipher.OCB_double((byte[])this.L[this.L.Count - 1])); } return((byte[])this.L[n]); }
public virtual int DoFinal(byte[] output, int outOff) { byte[] array = null; if (!this.forEncryption) { if (this.mainBlockPos < this.macSize) { throw new InvalidCipherTextException("data too short"); } this.mainBlockPos -= this.macSize; array = new byte[this.macSize]; Array.Copy(this.mainBlock, this.mainBlockPos, array, 0, this.macSize); } if (this.hashBlockPos > 0) { OcbBlockCipher.OCB_extend(this.hashBlock, this.hashBlockPos); this.UpdateHASH(this.L_Asterisk); } if (this.mainBlockPos > 0) { if (this.forEncryption) { OcbBlockCipher.OCB_extend(this.mainBlock, this.mainBlockPos); OcbBlockCipher.Xor(this.Checksum, this.mainBlock); } OcbBlockCipher.Xor(this.OffsetMAIN, this.L_Asterisk); byte[] array2 = new byte[16]; this.hashCipher.ProcessBlock(this.OffsetMAIN, 0, array2, 0); OcbBlockCipher.Xor(this.mainBlock, array2); Check.OutputLength(output, outOff, this.mainBlockPos, "Output buffer too short"); Array.Copy(this.mainBlock, 0, output, outOff, this.mainBlockPos); if (!this.forEncryption) { OcbBlockCipher.OCB_extend(this.mainBlock, this.mainBlockPos); OcbBlockCipher.Xor(this.Checksum, this.mainBlock); } } OcbBlockCipher.Xor(this.Checksum, this.OffsetMAIN); OcbBlockCipher.Xor(this.Checksum, this.L_Dollar); this.hashCipher.ProcessBlock(this.Checksum, 0, this.Checksum, 0); OcbBlockCipher.Xor(this.Checksum, this.Sum); this.macBlock = new byte[this.macSize]; Array.Copy(this.Checksum, 0, this.macBlock, 0, this.macSize); int num = this.mainBlockPos; if (this.forEncryption) { Check.OutputLength(output, outOff, num + this.macSize, "Output buffer too short"); Array.Copy(this.macBlock, 0, output, outOff + num, this.macSize); num += this.macSize; } else if (!Arrays.ConstantTimeAreEqual(this.macBlock, array)) { throw new InvalidCipherTextException("mac check in OCB failed"); } this.Reset(false); return(num); }
protected static byte[] OCB_double(byte[] block) { byte[] array = new byte[16]; int num = OcbBlockCipher.ShiftLeft(block, array); byte[] expr_18_cp_0 = array; int expr_18_cp_1 = 15; expr_18_cp_0[expr_18_cp_1] ^= (byte)(135 >> (1 - num << 3)); return(array); }
protected virtual void ProcessMainBlock(byte[] output, int outOff) { Check.DataLength(output, outOff, 16, "Output buffer too short"); if (this.forEncryption) { OcbBlockCipher.Xor(this.Checksum, this.mainBlock); this.mainBlockPos = 0; } OcbBlockCipher.Xor(this.OffsetMAIN, this.GetLSub(OcbBlockCipher.OCB_ntz(this.mainBlockCount += 1L))); OcbBlockCipher.Xor(this.mainBlock, this.OffsetMAIN); this.mainCipher.ProcessBlock(this.mainBlock, 0, this.mainBlock, 0); OcbBlockCipher.Xor(this.mainBlock, this.OffsetMAIN); Array.Copy(this.mainBlock, 0, output, outOff, 16); if (!this.forEncryption) { OcbBlockCipher.Xor(this.Checksum, this.mainBlock); Array.Copy(this.mainBlock, 16, this.mainBlock, 0, this.macSize); this.mainBlockPos = this.macSize; } }
public static IBufferedCipher GetCipher( string algorithm) { if (algorithm == null) throw new ArgumentNullException("algorithm"); algorithm = Platform.ToUpperInvariant(algorithm); { string aliased = (string) algorithms[algorithm]; if (aliased != null) algorithm = aliased; } IBasicAgreement iesAgreement = null; if (algorithm == "IES") { iesAgreement = new DHBasicAgreement(); } else if (algorithm == "ECIES") { iesAgreement = new ECDHBasicAgreement(); } if (iesAgreement != null) { return new BufferedIesCipher( new IesEngine( iesAgreement, new Kdf2BytesGenerator( new Sha1Digest()), new HMac( new Sha1Digest()))); } if (algorithm.StartsWith("PBE")) { if (algorithm.EndsWith("-CBC")) { if (algorithm == "PBEWITHSHA1ANDDES-CBC") { return new PaddedBufferedBlockCipher( new CbcBlockCipher(new DesEngine())); } else if (algorithm == "PBEWITHSHA1ANDRC2-CBC") { return new PaddedBufferedBlockCipher( new CbcBlockCipher(new RC2Engine())); } else if (Strings.IsOneOf(algorithm, "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC")) { return new PaddedBufferedBlockCipher( new CbcBlockCipher(new DesEdeEngine())); } else if (Strings.IsOneOf(algorithm, "PBEWITHSHAAND128BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC")) { return new PaddedBufferedBlockCipher( new CbcBlockCipher(new RC2Engine())); } } else if (algorithm.EndsWith("-BC") || algorithm.EndsWith("-OPENSSL")) { if (Strings.IsOneOf(algorithm, "PBEWITHSHAAND128BITAES-CBC-BC", "PBEWITHSHAAND192BITAES-CBC-BC", "PBEWITHSHAAND256BITAES-CBC-BC", "PBEWITHSHA256AND128BITAES-CBC-BC", "PBEWITHSHA256AND192BITAES-CBC-BC", "PBEWITHSHA256AND256BITAES-CBC-BC", "PBEWITHMD5AND128BITAES-CBC-OPENSSL", "PBEWITHMD5AND192BITAES-CBC-OPENSSL", "PBEWITHMD5AND256BITAES-CBC-OPENSSL")) { return new PaddedBufferedBlockCipher( new CbcBlockCipher(new AesFastEngine())); } } } string[] parts = algorithm.Split('/'); IBlockCipher blockCipher = null; IAsymmetricBlockCipher asymBlockCipher = null; IStreamCipher streamCipher = null; string algorithmName = parts[0]; { string aliased = (string)algorithms[algorithmName]; if (aliased != null) algorithmName = aliased; } CipherAlgorithm cipherAlgorithm; try { cipherAlgorithm = (CipherAlgorithm)Enums.GetEnumValue(typeof(CipherAlgorithm), algorithmName); } catch (ArgumentException) { throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); } switch (cipherAlgorithm) { case CipherAlgorithm.AES: blockCipher = new AesFastEngine(); break; case CipherAlgorithm.ARC4: streamCipher = new RC4Engine(); break; case CipherAlgorithm.BLOWFISH: blockCipher = new BlowfishEngine(); break; case CipherAlgorithm.CAMELLIA: blockCipher = new CamelliaEngine(); break; case CipherAlgorithm.CAST5: blockCipher = new Cast5Engine(); break; case CipherAlgorithm.CAST6: blockCipher = new Cast6Engine(); break; case CipherAlgorithm.DES: blockCipher = new DesEngine(); break; case CipherAlgorithm.DESEDE: blockCipher = new DesEdeEngine(); break; case CipherAlgorithm.ELGAMAL: asymBlockCipher = new ElGamalEngine(); break; case CipherAlgorithm.GOST28147: blockCipher = new Gost28147Engine(); break; case CipherAlgorithm.HC128: streamCipher = new HC128Engine(); break; case CipherAlgorithm.HC256: streamCipher = new HC256Engine(); break; case CipherAlgorithm.IDEA: blockCipher = new IdeaEngine(); break; case CipherAlgorithm.NOEKEON: blockCipher = new NoekeonEngine(); break; case CipherAlgorithm.PBEWITHSHAAND128BITRC4: case CipherAlgorithm.PBEWITHSHAAND40BITRC4: streamCipher = new RC4Engine(); break; case CipherAlgorithm.RC2: blockCipher = new RC2Engine(); break; case CipherAlgorithm.RC5: blockCipher = new RC532Engine(); break; case CipherAlgorithm.RC5_64: blockCipher = new RC564Engine(); break; case CipherAlgorithm.RC6: blockCipher = new RC6Engine(); break; case CipherAlgorithm.RIJNDAEL: blockCipher = new RijndaelEngine(); break; case CipherAlgorithm.RSA: asymBlockCipher = new RsaBlindedEngine(); break; case CipherAlgorithm.SALSA20: streamCipher = new Salsa20Engine(); break; case CipherAlgorithm.SEED: blockCipher = new SeedEngine(); break; case CipherAlgorithm.SERPENT: blockCipher = new SerpentEngine(); break; case CipherAlgorithm.SKIPJACK: blockCipher = new SkipjackEngine(); break; case CipherAlgorithm.TEA: blockCipher = new TeaEngine(); break; case CipherAlgorithm.TWOFISH: blockCipher = new TwofishEngine(); break; case CipherAlgorithm.VMPC: streamCipher = new VmpcEngine(); break; case CipherAlgorithm.VMPC_KSA3: streamCipher = new VmpcKsa3Engine(); break; case CipherAlgorithm.XTEA: blockCipher = new XteaEngine(); break; default: throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); } if (streamCipher != null) { if (parts.Length > 1) throw new ArgumentException("Modes and paddings not used for stream ciphers"); return new BufferedStreamCipher(streamCipher); } bool cts = false; bool padded = true; IBlockCipherPadding padding = null; IAeadBlockCipher aeadBlockCipher = null; if (parts.Length > 2) { if (streamCipher != null) throw new ArgumentException("Paddings not used for stream ciphers"); string paddingName = parts[2]; CipherPadding cipherPadding; if (paddingName == "") { cipherPadding = CipherPadding.RAW; } else if (paddingName == "X9.23PADDING") { cipherPadding = CipherPadding.X923PADDING; } else { try { cipherPadding = (CipherPadding)Enums.GetEnumValue(typeof(CipherPadding), paddingName); } catch (ArgumentException) { throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); } } switch (cipherPadding) { case CipherPadding.NOPADDING: padded = false; break; case CipherPadding.RAW: break; case CipherPadding.ISO10126PADDING: case CipherPadding.ISO10126D2PADDING: case CipherPadding.ISO10126_2PADDING: padding = new ISO10126d2Padding(); break; case CipherPadding.ISO7816_4PADDING: case CipherPadding.ISO9797_1PADDING: padding = new ISO7816d4Padding(); break; case CipherPadding.ISO9796_1: case CipherPadding.ISO9796_1PADDING: asymBlockCipher = new ISO9796d1Encoding(asymBlockCipher); break; case CipherPadding.OAEP: case CipherPadding.OAEPPADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher); break; case CipherPadding.OAEPWITHMD5ANDMGF1PADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher, new MD5Digest()); break; case CipherPadding.OAEPWITHSHA1ANDMGF1PADDING: case CipherPadding.OAEPWITHSHA_1ANDMGF1PADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha1Digest()); break; case CipherPadding.OAEPWITHSHA224ANDMGF1PADDING: case CipherPadding.OAEPWITHSHA_224ANDMGF1PADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha224Digest()); break; case CipherPadding.OAEPWITHSHA256ANDMGF1PADDING: case CipherPadding.OAEPWITHSHA_256ANDMGF1PADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest()); break; case CipherPadding.OAEPWITHSHA384ANDMGF1PADDING: case CipherPadding.OAEPWITHSHA_384ANDMGF1PADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha384Digest()); break; case CipherPadding.OAEPWITHSHA512ANDMGF1PADDING: case CipherPadding.OAEPWITHSHA_512ANDMGF1PADDING: asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha512Digest()); break; case CipherPadding.PKCS1: case CipherPadding.PKCS1PADDING: asymBlockCipher = new Pkcs1Encoding(asymBlockCipher); break; case CipherPadding.PKCS5: case CipherPadding.PKCS5PADDING: case CipherPadding.PKCS7: case CipherPadding.PKCS7PADDING: padding = new Pkcs7Padding(); break; case CipherPadding.TBCPADDING: padding = new TbcPadding(); break; case CipherPadding.WITHCTS: cts = true; break; case CipherPadding.X923PADDING: padding = new X923Padding(); break; case CipherPadding.ZEROBYTEPADDING: padding = new ZeroBytePadding(); break; default: throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); } } string mode = ""; if (parts.Length > 1) { mode = parts[1]; int di = GetDigitIndex(mode); string modeName = di >= 0 ? mode.Substring(0, di) : mode; try { CipherMode cipherMode = modeName == "" ? CipherMode.NONE : (CipherMode)Enums.GetEnumValue(typeof(CipherMode), modeName); switch (cipherMode) { case CipherMode.ECB: case CipherMode.NONE: break; case CipherMode.CBC: blockCipher = new CbcBlockCipher(blockCipher); break; case CipherMode.CCM: aeadBlockCipher = new CcmBlockCipher(blockCipher); break; case CipherMode.CFB: { int bits = (di < 0) ? 8 * blockCipher.GetBlockSize() : int.Parse(mode.Substring(di)); blockCipher = new CfbBlockCipher(blockCipher, bits); break; } case CipherMode.CTR: blockCipher = new SicBlockCipher(blockCipher); break; case CipherMode.CTS: cts = true; blockCipher = new CbcBlockCipher(blockCipher); break; case CipherMode.EAX: aeadBlockCipher = new EaxBlockCipher(blockCipher); break; case CipherMode.GCM: aeadBlockCipher = new GcmBlockCipher(blockCipher); break; case CipherMode.GOFB: blockCipher = new GOfbBlockCipher(blockCipher); break; case CipherMode.OCB: aeadBlockCipher = new OcbBlockCipher(blockCipher, CreateBlockCipher(cipherAlgorithm)); break; case CipherMode.OFB: { int bits = (di < 0) ? 8 * blockCipher.GetBlockSize() : int.Parse(mode.Substring(di)); blockCipher = new OfbBlockCipher(blockCipher, bits); break; } case CipherMode.OPENPGPCFB: blockCipher = new OpenPgpCfbBlockCipher(blockCipher); break; case CipherMode.SIC: if (blockCipher.GetBlockSize() < 16) { throw new ArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)"); } blockCipher = new SicBlockCipher(blockCipher); break; default: throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); } } catch (ArgumentException) { throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); } } if (aeadBlockCipher != null) { if (cts) throw new SecurityUtilityException("CTS mode not valid for AEAD ciphers."); if (padded && parts.Length > 2 && parts[2] != "") throw new SecurityUtilityException("Bad padding specified for AEAD cipher."); return new BufferedAeadBlockCipher(aeadBlockCipher); } if (blockCipher != null) { if (cts) { return new CtsBlockCipher(blockCipher); } if (padding != null) { return new PaddedBufferedBlockCipher(blockCipher, padding); } if (!padded || blockCipher.IsPartialBlockOkay) { return new BufferedBlockCipher(blockCipher); } return new PaddedBufferedBlockCipher(blockCipher); } if (asymBlockCipher != null) { return new BufferedAsymmetricBlockCipher(asymBlockCipher); } throw new SecurityUtilityException("Cipher " + algorithm + " not recognised."); }
public virtual void Init(bool forEncryption, ICipherParameters parameters) { bool flag = this.forEncryption; this.forEncryption = forEncryption; this.macBlock = null; byte[] array; KeyParameter keyParameter; if (parameters is AeadParameters) { AeadParameters aeadParameters = (AeadParameters)parameters; array = aeadParameters.GetNonce(); this.initialAssociatedText = aeadParameters.GetAssociatedText(); int num = aeadParameters.MacSize; if (num < 64 || num > 128 || num % 8 != 0) { throw new ArgumentException("Invalid value for MAC size: " + num); } this.macSize = num / 8; keyParameter = aeadParameters.Key; } else { if (!(parameters is ParametersWithIV)) { throw new ArgumentException("invalid parameters passed to OCB"); } ParametersWithIV parametersWithIV = (ParametersWithIV)parameters; array = parametersWithIV.GetIV(); this.initialAssociatedText = null; this.macSize = 16; keyParameter = (KeyParameter)parametersWithIV.Parameters; } this.hashBlock = new byte[16]; this.mainBlock = new byte[forEncryption ? 16 : (16 + this.macSize)]; if (array == null) { array = new byte[0]; } if (array.Length > 15) { throw new ArgumentException("IV must be no more than 15 bytes"); } if (keyParameter != null) { this.hashCipher.Init(true, keyParameter); this.mainCipher.Init(forEncryption, keyParameter); this.KtopInput = null; } else if (flag != forEncryption) { throw new ArgumentException("cannot change encrypting state without providing key."); } this.L_Asterisk = new byte[16]; this.hashCipher.ProcessBlock(this.L_Asterisk, 0, this.L_Asterisk, 0); this.L_Dollar = OcbBlockCipher.OCB_double(this.L_Asterisk); this.L = Platform.CreateArrayList(); this.L.Add(OcbBlockCipher.OCB_double(this.L_Dollar)); int num2 = this.ProcessNonce(array); int num3 = num2 % 8; int num4 = num2 / 8; if (num3 == 0) { Array.Copy(this.Stretch, num4, this.OffsetMAIN_0, 0, 16); } else { for (int i = 0; i < 16; i++) { uint num5 = (uint)this.Stretch[num4]; uint num6 = (uint)this.Stretch[++num4]; this.OffsetMAIN_0[i] = (byte)(num5 << num3 | num6 >> 8 - num3); } } this.hashBlockPos = 0; this.mainBlockPos = 0; this.hashBlockCount = 0L; this.mainBlockCount = 0L; this.OffsetHASH = new byte[16]; this.Sum = new byte[16]; Array.Copy(this.OffsetMAIN_0, 0, this.OffsetMAIN, 0, 16); this.Checksum = new byte[16]; if (this.initialAssociatedText != null) { this.ProcessAadBytes(this.initialAssociatedText, 0, this.initialAssociatedText.Length); } }
protected virtual void ProcessHashBlock() { this.UpdateHASH(this.GetLSub(OcbBlockCipher.OCB_ntz(this.hashBlockCount += 1L))); this.hashBlockPos = 0; }
private void DoTestExceptions() { IAeadBlockCipher ocb = CreateOcbCipher(); try { ocb = new OcbBlockCipher(new DesEngine(), new DesEngine()); Fail("incorrect block size not picked up"); } catch (ArgumentException) { // expected } try { ocb.Init(false, new KeyParameter(new byte[16])); Fail("illegal argument not picked up"); } catch (ArgumentException) { // expected } // TODO //AEADTestUtil.testReset(this, createOCBCipher(), createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15])); //AEADTestUtil.testTampering(this, ocb, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15])); }
private void RunLongerTestCase(int aesKeySize, int tagLen, byte[] expectedOutput) { KeyParameter key = new KeyParameter(new byte[aesKeySize / 8]); byte[] N = new byte[12]; IAeadBlockCipher c1 = new OcbBlockCipher(new AesFastEngine(), new AesFastEngine()); c1.Init(true, new AeadParameters(key, tagLen, N)); IAeadBlockCipher c2 = new OcbBlockCipher(new AesFastEngine(), new AesFastEngine()); long total = 0; byte[] S = new byte[128]; for (int i = 0; i < 128; ++i) { N[11] = (byte) i; c2.Init(true, new AeadParameters(key, tagLen, N)); total += UpdateCiphers(c1, c2, S, i, true, true); total += UpdateCiphers(c1, c2, S, i, false, true); total += UpdateCiphers(c1, c2, S, i, true, false); } long expectedTotal = 16256 + (48 * tagLen); if (total != expectedTotal) { Fail("test generated the wrong amount of input: " + total); } byte[] output = new byte[c1.GetOutputSize(0)]; c1.DoFinal(output, 0); if (!AreEqual(expectedOutput, output)) { Fail("incorrect encrypt in long-form test"); } }
private void CheckTestCase(OcbBlockCipher encCipher, OcbBlockCipher decCipher, string testName, int macLengthBytes, byte[] P, byte[] C) { byte[] tag = Arrays.Copy(C, C.Length - macLengthBytes, macLengthBytes); { byte[] enc = new byte[encCipher.GetOutputSize(P.Length)]; int len = encCipher.ProcessBytes(P, 0, P.Length, enc, 0); len += encCipher.DoFinal(enc, len); if (enc.Length != len) { Fail("encryption reported incorrect length: " + testName); } if (!AreEqual(C, enc)) { Fail("incorrect encrypt in: " + testName); } if (!AreEqual(tag, encCipher.GetMac())) { Fail("getMac() not the same as the appended tag: " + testName); } } { byte[] dec = new byte[decCipher.GetOutputSize(C.Length)]; int len = decCipher.ProcessBytes(C, 0, C.Length, dec, 0); len += decCipher.DoFinal(dec, len); if (dec.Length != len) { Fail("decryption reported incorrect length: " + testName); } if (!AreEqual(P, dec)) { Fail("incorrect decrypt in: " + testName); } if (!AreEqual(tag, decCipher.GetMac())) { Fail("getMac() not the same as the appended tag: " + testName); } } }
private OcbBlockCipher InitCipher(bool forEncryption, AeadParameters parameters) { OcbBlockCipher c = new OcbBlockCipher(new AesFastEngine(), new AesFastEngine()); c.Init(forEncryption, parameters); return c; }