public ICipherBuilder <AlgorithmIdentifier> Build(char[] password)
        {
            if (algorithm.Equals(PkcsObjectIdentifiers.IdPbeS2))
            {
                IPasswordBasedDeriverBuilder <FipsPbkd.Parameters> pbeDeriverBuilder = CryptoServicesRegistrar.CreateService(FipsPbkd.PbkdF2).From(converter, password);

                IPasswordBasedDeriver <FipsPbkd.Parameters> pbeDeriver = pbeDeriverBuilder
                                                                         .WithPrf(digestAlgorithm)
                                                                         .WithSalt(salt)
                                                                         .WithIterationCount(iterationCount)
                                                                         .Build();

                byte[] keyEnc = pbeDeriver.DeriveKey(TargetKeyType.CIPHER, (int)Utils.keySizesInBytes[keyEncAlgorithm]);

                EncryptionScheme encScheme = Utils.GetEncryptionSchemeIdentifier(keyEncAlgorithm, random);

                PbeS2Parameters algParams = new PbeS2Parameters(
                    new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2, new Pbkdf2Params(salt, iterationCount,
                                                                                           new AlgorithmIdentifier((DerObjectIdentifier)Utils.digestTable[digestAlgorithm], DerNull.Instance))),
                    encScheme);


                IParameters <Algorithm> cipherParams = Utils.GetCipherParameters(encScheme);

                if (Utils.IsBlockMode(cipherParams.Algorithm))
                {
                    return(new PbeBlockCipherBuilder(new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbeS2, algParams), Utils.CreateBlockEncryptorBuilder(keyEncAlgorithm, keyEnc, cipherParams)));
                }
                else if (Utils.IsAeadMode(cipherParams.Algorithm))
                {
                    return(new PkixAeadCipherBuilder(new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbeS2, algParams), Utils.CreateAeadEncryptorBuilder(keyEncAlgorithm, keyEnc, cipherParams)));
                }
                else
                {
                    return(new PkixCipherBuilder(new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbeS2, algParams), Utils.CreateEncryptorBuilder(keyEncAlgorithm, keyEnc, cipherParams)));
                }
            }
            else if (algorithm.Equals(PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc) ||
                     algorithm.Equals(PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc))
            {
                int             keySize   = algorithm.Equals(PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc) ? 16 : 24;
                Pkcs12PbeParams pbeParams = new Pkcs12PbeParams(salt, iterationCount);
                // we ignore converter as it's specified by the algorithm
                IPasswordBasedDeriverBuilder <Pbkd.PbkdParameters> pbeDeriverBuilder = CryptoServicesRegistrar.CreateService(Pbkd.Pkcs12).From(PasswordConverter.PKCS12, password);

                IPasswordBasedDeriver <Pbkd.PbkdParameters> pbeDeriver = pbeDeriverBuilder
                                                                         .WithPrf(FipsShs.Sha1)
                                                                         .WithSalt(pbeParams.GetIV())
                                                                         .WithIterationCount(pbeParams.Iterations.IntValue)
                                                                         .Build();

                byte[][]            keyIV      = pbeDeriver.DeriveKeyAndIV(TargetKeyType.CIPHER, keySize, 8);
                AlgorithmIdentifier algDetails = new AlgorithmIdentifier(algorithm, pbeParams);

                return(new PbeBlockCipherBuilder(algDetails, Utils.CreateBlockEncryptorBuilder(algDetails, keyIV[0], keyIV[1])));
            }

            throw new InvalidOperationException("cannot match algorithm: " + algorithm);
        }
            public ICipherBuilder <AlgorithmIdentifier> CreateDecryptorBuilder(AlgorithmIdentifier algorithmDetails)
            {
                if (algorithmDetails.Algorithm.Equals(PkcsObjectIdentifiers.IdPbeS2))
                {
                    IPasswordBasedDeriverBuilder <FipsPbkd.Parameters> pbeDeriverBuilder = CryptoServicesRegistrar.CreateService(FipsPbkd.PbkdF2).From(converter.Convert(password));
                    PbeS2Parameters     pbeParams   = PbeS2Parameters.GetInstance(algorithmDetails.Parameters);
                    Pbkdf2Params        pbkdfParams = Pbkdf2Params.GetInstance(pbeParams.KeyDerivationFunc.Parameters);
                    AlgorithmIdentifier encScheme   = pbeParams.EncryptionScheme;
                    IPasswordBasedDeriver <FipsPbkd.Parameters> pbeDeriver = pbeDeriverBuilder
                                                                             .WithPrf((DigestAlgorithm)Utils.digestTable[pbkdfParams.Prf.Algorithm])
                                                                             .WithSalt(pbkdfParams.GetSalt())
                                                                             .WithIterationCount(pbkdfParams.IterationCount.IntValue)
                                                                             .Build();

                    byte[] keyEnc = pbeDeriver.DeriveKey(TargetKeyType.CIPHER, (pbkdfParams.KeyLength != null ? pbkdfParams.KeyLength.IntValue : (int)Utils.keySizesInBytes[encScheme.Algorithm]));
                    IParameters <Algorithm> cipherParams = Utils.GetCipherParameters(encScheme);

                    if (Utils.IsBlockMode(cipherParams.Algorithm))
                    {
                        return(new PbeBlockCipherBuilder(algorithmDetails, Utils.CreateBlockDecryptorBuilder(encScheme, keyEnc, cipherParams)));
                    }
                    else if (Utils.IsAeadMode(cipherParams.Algorithm))
                    {
                        return(new PkixAeadCipherBuilder(algorithmDetails, Utils.CreateAeadDecryptorBuilder(encScheme, keyEnc, cipherParams)));
                    }
                    else
                    {
                        return(new PkixCipherBuilder(algorithmDetails, Utils.CreateDecryptorBuilder(encScheme, keyEnc, cipherParams)));
                    }
                }
                else if (algorithmDetails.Algorithm.Equals(PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc) ||
                         algorithmDetails.Algorithm.Equals(PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc))
                {
                    int             keySize   = algorithmDetails.Algorithm.Equals(PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc) ? 16 : 24;
                    Pkcs12PbeParams pbeParams = Pkcs12PbeParams.GetInstance(algorithmDetails.Parameters);
                    // we ignore converter as it's specified by the algorithm
                    IPasswordBasedDeriverBuilder <Pbkd.PbkdParameters> pbeDeriverBuilder = CryptoServicesRegistrar.CreateService(Pbkd.Pkcs12).From(PasswordConverter.PKCS12, password);

                    IPasswordBasedDeriver <Pbkd.PbkdParameters> pbeDeriver = pbeDeriverBuilder
                                                                             .WithPrf(FipsShs.Sha1)
                                                                             .WithSalt(pbeParams.GetIV())
                                                                             .WithIterationCount(pbeParams.Iterations.IntValue)
                                                                             .Build();

                    byte[][] keyIV = pbeDeriver.DeriveKeyAndIV(TargetKeyType.CIPHER, keySize, 8);

                    return(new PbeBlockCipherBuilder(algorithmDetails, Utils.CreateDecryptorBuilder(algorithmDetails, keyIV[0], keyIV[1])));
                }

                throw new InvalidOperationException("cannot match algorithm: " + algorithmDetails.Algorithm);
            }