/// <summary> /// Resets the current KeysV3 object with the Passphrase, converting it into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="PassphraseBytes">The Passphrase as a series of bytes.</param> /// <param name="RNG"></param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public void Initialize(byte[] PassphraseBytes, RNGV3 RNG, bool WipePassphrase = false) { if (RNG == null) { RNG = new RNGV3(); } Initialize(PassphraseBytes, RNG.Salt, WipePassphrase); }
/// <summary> /// Creates a new KeysV3 object with the Passphrase converted into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="Passphrase">The Passphrase string.</param> /// <param name="RNG">A previously generated RNGV3 object (needed for the Salt).</param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public KeysV3(string Passphrase, RNGV3 RNG, bool WipePassphrase = false) { if (RNG == null) { RNG = new RNGV3(); } Initialize(Passphrase, RNG, WipePassphrase); }
/// <summary> /// Resets the current KeysV3 object with the Passphrase, converting it into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="Passphrase">The Passphrase string.</param> /// <param name="RNG"></param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public void Initialize(string Passphrase, RNGV3 RNG, bool WipePassphrase = false) { if (RNG == null) { RNG = new RNGV3(); } Initialize(new UTF8Encoding().GetBytes(Passphrase), RNG, WipePassphrase); }
/// <summary> /// Resets the current KeysV3 object with the Passphrase, converting it into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="PassphraseBytes">The Passphrase as a series of bytes.</param> /// <param name="Salt">The Salt as a series of bytes or NULL/NOTHING to use a newly created random sequence of bytes (use the Salt property to retrieve the created array).</param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public void Initialize(byte[] PassphraseBytes, byte[] Salt = null, bool WipePassphrase = false) { // all constructors and initializers end up here if (PassphraseBytes == null || PassphraseBytes.Length == 0) { throw new ArgumentNullException("PassphraseBytes"); } byte[] _tempSalt = null; if (Salt == null) { _tempSalt = new RNGV3().Salt; } else if (Salt.Length != 16) { throw new ArgumentOutOfRangeException("Salt", "Salt must be 16 bytes or NULL/NOTHING."); } else { _tempSalt = (byte[])Salt.Clone(); } lock (LOCKTHIS) { // remove old SCRYPT reference //byte[] KEYS = CryptSharp.Utility.SCrypt.ComputeDerivedKey( // PassphraseBytes, _tempSalt, // SCRYPT_CPU_COST, SCRYPT_BLOCKS, SCRYPT_PARALLEL_THREADS, SCRYPT_PARALLEL_THREADS, SCRYPT_OUTPUT_BYTES); // add SCryptManaged reference byte[] KEYS = ScryptManaged.Scrypt.ComputeDerivedHash( PassphraseBytes, _tempSalt, SCRYPT_CPU_COST, SCRYPT_BLOCKS, SCRYPT_PARALLEL_THREADS, SCRYPT_OUTPUT_BYTES); // USE THE FOLLOWING WITH EXTREME CAUTION, THE PASSPHRASE WILL BE CLEANED A LONG WAY UP THE HEAP!!!! if (WipePassphrase) // WARNING: only do this if asked, as it will wipe ALL the way back up the call stack!!!!! { PassphraseBytes.Wipe(); // get it out of memory absolutely as soon as possible! } this.Clear(); _salt = (byte[])_tempSalt.Clone(); _tempSalt.Wipe(); this._hmac512key = new byte[48]; this._hmackeccak512key = new byte[48]; this._aeskey = new byte[32]; this._twofishkey = new byte[32]; this._xsalsa20key = new byte[32]; Buffer.BlockCopy(KEYS, 0, this._hmac512key, 0, this._hmac512key.Length); Buffer.BlockCopy(KEYS, 48, this._hmackeccak512key, 0, this._hmackeccak512key.Length); Buffer.BlockCopy(KEYS, 48 + 48, this._aeskey, 0, this._aeskey.Length); Buffer.BlockCopy(KEYS, 48 + 48 + 32, this._twofishkey, 0, this._twofishkey.Length); Buffer.BlockCopy(KEYS, 48 + 48 + 32 + 32, this._xsalsa20key, 0, this._xsalsa20key.Length); _ready = true; } }
// HASHLIB REMOVED ------------! /// <summary> /// Encrypt an array of bytes using the TripleSec protocol with the supplied passphrase. /// </summary> /// <param name="Source"></param> /// <param name="Passphrase"></param> /// <returns></returns> public static byte[] Encrypt(byte[] Source, byte[] Passphrase) { if (Source == null || Source.Length == 0) { throw new ArgumentNullException("Source"); } if (Passphrase == null || Passphrase.Length == 0) { throw new ArgumentNullException("Passphrase"); } #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 RNGV3 rng = new RNGV3(); // get a new salt and IV's KeysV3 keys = new KeysV3(Passphrase, rng); // build the internal keys based on the Passphrase and generated salt return(Encrypt(Source, keys, rng)); #if DEBUG #pragma warning restore 618 #endif }
/// <summary> /// Encrypt an array of bytes using the TripleSec protocol with the supplied passphrase. /// </summary> /// <param name="Source"></param> /// <param name="Passphrase"></param> /// <returns></returns> public static byte[] Encrypt(byte[] Source, byte[] Passphrase) { if (Source == null || Source.Length == 0) throw new ArgumentNullException("Source"); if (Passphrase == null || Passphrase.Length == 0) throw new ArgumentNullException("Passphrase"); #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 RNGV3 rng = new RNGV3(); // get a new salt and IV's KeysV3 keys = new KeysV3(Passphrase, rng); // build the internal keys based on the Passphrase and generated salt return Encrypt(Source, keys, rng); #pragma warning restore 618 }
/// <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 Buffer.BlockCopy(Utilities.HexStringToBytes(TRIPLESEC_MAGICPLUSVERSION3_HEXBYTES), 0, OUT_BUFFER, 0, 8); // The SALT and AES IV are public in the final construction, so putting them here is a minimal risk. // At worst, it leaks RNG material on abort. //salt Buffer.BlockCopy(IVs.Salt, 0, OUT_BUFFER, SALT_START, SALT_LEN); //AES IV Buffer.BlockCopy(IVs.AES_IV, 0, OUT_BUFFER, AES_IV_START, AES_IV_LEN); //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 Buffer.BlockCopy(interim, 0, OUT_BUFFER, CIPHERTEXT_START, interim.Length); aes.Reset(); aes = null; HashLib.IHMAC h512 = CreateSHA512MacObject(Keys.HMACSHA512_KEY); h512.TransformBytes(Utilities.HexStringToBytes(TRIPLESEC_MAGICPLUSVERSION3_HEXBYTES)); //header h512.TransformBytes(IVs.Salt); //salt h512.TransformBytes(IVs.AES_IV); // IV for AES h512.TransformBytes(interim); // ciphertext HashLib.HashResult sig1 = h512.TransformFinal(); // get the result Buffer.BlockCopy(sig1.GetBytes(), 0, OUT_BUFFER, HMACSHA512_START, HMACSHA512_LEN); // store it HashLib.IHMAC keccak = CreateKeccak512MacObject(Keys.HMACKeccak512_KEY); keccak.TransformBytes(Utilities.HexStringToBytes(TRIPLESEC_MAGICPLUSVERSION3_HEXBYTES)); //header keccak.TransformBytes(IVs.Salt); //salt keccak.TransformBytes(IVs.AES_IV); // IV for AES keccak.TransformBytes(interim); // ciphertext HashLib.HashResult sig2 = keccak.TransformFinal(); // get the result Buffer.BlockCopy(sig2.GetBytes(), 0, OUT_BUFFER, HMACKECCAK512_START, HMACKECCAK512_LEN); //store it 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; }
public static byte[] Encrypt(byte[] Source, KeysV3 Keys, RNGV3 IVs)
/// <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); }
public static byte[] Encrypt(byte[] Source, KeysV3 Keys, RNGV3 IVs)
/// <summary> /// Creates a new KeysV3 object with the Passphrase converted into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="Passphrase">The Passphrase string.</param> /// <param name="RNG">A previously generated RNGV3 object (needed for the Salt).</param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public KeysV3(string Passphrase, RNGV3 RNG, bool WipePassphrase = false) { if (RNG == null) RNG = new RNGV3(); Initialize(Passphrase, RNG, WipePassphrase); }
/// <summary> /// Resets the current KeysV3 object with the Passphrase, converting it into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="PassphraseBytes">The Passphrase as a series of bytes.</param> /// <param name="Salt">The Salt as a series of bytes or NULL/NOTHING to use a newly created random sequence of bytes (use the Salt property to retrieve the created array).</param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public void Initialize(byte[] PassphraseBytes, byte[] Salt = null, bool WipePassphrase = false) { // all constructors and initializers end up here if (PassphraseBytes == null || PassphraseBytes.Length == 0) throw new ArgumentNullException("PassphraseBytes"); byte[] _tempSalt = null; if (Salt == null) { _tempSalt = new RNGV3().Salt; } else if (Salt.Length != 16) throw new ArgumentOutOfRangeException("Salt", "Salt must be 16 bytes or NULL/NOTHING."); else _tempSalt = (byte[])Salt.Clone(); lock (LOCKTHIS) { byte[] KEYS = CryptSharp.Utility.SCrypt.ComputeDerivedKey( PassphraseBytes, _tempSalt, SCRYPT_CPU_COST, SCRYPT_BLOCKS, SCRYPT_PARALLEL_THREADS, SCRYPT_PARALLEL_THREADS, SCRYPT_OUTPUT_BYTES); // USE THE FOLLOWING WITH EXTREME CAUTION, THE PASSPHRASE WILL BE CLEANED A LONG WAY UP THE HEAP!!!! if (WipePassphrase) // WARNING: only do this if asked, as it will wipe ALL the way back up the call stack!!!!! PassphraseBytes.Wipe(); // get it out of memory absolutely as soon as possible! this.Clear(); _salt = (byte[])_tempSalt.Clone(); _tempSalt.Wipe(); this._hmac512key = new byte[48]; this._hmackeccak512key = new byte[48]; this._aeskey = new byte[32]; this._twofishkey = new byte[32]; this._xsalsa20key = new byte[32]; Buffer.BlockCopy(KEYS, 0, this._hmac512key, 0, this._hmac512key.Length); Buffer.BlockCopy(KEYS, 48, this._hmackeccak512key, 0, this._hmackeccak512key.Length); Buffer.BlockCopy(KEYS, 48 + 48, this._aeskey, 0, this._aeskey.Length); Buffer.BlockCopy(KEYS, 48 + 48 + 32, this._twofishkey, 0, this._twofishkey.Length); Buffer.BlockCopy(KEYS, 48 + 48 + 32 + 32, this._xsalsa20key, 0, this._xsalsa20key.Length); _ready = true; } }
/// <summary> /// Resets the current KeysV3 object with the Passphrase, converting it into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="PassphraseBytes">The Passphrase as a series of bytes.</param> /// <param name="RNG"></param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public void Initialize(byte[] PassphraseBytes, RNGV3 RNG, bool WipePassphrase = false) { if (RNG == null) RNG = new RNGV3(); Initialize(PassphraseBytes, RNG.Salt, WipePassphrase); }
/// <summary> /// Resets the current KeysV3 object with the Passphrase, converting it into the proper internal TripleSec encryption and HMAC keys. /// </summary> /// <param name="Passphrase">The Passphrase string.</param> /// <param name="RNG"></param> /// <param name="WipePassphrase">Wipe the passphrase from memory when no longer needed? WARNING: USE WITH CAUTION!!!</param> public void Initialize(string Passphrase, RNGV3 RNG, bool WipePassphrase = false) { if (RNG == null) RNG = new RNGV3(); Initialize(new UTF8Encoding().GetBytes(Passphrase), RNG, WipePassphrase); }