using System;
using System.Collections;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Math;

namespace Org.BouncyCastle.Asn1.Pkcs
{
    public class RsaPrivateKeyStructure
        : Asn1Encodable
    {
        private readonly BigInteger	modulus;
        private readonly BigInteger	publicExponent;
        private readonly BigInteger	privateExponent;
        private readonly BigInteger	prime1;
        private readonly BigInteger	prime2;
        private readonly BigInteger	exponent1;
        private readonly BigInteger	exponent2;
        private readonly BigInteger	coefficient;

		public RsaPrivateKeyStructure(
            BigInteger	modulus,
            BigInteger	publicExponent,
            BigInteger	privateExponent,
            BigInteger	prime1,
            BigInteger	prime2,
            BigInteger	exponent1,
            BigInteger	exponent2,
            BigInteger	coefficient)
        {
            this.modulus = modulus;
            this.publicExponent = publicExponent;
            this.privateExponent = privateExponent;
            this.prime1 = prime1;
            this.prime2 = prime2;
            this.exponent1 = exponent1;
            this.exponent2 = exponent2;
            this.coefficient = coefficient;
        }

		public RsaPrivateKeyStructure(
            Asn1Sequence seq)
        {
			BigInteger version = ((DerInteger) seq[0]).Value;
			if (version.IntValue != 0)
                throw new ArgumentException("wrong version for RSA private key");

			modulus = ((DerInteger) seq[1]).Value;
			publicExponent = ((DerInteger) seq[2]).Value;
			privateExponent = ((DerInteger) seq[3]).Value;
			prime1 = ((DerInteger) seq[4]).Value;
			prime2 = ((DerInteger) seq[5]).Value;
			exponent1 = ((DerInteger) seq[6]).Value;
			exponent2 = ((DerInteger) seq[7]).Value;
			coefficient = ((DerInteger) seq[8]).Value;
		}

		public BigInteger Modulus
		{
			get { return modulus; }
		}

		public BigInteger PublicExponent
		{
			get { return publicExponent; }
		}

		public BigInteger PrivateExponent
		{
			get { return privateExponent; }
		}

		public BigInteger Prime1
		{
			get { return prime1; }
		}

		public BigInteger Prime2
		{
			get { return prime2; }
		}

		public BigInteger Exponent1
		{
			get { return exponent1; }
		}

		public BigInteger Exponent2
		{
			get { return exponent2; }
		}

		public BigInteger Coefficient
		{
			get { return coefficient; }
		}

		/**
         * This outputs the key in Pkcs1v2 format.
         * <pre>
         *      RsaPrivateKey ::= Sequence {
         *                          version Version,
         *                          modulus Integer, -- n
         *                          publicExponent Integer, -- e
         *                          privateExponent Integer, -- d
         *                          prime1 Integer, -- p
         *                          prime2 Integer, -- q
         *                          exponent1 Integer, -- d mod (p-1)
         *                          exponent2 Integer, -- d mod (q-1)
         *                          coefficient Integer -- (inverse of q) mod p
         *                      }
         *
         *      Version ::= Integer
         * </pre>
         * <p>This routine is written to output Pkcs1 version 0, private keys.</p>
         */
        public override Asn1Object ToAsn1Object()
        {
			return new DerSequence(
				new DerInteger(0), // version
				new DerInteger(Modulus),
				new DerInteger(PublicExponent),
				new DerInteger(PrivateExponent),
				new DerInteger(Prime1),
				new DerInteger(Prime2),
				new DerInteger(Exponent1),
				new DerInteger(Exponent2),
				new DerInteger(Coefficient));
        }
    }
}
