<commit_before>﻿/* Copyright 2012 <NAME> (<EMAIL>)
*  
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*  
*      http://www.apache.org/licenses/LICENSE-2.0
*  
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Keyczar.Crypto;
using Keyczar.Util;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.OpenSsl;

namespace Keyczar.Compat
{
    /// <summary>
    /// Imported Keyset, can be used for compatiblity with keys stored as PEM,DER or X509 certificates
    /// </summary>
    public class ImportedKeySet : IKeySet, IDisposable
    {
        /// <summary>
        /// Methods of this property are the import commands
        /// </summary>
        public static Importer Import = new Importer();


        private readonly KeyMetadata _metadata;
        private Key _key;

        /// <summary>
        /// Initializes a new instance of the <see cref="ImportedKeySet"/> class.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="purpose">The purpose.</param>
        /// <param name="description">The description.</param>
        public ImportedKeySet(Key key, KeyPurpose purpose, string description = null)
        {
            _key = key;
            var keyType = key.KeyType;
            _metadata = new KeyMetadata()
            {
                Name = description ?? "Imported" + key.KeyType.Identifier,
                Purpose = purpose,
                Kind = key.KeyType.Kind,
                Versions = new List<KeyVersion>
                                  {
                                      new KeyVersion
                                      {
                                          KeyType = keyType,
                                          VersionNumber = 1,
                                          Status = KeyStatus.Primary,
                                          Exportable = false
                                      }
                                  }
            };
        }


        /// <summary>
        /// Gets the binary data that the key is stored in.
        /// </summary>
        /// <param name="version">The version.</param>
        /// <returns></returns>
        public byte[] GetKeyData(int version)
        {
            return Keyczar.RawStringEncoding.GetBytes(_key.ToJson());
        }

        /// <summary>
        /// Gets the meta data.
        /// </summary>
        /// <value>The meta data.</value>
        public KeyMetadata Metadata
        {
            get { return _metadata; }
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Finalizes an instance of the <see cref="ImportedKeySet" /> class.
        /// </summary>
        ~ImportedKeySet()
        {
            Dispose(false);
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources.
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            _key = _key.SafeDispose();
        }

        /// <summary>
        /// Turns files into importedkeysets
        /// </summary>
        public class Importer
        {
            /// <summary>
            ///  password finder used for bouncy castle api
            /// </summary>
            public class PasswordFinder : IPasswordFinder
            {
                private Func<string> _password;

                /// <summary>
                /// Initializes a new instance of the <see cref="PasswordFinder"/> class.
                /// </summary>
                /// <param name="password">The pass<PASSWORD>.</param>
                public PasswordFinder(Func<string> password)
                {
                    _password = password;
                }

                /// <summary>
                /// Gets the password.
                /// </summary>
                /// <returns></returns>
                public char[] GetPassword()
                {
                    if (_password == null)
                    {
                        return null;
                    }
                    return _password().ToCharArray();
                }
            }


         

            /// <summary>
            /// Import the PKCS key.
            /// </summary>
            /// <param name="purpose">The purpose.</param>
            /// <param name="path">The path.</param>
            /// <param name="passwordPrompt">The pass phrase prompt.</param>
            /// <returns></returns>
            public ImportedKeySet PkcsKey(KeyPurpose purpose, string path, Func<string> passwordPrompt = null)
            {
                using (var stream = File.OpenRead(path))
                    return PkcsKey(purpose, stream, passwordPrompt);
            }

            /// <summary>
            /// Import the PKCS key.
            /// </summary>
            /// <param name="purpose">The purpose.</param>
            /// <param name="input">The input.</param>
            /// <param name="passwordPrompt">The pass phrase prompt.</param>
            /// <returns></returns>
            /// <exception cref="InvalidKeySetException">DSA key cannot be used for encryption and decryption!</exception>
            /// <exception cref="InvalidKeySetException">Unsupported key type!</exception>
            public virtual ImportedKeySet PkcsKey(KeyPurpose purpose, Stream input, Func<string> passwordPrompt = null)
            {
                using (var password = CachedPrompt.Password(passwordPrompt))
                {
                    AsymmetricKeyParameter bouncyKey;
                    var resetStream = Utility.ResetStreamWhenFinished(input);<commit_msg>Rough pkcs12 imported keyset<commit_after>﻿/* Copyright 2012 <NAME> (<EMAIL>)
*  
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*  
*      http://www.apache.org/licenses/LICENSE-2.0
*  
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Keyczar.Crypto;
using Keyczar.Util;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;

namespace Keyczar.Compat
{
    /// <summary>
    /// Imported Keyset, can be used for compatiblity with keys stored as PEM,DER or X509 certificates
    /// </summary>
    public class ImportedKeySet : IKeySet, IDisposable
    {
        /// <summary>
        /// Methods of this property are the import commands
        /// </summary>
        public static Importer Import = new Importer();


        private readonly KeyMetadata _metadata;
        private IList<Key> _key = new List<Key>();

        /// <summary>
        /// Initializes a new instance of the <see cref="ImportedKeySet"/> class.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="purpose">The purpose.</param>
        /// <param name="description">The description.</param>
        public ImportedKeySet(Key key, KeyPurpose purpose, string description = null)
        {
            _key.Add(key);
            var keyType = key.KeyType;
            _metadata = new KeyMetadata()
            {
                Name = description ?? "Imported" + key.KeyType.Identifier,
                Purpose = purpose,
                Kind = key.KeyType.Kind,
                Versions = new List<KeyVersion>
                                  {
                                      new KeyVersion
                                      {
                                          KeyType = keyType,
                                          VersionNumber = 1,
                                          Status = KeyStatus.Primary,
                                          Exportable = false
                                      }
                                  }
            };
        }

        public ImportedKeySet(IEnumerable<Key> keys, KeyPurpose purpose, string description = null)
        {
            _key = keys.ToList();
            _metadata = new KeyMetadata()
            {
                Name = description,
                Purpose = purpose,
                Kind = keys.First().KeyType.Kind,
                Versions = keys.Select((it, i) => new KeyVersion
                {
                    KeyType = it.KeyType,
                    VersionNumber = i,
                    Exportable = false
                }).ToList()
            };
        }



        /// <summary>
        /// Gets the binary data that the key is stored in.
        /// </summary>
        /// <param name="version">The version.</param>
        /// <returns></returns>
        public byte[] GetKeyData(int version)
        {
            return Keyczar.RawStringEncoding.GetBytes(_key[version-1].ToJson());
        }

        /// <summary>
        /// Gets the meta data.
        /// </summary>
        /// <value>The meta data.</value>
        public KeyMetadata Metadata
        {
            get { return _metadata; }
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Finalizes an instance of the <see cref="ImportedKeySet" /> class.
        /// </summary>
        ~ImportedKeySet()
        {
            Dispose(false);
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources.
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            _key = _key.Select(k=>k.SafeDispose()).ToList();
            _key = new List<Key>();
        }

        /// <summary>
        /// Turns files into importedkeysets
        /// </summary>
        public class Importer
        {
            /// <summary>
            ///  password finder used for bouncy castle api
            /// </summary>
            public class PasswordFinder : IPasswordFinder
            {
                private Func<string> _password;

                /// <summary>
                /// Initializes a new instance of the <see cref="PasswordFinder"/> class.
                /// </summary>
                /// <param name="password">The passs<PASSWORD>.</param>
                public PasswordFinder(Func<string> password)
                {
                    _password = password;
                }

                /// <summary>
                /// Gets the password.
                /// </summary>
                /// <returns></returns>
                public char[] GetPassword()
                {
                    if (_password == null)
                    {
                        return null;
                    }
                    return _password().ToCharArray();
                }
            }


         

            /// <summary>
            /// Import the PKCS key.
            /// </summary>
            /// <param name="purpose">The purpose.</param>
            /// <param name="path">The path.</param>
            /// <param name="passwordPrompt">The pass phrase prompt.</param>
            /// <returns></returns>
            public ImportedKeySet PkcsKey(KeyPurpose purpose, string path, Func<string> passwordPrompt = null)
            {
                using (var stream = File.OpenRead(path))
                    return PkcsKey(purpose, stream, passwordPrompt);
            }

            public virtual ImportedKeySet Pkcs12Keys(KeyPurpose purpose, Stream input, Func<string> passwordPrompt = null)
            {
                
                using (var password = CachedPrompt.Password(passwordPrompt))
                {
                    var keyStore = new Pkcs12Store(input, password.Prompt().ToCharArray());
                    var keys = new List<Key>();
                    var kind = KeyKind.Private;
                    foreach (string n in keyStore.Aliases)
                    {
                        if (keyStore.IsKeyEntry(n))
                        {
                            AsymmetricKeyEntry key = keyStore.GetKey(n);

                            if (key.Key.IsPrivate)
                            {
                                switch(key.Key){
                                    case RsaPrivateCrtKeyParameters rsa:
                                        {
                                            var newKey = new RsaPrivateKey()
                                            {
                                                PublicKey = new RsaPublicKey()
                                                {
                                                    Modulus = rsa.Modulus.ToSystemBigInteger(),
                                                    PublicExponent = rsa.PublicExponent.ToSystemBigInteger(),
                                                    Size = rsa.Modulus.BitLength,
                                                },
                                                PrimeP = rsa.P.ToSystemBigInteger(),
                                                PrimeExponentP = rsa.DP.ToSystemBigInteger(),
                                                PrimeExponentQ = rsa.DQ.ToSystemBigInteger(),
                                                PrimeQ = rsa.Q.ToSystemBigInteger(),
                                                CrtCoefficient = rsa.QInv.ToSystemBigInteger(),
                                                PrivateExponent = rsa.Exponent.ToSystemBigInteger(),
                                                Size = rsa.Modulus.BitLength,
                                            };  
                                            keys.Add(newKey);
                                        }

                                    break;

                                    case DsaPrivateKeyParameters dsa:
                                        {
                                            var dsaKey = new DsaPrivateKey()
                                            {
                                                X = dsa.X.ToSystemBigInteger(),
                                                PublicKey = new DsaPublicKey
                                                {
                                                    Y =
                                                              dsa.Parameters.G.ModPow(dsa.X,
                                                                                           dsa.Parameters.P)
                                                                      .ToSystemBigInteger(),
                                                    G = dsa.Parameters.G.ToSystemBigInteger(),
                                                    P = dsa.Parameters.P.ToSystemBigInteger(),
                                                    Q = dsa.Parameters.Q.ToSystemBigInteger(),
                                                    Size = dsa.Parameters.P.BitLength
                                                },
                                                Size = dsa.Parameters.P.BitLength
                                            }; 
                                            keys.Add(dsaKey);
                                        }

                                    break;
                                }


                            }
                        }
                    }
                    if(!keys.Any()){
                        kind = KeyKind.Public;

                        foreach (string n in keyStore.Aliases)
                        {
                            if (keyStore.IsCertificateEntry(n))
                            {

                                var entry = keyStore.GetCertificate(n);

                                var pubKey = entry.Certificate.GetPublicKey();
                               
                                switch(pubKey){
                                    case RsaKeyParameters rsa:
                                        {
                                            var rsaKey = new RsaPublicKey
                                            {
                                                Modulus = rsa.Modulus.ToSystemBigInteger(),
                                                PublicExponent = rsa.Exponent.ToSystemBigInteger(),
                                                Size = rsa.Modulus.BitLength,
                                            };
                                            keys.Add(rsaKey);
                                        }
                                        break;
                                    case DsaPublicKeyParameters dsa:
                                        {
                                            var dsaKey = new DsaPublicKey
                                            {
                                                Y = dsa.Y.ToSystemBigInteger(),
                                                G = dsa.Parameters.G.ToSystemBigInteger(),
                                                P = dsa.Parameters.P.ToSystemBigInteger(),
                                                Q = dsa.Parameters.Q.ToSystemBigInteger(),
                                                Size = dsa.Parameters.P.BitLength
                                            };
                                            keys.Add(dsaKey);
                                        }
                                        break;
                                }


                            }
                        } 
                    }

                    if(keys.Any()){
                        return new ImportedKeySet(keys, purpose, "imported keys");
                    }
                    throw new InvalidKeySetException("couldn't find any keys in file");

                }
            }



            /// <summary>
            /// Import the PKCS key.
            /// </summary>
            /// <param name="purpose">The purpose.</param>
            /// <param name="input">The input.</param>
            /// <param name="passwordPrompt">The pass phrase prompt.</param>
            /// <returns></returns>
            /// <exception cref="InvalidKeySetException">DSA key cannot be used for encryption and decryption!</exception>
            /// <exception cref="InvalidKeySetException">Unsupported key type!</exception>
            public virtual ImportedKeySet PkcsKey(KeyPurpose purpose, Stream input, Func<string> passwordPrompt = null)
            {
                using (var password = CachedPrompt.Password(passwordPrompt))
                {
                    AsymmetricKeyParameter bouncyKey;
                    var resetStream = Utility.ResetStreamWhenFinished(input);
{'fraction_non_alphanumeric': 0.09062836976766983, 'fraction_numerical': 0.0018135476914028037, 'mean_word_length': 1.0165052381893656, 'pattern_counts': {'":': 0, '<': 171, '<?xml version=': 0, '>': 173, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 149, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '962516', 'n_tokens_mistral': 4504, 'n_tokens_neox': 4288, 'n_words': 1118}