/// <summary> /// Initializes the Skein hash instance. /// </summary> /// <param name="stateSize">The internal state size of the hash in bits. /// Supported values are 256, 512, and 1024.</param> /// <param name="outputSize">The output size of the hash in bits. /// Output size must be divisible by 8 and greater than zero.</param> public Skein(int stateSize, int outputSize) { if (outputSize <= 0) { throw new CryptographicException("Output bit size must be greater than zero."); } if (outputSize % 8 != 0) { throw new CryptographicException("Output bit size must be divisible by 8."); } cipherStateBits = stateSize; cipherStateBytes = stateSize / 8; cipherStateWords = stateSize / 64; HashSizeValue = outputSize; outputBytes = (outputSize + 7) / 8; cipher = ThreefishCipher.CreateCipher(stateSize); if (cipher == null) { throw new CryptographicException("Unsupported state size."); } inputBuffer = new byte[cipherStateBytes]; cipherInput = new ulong[cipherStateWords]; state = new ulong[cipherStateWords]; UbiParameters = new UbiTweak(); Configuration = new SkeinConfig(this); Configuration.SetSchema(83, 72, 65, 51); // "SHA3" Configuration.SetVersion(1); Configuration.GenerateConfiguration(); Initialize(); }
internal ThreefishTransform(byte[] key, byte[] iv, int feedbackSize, ThreefishTransformMode transformMode, CipherMode cipherMode, PaddingMode paddingMode) { this.transformMode = transformMode; this.cipherMode = cipherMode; this.paddingMode = paddingMode; cipherBytes = key.Length; cipherWords = key.Length / 8; feedbackBytes = feedbackSize / 8; // Allocate working blocks now so that we don't have to allocate them // each time Transform(Final)Block is called block = new ulong[cipherWords]; tempBlock = new ulong[cipherWords]; streamBytes = new byte[cipherBytes]; depadBuffer = new byte[cipherBytes]; this.iv = new ulong[cipherWords]; GetBytes(iv, 0, this.iv, cipherBytes); switch (OutputBlockSize) { case 256 / 8: cipher = new Threefish256(); break; case 512 / 8: cipher = new Threefish512(); break; case 1024 / 8: cipher = new Threefish1024(); break; default: throw new CryptographicException("Unsupported key/block size."); } bool e = transformMode == ThreefishTransformMode.Encrypt; switch (cipherMode) { case CipherMode.ECB: transformFunc = e ? EcbEncrypt : new TransformFunc(EcbDecrypt); break; case CipherMode.CBC: transformFunc = e ? CbcEncrypt : new TransformFunc(CbcDecrypt); break; case CipherMode.OFB: transformFunc = OfbApplyStream; break; case CipherMode.CFB: transformFunc = e ? CfbEncrypt : new TransformFunc(CfbDecrypt); break; default: throw new CryptographicException("Unsupported cipher mode."); } var keyWords = new ulong[cipherWords]; GetBytes(key, 0, keyWords, cipherBytes); cipher.SetKey(keyWords); InitializeBlocks(); }
public void GenerateConfiguration() { var cipher = ThreefishCipher.CreateCipher(stateSize); var tweak = new UbiTweak(); tweak.StartNewBlockType(UbiType.Config); tweak.IsFinalBlock = true; tweak.BitsProcessed = 32; cipher.SetTweak(tweak.Tweak); cipher.Encrypt(ConfigString, ConfigValue); ConfigValue[0] ^= ConfigString[0]; ConfigValue[1] ^= ConfigString[1]; ConfigValue[2] ^= ConfigString[2]; }