Beispiel #1
0
        public static bool TryDecrypt(byte[] Source, byte[] Passphrase, out byte[] Result)
        {
            //is this the correct version and is this a TripleSec payload to begin with
            byte[] buffer = new byte[4 + 4];
            Buffer.BlockCopy(Source, 0, buffer, 0, buffer.Length);
            if (buffer.ToHexString() != TRIPLESEC_MAGICPLUSVERSION3_HEXBYTES)
            {
                throw new ArgumentException("Not a TripleSec v3 encrypted payload!");
            }

            byte[] theSalt = new byte[SALT_LEN];
            Buffer.BlockCopy(Source, SALT_START, theSalt, 0, SALT_LEN);
            // need the keys to verify the signatures
#if DEBUG
#pragma warning disable 618 // we know in DEBUG mode this will throw an Obsolete warning; this is a legitimate use of this function, so supress it
#endif
            KeysV3 keys = new KeysV3(Passphrase, theSalt);
#if DEBUG
#pragma warning restore 618
#endif
            // VERIFY SIGNATURES HERE
            // get existing signatures
            byte[] SENT_HMACSHA512 = new byte[HMACSHA512_LEN];
            Buffer.BlockCopy(Source, HMACSHA512_START, SENT_HMACSHA512, 0, HMACSHA512_LEN);
            byte[] SENT_HMACKECCAK512 = new byte[HMACKECCAK512_LEN];
            Buffer.BlockCopy(Source, HMACKECCAK512_START, SENT_HMACKECCAK512, 0, HMACKECCAK512_LEN);
            string SENT_SIGNATURE = Utilities.BytesToHexString(SENT_HMACSHA512) + Utilities.BytesToHexString(SENT_HMACKECCAK512);

            //calculate hash on sent data before decryption
            int sourceLength = Source.Length - CIPHERTEXT_START; // the AES_IV isn't counted here

            byte[] AES_IV = new byte[AES_IV_LEN];
            Buffer.BlockCopy(Source, AES_IV_START, AES_IV, 0, AES_IV_LEN);
            //buffer = new byte[TRIPLESEC_MAGICPLUSVERSION3_BYTELENGTH + theSalt.Length + AES_IV.Length + sourceLength];

            HMACSHA512 sha512 = new HMACSHA512(keys.HMACSHA512_KEY);
            SHA3Managed.HMAC_Proposed_SHA3_512 sha3_512 = new SHA3Managed.HMAC_Proposed_SHA3_512(keys.HMACKeccak512_KEY);
            sha512.TransformBlock(TRIPLESEC_MAGICPLUSVERSION3_BYTES, 0, TRIPLESEC_MAGICPLUSVERSION3_BYTELENGTH, TRIPLESEC_MAGICPLUSVERSION3_BYTES, 0);
            sha3_512.HashCore(TRIPLESEC_MAGICPLUSVERSION3_BYTES, 0, TRIPLESEC_MAGICPLUSVERSION3_BYTELENGTH);
            sha512.TransformBlock(theSalt, 0, theSalt.Length, theSalt, 0);
            sha3_512.HashCore(theSalt, 0, theSalt.Length);
            sha512.TransformBlock(AES_IV, 0, AES_IV.Length, AES_IV, 0);
            sha3_512.HashCore(AES_IV, 0, AES_IV.Length);
            sha512.TransformBlock(Source, CIPHERTEXT_START, sourceLength, Source, CIPHERTEXT_START);
            sha3_512.HashCore(Source, CIPHERTEXT_START, sourceLength);
            sha512.TransformFinalBlock(Source, 0, 0);
            sha3_512.HashFinal(Source, 0, 0);
//#if DEBUG
//            System.Diagnostics.Debug.Print("DECRYPT SIGNATURES:");
//            System.Diagnostics.Debug.Print(BitConverter.ToString(sha512.Hash).Replace("-", ""));
//            System.Diagnostics.Debug.Print(BitConverter.ToString(sha3_512.Hash).Replace("-", ""));
//#endif
            // HASHLIB REMOVED ----!!

            string CALCULATED_SIGNATURE = Utilities.BytesToHexString(sha512.Hash) + Utilities.BytesToHexString(sha3_512.Hash);

            if (CALCULATED_SIGNATURE != SENT_SIGNATURE)
            {
                Result = null;
                return(false);
            }
            //==================================================================================

            byte[] OUTPUT = new byte[sourceLength];
            // AES is first (outermost)
            BC.Crypto.Modes.SicBlockCipher mySIC_AES = new BC.Crypto.Modes.SicBlockCipher(new BC.Crypto.Engines.AesEngine());
            mySIC_AES.Init(true,
                           new BC.Crypto.Parameters.ParametersWithIV(
                               new BC.Crypto.Parameters.KeyParameter(keys.AES_KEY),
                               AES_IV));
            ProcessArray(mySIC_AES, Source, CIPHERTEXT_START, OUTPUT, 0, sourceLength);

            // prepare for next
            byte[] IV_TWOFISH = new byte[16];
            Buffer.BlockCopy(OUTPUT, 0, IV_TWOFISH, 0, IV_TWOFISH.Length);
            byte[] INPUT = new byte[OUTPUT.Length - IV_TWOFISH.Length];
            Buffer.BlockCopy(OUTPUT, IV_TWOFISH.Length, INPUT, 0, INPUT.Length);
            OUTPUT.Wipe(); // DON'T LEAK!
            OUTPUT = new byte[INPUT.Length];

            //Twofish is next
            BC.Crypto.Modes.SicBlockCipher mySIC_TF = new BC.Crypto.Modes.SicBlockCipher(new BC.Crypto.Engines.TwofishEngine());
            mySIC_TF.Init(true,
                          new BC.Crypto.Parameters.ParametersWithIV(
                              new BC.Crypto.Parameters.KeyParameter(keys.Twofish_KEY),
                              IV_TWOFISH));
            ProcessArray(mySIC_TF, INPUT, OUTPUT);
            INPUT.Wipe(); // DON'T LEAK!

            // prepare for next
            byte[] IV_XSALSA20 = new byte[24];
            Buffer.BlockCopy(OUTPUT, 0, IV_XSALSA20, 0, IV_XSALSA20.Length);
            INPUT = new byte[OUTPUT.Length - IV_XSALSA20.Length];
            Buffer.BlockCopy(OUTPUT, IV_XSALSA20.Length, INPUT, 0, INPUT.Length);
            OUTPUT.Wipe(); // DON'T LEAK!

            //XSalsa20 is last
            OUTPUT = Chaos.NaCl.XSalsa20.Process(INPUT, keys.XSalsa20_KEY, IV_XSALSA20);
            INPUT.Wipe(); // DON'T LEAK!
            Result = OUTPUT;
            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Encrypt an array of bytes using the TripleSec protocol with the supplied passphrase.  Internal function, not intended for use by an end coder.
        /// </summary>
        /// <param name="Source">Source array of bytes to process.</param>
        /// <param name="Keys">The KeysV3 object initialized with the proper keys.</param>
        /// <param name="IVs">The RNGV3 object initialized with the proper initialization arrays.</param>
        /// <returns>The encrypted array.</returns>
        internal static byte[] Encrypt(byte[] Source, KeysV3 Keys, RNGV3 IVs)
#endif
        {
            if (Source == null || Source.Length == 0)
            {
                throw new ArgumentNullException("Source");
            }
            if (Keys == null || !Keys.IsInitialized || IVs == null || !IVs.IsInitialized)
            {
                throw new InvalidOperationException("Keys and IVs objects must not be null (and both must be initialized)");
            }

            // the added IV's and the signatures and the header always add up to the same length added to the original message length
            //  if we're going to run out of memory, it will be here, or shortly thereafter
            byte[] OUT_BUFFER = new byte[Source.Length + 208];
            //standard header stuff
            // All the header pieces are now copied by the built-in SHA512 method TransformBlock

            //XSalsa20 is up first
            byte[] interim  = Chaos.NaCl.XSalsa20.Process(Source, Keys.XSalsa20_KEY, IVs.XSalsa20_IV);
            byte[] interim2 = new byte[interim.Length + IVs.XSalsa20_IV.Length]; // IV included here as it is part of the input to the next process
            Buffer.BlockCopy(IVs.XSalsa20_IV, 0, interim2, 0, IVs.XSalsa20_IV.Length);
            Buffer.BlockCopy(interim, 0, interim2, IVs.XSalsa20_IV.Length, interim.Length);

            //Twofish is up next
            interim.Wipe();                                              // DON'T LEAK!
            interim = new byte[interim2.Length + IVs.Twofish_IV.Length]; // IV included here as it is part of the input to the next process
            Buffer.BlockCopy(IVs.Twofish_IV, 0, interim, 0, IVs.Twofish_IV.Length);
            BC.Crypto.Modes.SicBlockCipher tf = new BC.Crypto.Modes.SicBlockCipher(new BC.Crypto.Engines.TwofishEngine());
            tf.Init(true, new BC.Crypto.Parameters.ParametersWithIV(new BC.Crypto.Parameters.KeyParameter(Keys.Twofish_KEY), IVs.Twofish_IV));
            ProcessArray(tf, interim2, interim2); // process array in-place
            Buffer.BlockCopy(interim2, 0, interim, IVs.Twofish_IV.Length, interim2.Length);
            tf.Reset(); tf = null;

            //AES is last
            interim2.Wipe(); // DON'T LEAK!
            BC.Crypto.Modes.SicBlockCipher aes = new BC.Crypto.Modes.SicBlockCipher(new BC.Crypto.Engines.AesEngine());
            aes.Init(true, new BC.Crypto.Parameters.ParametersWithIV(new BC.Crypto.Parameters.KeyParameter(Keys.AES_KEY), IVs.AES_IV));
            ProcessArray(aes, interim, interim); // process array in-place
            //the HMACSHA512 process will copy the data to the output as it hashes
            aes.Reset();
            aes = null;

            HMACSHA512 sha512 = new HMACSHA512(Keys.HMACSHA512_KEY);

            sha512.TransformBlock(TRIPLESEC_MAGICPLUSVERSION3_BYTES, 0, TRIPLESEC_MAGICPLUSVERSION3_BYTELENGTH, OUT_BUFFER, 0);
            sha512.TransformBlock(Keys.Salt, 0, Keys.Salt.Length, OUT_BUFFER, SALT_START);
            sha512.TransformBlock(IVs.AES_IV, 0, IVs.AES_IV.Length, OUT_BUFFER, AES_IV_START);
            sha512.TransformBlock(interim, 0, interim.Length, OUT_BUFFER, CIPHERTEXT_START);
            sha512.TransformFinalBlock(interim, 0, 0); // transform final block doesn't copy the output
            Buffer.BlockCopy(sha512.Hash, 0, OUT_BUFFER, HMACSHA512_START, sha512.Hash.Length);


            // Proposed SHA3 uses a delimiter/padding byte of 0x01 intead of 0x06 or 0x1f (SHAKE128/256), that's the only difference
            // This is IMPORTANT for V3, as it used a pre-release version of the proposed SHA3 standard.  NIST changed SHA3 well after
            //  TripleSec was released and had been used in the wild.
            SHA3Managed.HMAC_Proposed_SHA3_512 sha3_512 = new SHA3Managed.HMAC_Proposed_SHA3_512(Keys.HMACKeccak512_KEY);
            sha3_512.HashCore(TRIPLESEC_MAGICPLUSVERSION3_BYTES, 0, TRIPLESEC_MAGICPLUSVERSION3_BYTELENGTH);
            sha3_512.HashCore(Keys.Salt, 0, Keys.Salt.Length);
            sha3_512.HashCore(IVs.AES_IV, 0, IVs.AES_IV.Length);
            sha3_512.HashCore(interim, 0, interim.Length);
            sha3_512.HashFinal(interim, 0, 0); // transform final block doesn't copy the output
            Buffer.BlockCopy(sha3_512.Hash, 0, OUT_BUFFER, HMACKECCAK512_START, sha3_512.Hash.Length);
//#if DEBUG
//            System.Diagnostics.Debug.Print("ENCRYPT SIGNATURES:");
//            System.Diagnostics.Debug.Print(BitConverter.ToString(sha512.Hash).Replace("-", ""));
//            System.Diagnostics.Debug.Print(BitConverter.ToString(sha3_512.Hash).Replace("-", ""));
//            System.Diagnostics.Debug.Print(BitConverter.ToString(OUT_BUFFER).Replace("-",""));
//#endif
            // HASHLIB REMOVED -----------!

            interim.Wipe(); // this isn't really leaking since it's encrypted AND copied to the output buffer, but clean house all the same.

            return(OUT_BUFFER);
        }