Пример #1
0
 public CryptoConfig(IKdfConfig kdfConfig,
                     CipherModeType cipherMode,
                     IvGenerationModeType ivGenerationMode,
                     SignatureModeType signatureMode)
 {
     KdfConfig        = kdfConfig;
     CipherMode       = cipherMode;
     IvGenerationMode = ivGenerationMode;
     SignatureMode    = signatureMode;
 }
Пример #2
0
            public byte[] GetOrDerive(byte[] password, byte[] salt, IKdfConfig config)
            {
                var id = config.GetUniqueId(password, salt);

                if (_cache.TryGetValue(id, out var key))
                {
                    return(key);
                }

                key        = config.Derive(password, salt);
                _cache[id] = key;

                return(key);
            }
Пример #3
0
        public static Blob ParseFlexibleBlob(byte[] blob)
        {
            // Pieces of the string joined with $ ($1$argon2d$16$3$32768$2$aes256$cbchmac$16$...)

            // This part is the key derivation configuration:
            //   - $1       - version, must be 1
            //   - $argon2d - method, must be "argon2d" or "pbkdf2"
            //
            // For argon2d:
            //   - $16     - salt length
            //   - $3      - time cost
            //   - $32768  - memory cost
            //   - $2      - parallelism
            //
            // For pbkdf2:
            //   - $16     - salt length
            //   - $10000  - number of iterations
            //   - $sha256 - hash method
            //
            // The next part is the cipher/encryption configuration:
            //   - $aes256  - cipher, must be aes256
            //   - $cbchmac - AES mode, must be cbchmac, cbc or gcm
            //   - $16      - IV length
            //
            // Signature is always "hmac"
            // IV derivation could be either "data" or "evpByteToKey"
            //
            // After the crypto configuration:
            //   - salt       - "salt length" bytes
            //   - IV         - "IV length" bytes
            //   - MAC        - 32 bytes
            //   - ciphertext - the rest

            var offset = 1;

            var version = GetNextComponent(blob, ref offset);

            if (version != "1")
            {
                throw new InternalErrorException($"Unsupported version: {version}");
            }

            IKdfConfig kdfConfig = null;
            var        method    = GetNextComponent(blob, ref offset);

            switch (method)
            {
            case "argon2d":
            {
                var saltLength  = int.Parse(GetNextComponent(blob, ref offset));
                var timeCost    = int.Parse(GetNextComponent(blob, ref offset));
                var memoryCost  = int.Parse(GetNextComponent(blob, ref offset));
                var parallelism = int.Parse(GetNextComponent(blob, ref offset));
                kdfConfig = new Argon2dConfig(memoryCost: memoryCost,
                                              timeCost: timeCost,
                                              parallelism: parallelism,
                                              saltLength: saltLength);
            }
            break;

            case "pbkdf2":
            {
                var saltLength = int.Parse(GetNextComponent(blob, ref offset));
                var iterations = int.Parse(GetNextComponent(blob, ref offset));

                Pbkdf2Config.HashMethodType hashMethod;
                string hashMethodStr = GetNextComponent(blob, ref offset);
                switch (hashMethodStr)
                {
                case "sha1":
                    hashMethod = Pbkdf2Config.HashMethodType.Sha1;
                    break;

                case "sha256":
                    hashMethod = Pbkdf2Config.HashMethodType.Sha256;
                    break;

                default:
                    throw new InternalErrorException($"Unknown PBKDF2 hashing method: {hashMethodStr}");
                }

                kdfConfig = new Pbkdf2Config(hashMethod: hashMethod,
                                             iterations: iterations,
                                             saltLength: saltLength);
            }
            break;

            default:
                throw new InternalErrorException($"Unexpected hashing method: {method}");
            }

            var cipher = GetNextComponent(blob, ref offset);

            if (cipher != "aes256")
            {
                throw new InternalErrorException($"Unexpected cipher: {cipher}");
            }

            CryptoConfig.CipherModeType cipherMode;
            var cipherModeStr = GetNextComponent(blob, ref offset);

            switch (cipherModeStr)
            {
            case "cbc":
                cipherMode = CryptoConfig.CipherModeType.Cbc;
                break;

            case "cbchmac":
                cipherMode = CryptoConfig.CipherModeType.CbcHmac;
                break;

            case "gcm":
                cipherMode = CryptoConfig.CipherModeType.Gcm;
                break;

            default:
                throw new InternalErrorException($"Unknown cipher mode: {cipherModeStr}");
            }

            var cryptoConfig = new CryptoConfig(kdfConfig,
                                                cipherMode,
                                                CryptoConfig.IvGenerationModeType.Data,
                                                CryptoConfig.SignatureModeType.HmacSha256);

            var ivLength = int.Parse(GetNextComponent(blob, ref offset));

            var salt = blob.Sub(offset, kdfConfig.SaltLength);

            offset += kdfConfig.SaltLength;

            var iv = blob.Sub(offset, ivLength);

            offset += ivLength;

            var hash = blob.Sub(offset, 32);

            offset += 32;

            var ciphertext = blob.Sub(offset, int.MaxValue);

            return(new Blob(ciphertext: ciphertext, salt: salt, iv: iv, hash: hash, cryptoConfig: cryptoConfig));
        }