Example #1
0
        public static KeyInfo GetType(byte[] data)
        {
            if (data == null)
                throw new ArgumentNullException("data");

            KeyInfo ki = KeyInfo.Unknown;
            try
            {
                ASN1 top = new ASN1(data);
                if ((top.Tag == 0x30) && (top.Count > 0))
                {
                    ASN1 firstLevel = top[0];
                    switch (firstLevel.Tag)
                    {
                        case 0x02:
                            ki = KeyInfo.PrivateKey;
                            break;
                        case 0x30:
                            ki = KeyInfo.EncryptedPrivateKey;
                            break;
                    }
                }
            }
            catch
            {
                throw new CryptographicException("invalid ASN.1 data");
            }
            return ki;
        }
Example #2
0
 public static ASN1 FromInt32(Int32 value)
 {
     byte[] integer = BitConverterLE.GetBytes(value);
     Array.Reverse(integer);
     int x = 0;
     while ((x < integer.Length) && (integer[x] == 0x00))
         x++;
     ASN1 asn1 = new ASN1(0x02);
     switch (x)
     {
         case 0:
             asn1.Value = integer;
             break;
         case 4:
             asn1.Value = new byte[1];
             break;
         default:
             byte[] smallerInt = new byte[4 - x];
             Buffer.BlockCopy(integer, x, smallerInt, 0, smallerInt.Length);
             asn1.Value = smallerInt;
             break;
     }
     return asn1;
 }
Example #3
0
 public ASN1 Add(ASN1 asn1)
 {
     if (asn1 != null)
     {
         if (elist == null)
             elist = new ArrayList();
         elist.Add(asn1);
     }
     return asn1;
 }
Example #4
0
        // Convert a binary encoded OID to human readable string representation of
        // an OID (IETF style). Based on DUMPASN1.C from Peter Gutmann.
        public static string ToOid(ASN1 asn1)
        {
            if (asn1 == null)
                throw new ArgumentNullException("asn1");

            byte[] aOID = asn1.Value;
            StringBuilder sb = new StringBuilder();
            // Pick apart the OID
            byte x = (byte)(aOID[0] / 40);
            byte y = (byte)(aOID[0] % 40);
            if (x > 2)
            {
                // Handle special case for large y if x = 2
                y += (byte)((x - 2) * 40);
                x = 2;
            }
            sb.Append(x.ToString(CultureInfo.InvariantCulture));
            sb.Append(".");
            sb.Append(y.ToString(CultureInfo.InvariantCulture));
            ulong val = 0;
            for (x = 1; x < aOID.Length; x++)
            {
                val = ((val << 7) | ((byte)(aOID[x] & 0x7F)));
                if (!((aOID[x] & 0x80) == 0x80))
                {
                    sb.Append(".");
                    sb.Append(val.ToString(CultureInfo.InvariantCulture));
                    val = 0;
                }
            }
            return sb.ToString();
        }
Example #5
0
        public static int ToInt32(ASN1 asn1)
        {
            if (asn1 == null)
                throw new ArgumentNullException("asn1");
            if (asn1.Tag != 0x02)
                throw new FormatException("Only integer can be converted");

            int x = 0;
            for (int i = 0; i < asn1.Value.Length; i++)
                x = (x << 8) + asn1.Value[i];
            return x;
        }
Example #6
0
        public static DateTime ToDateTime(ASN1 time)
        {
            if (time == null)
                throw new ArgumentNullException("time");

            string t = Encoding.ASCII.GetString(time.Value);
            // to support both UTCTime and GeneralizedTime (and not so common format)
            string mask = null;
            int year;
            switch (t.Length)
            {
                case 11:
                    // illegal format, still it's supported for compatibility
                    mask = "yyMMddHHmmZ";
                    break;
                case 13:
                    // RFC3280: 4.1.2.5.1  UTCTime
                    year = Convert.ToInt16(t.Substring(0, 2), CultureInfo.InvariantCulture);
                    // Where YY is greater than or equal to 50, the
                    // year SHALL be interpreted as 19YY; and
                    // Where YY is less than 50, the year SHALL be
                    // interpreted as 20YY.
                    if (year >= 50)
                        t = "19" + t;
                    else
                        t = "20" + t;
                    mask = "yyyyMMddHHmmssZ";
                    break;
                case 15:
                    mask = "yyyyMMddHHmmssZ"; // GeneralizedTime
                    break;
                case 17:
                    // another illegal format (990630000000+1000), again supported for compatibility
                    year = Convert.ToInt16(t.Substring(0, 2), CultureInfo.InvariantCulture);
                    string century = (year >= 50) ? "19" : "20";
                    // ASN.1 (see ITU X.680 section 43.3) deals with offset differently than .NET
                    char sign = (t[12] == '+') ? '-' : '+';
                    t = String.Format("{0}{1}{2}{3}{4}:{5}{6}", century, t.Substring(0, 12), sign,
                        t[13], t[14], t[15], t[16]);
                    mask = "yyyyMMddHHmmsszzz";
                    break;
            }
            return DateTime.ParseExact(t, mask, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
        }
Example #7
0
            public byte[] GetBytes()
            {
                ASN1 privateKeyAlgorithm = new ASN1(0x30);
                privateKeyAlgorithm.Add(ASN1Convert.FromOid(_algorithm));
                privateKeyAlgorithm.Add(new ASN1(0x05)); // ASN.1 NULL

                ASN1 pki = new ASN1(0x30);
                pki.Add(new ASN1(0x02, new byte[1] { (byte)_version }));
                pki.Add(privateKeyAlgorithm);
                pki.Add(new ASN1(0x04, _key));

                if (_list.Count > 0)
                {
                    ASN1 attributes = new ASN1(0xA0);
                    foreach (ASN1 attribute in _list)
                    {
                        attributes.Add(attribute);
                    }
                    pki.Add(attributes);
                }

                return pki.GetBytes();
            }
Example #8
0
            // methods
            private void Decode(byte[] data)
            {
                ASN1 privateKeyInfo = new ASN1(data);
                if (privateKeyInfo.Tag != 0x30)
                    throw new CryptographicException("invalid PrivateKeyInfo");

                ASN1 version = privateKeyInfo[0];
                if (version.Tag != 0x02)
                    throw new CryptographicException("invalid version");
                _version = version.Value[0];

                ASN1 privateKeyAlgorithm = privateKeyInfo[1];
                if (privateKeyAlgorithm.Tag != 0x30)
                    throw new CryptographicException("invalid algorithm");

                ASN1 algorithm = privateKeyAlgorithm[0];
                if (algorithm.Tag != 0x06)
                    throw new CryptographicException("missing algorithm OID");
                _algorithm = ASN1Convert.ToOid(algorithm);

                ASN1 privateKey = privateKeyInfo[2];
                _key = privateKey.Value;

                // attributes [0] IMPLICIT Attributes OPTIONAL
                if (privateKeyInfo.Count > 3)
                {
                    ASN1 attributes = privateKeyInfo[3];
                    for (int i = 0; i < attributes.Count; i++)
                    {
                        _list.Add(attributes[i]);
                    }
                }
            }
Example #9
0
            /*
             * 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
             *	otherPrimeInfos   OtherPrimeInfos OPTIONAL
             * }
             */
            public static byte[] Encode(RSA rsa)
            {
                RSAParameters param = rsa.ExportParameters(true);

                ASN1 rsaPrivateKey = new ASN1(0x30);
                rsaPrivateKey.Add(new ASN1(0x02, new byte[1] { 0x00 }));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.Modulus));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.Exponent));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.D));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.P));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.Q));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.DP));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.DQ));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.InverseQ));

                return rsaPrivateKey.GetBytes();
            }
Example #10
0
            /*
             * 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
             *	otherPrimeInfos   OtherPrimeInfos OPTIONAL
             * }
             */
            public static RSA DecodeRSA(byte[] keypair)
            {
                ASN1 privateKey = new ASN1(keypair);
                if (privateKey.Tag != 0x30)
                    throw new CryptographicException("invalid private key format");

                ASN1 version = privateKey[0];
                if (version.Tag != 0x02)
                    throw new CryptographicException("missing version");

                if (privateKey.Count < 9)
                    throw new CryptographicException("not enough key parameters");

                RSAParameters param = new RSAParameters();
                // note: MUST remove leading 0 - else MS wont import the key
                param.Modulus = RemoveLeadingZero(privateKey[1].Value);
                int keysize = param.Modulus.Length;
                int keysize2 = (keysize >> 1); // half-size
                // size must be normalized - else MS wont import the key
                param.D = Normalize(privateKey[3].Value, keysize);
                param.DP = Normalize(privateKey[6].Value, keysize2);
                param.DQ = Normalize(privateKey[7].Value, keysize2);
                param.Exponent = RemoveLeadingZero(privateKey[2].Value);
                param.InverseQ = Normalize(privateKey[8].Value, keysize2);
                param.P = Normalize(privateKey[4].Value, keysize2);
                param.Q = Normalize(privateKey[5].Value, keysize2);

                RSA rsa = null;
                try
                {
                    rsa = RSA.Create();
                    rsa.ImportParameters(param);
                }
                catch (CryptographicException)
                {
                #if MONOTOUCH
                    // there's no machine-wide store available for iOS so we can drop the dependency on
                    // CspParameters (which drops other things, like XML key persistance, unless used elsewhere)
                    throw;
                #else
                    // this may cause problem when this code is run under
                    // the SYSTEM identity on Windows (e.g. ASP.NET). See
                    // http://bugzilla.ximian.com/show_bug.cgi?id=77559
                    CspParameters csp = new CspParameters();
                    csp.Flags = CspProviderFlags.UseMachineKeyStore;
                    rsa = new RSACryptoServiceProvider(csp);
                    rsa.ImportParameters(param);
                #endif
                }
                return rsa;
            }
Example #11
0
            // DSA only encode it's X private key inside an ASN.1 INTEGER (Hint: Tag == 0x02)
            // which isn't enough for rebuilding the keypair. The other parameters
            // can be found (98% of the time) in the X.509 certificate associated
            // with the private key or (2% of the time) the parameters are in it's
            // issuer X.509 certificate (not supported in the .NET framework).
            public static DSA DecodeDSA(byte[] privateKey, DSAParameters dsaParameters)
            {
                ASN1 pvk = new ASN1(privateKey);
                if (pvk.Tag != 0x02)
                    throw new CryptographicException("invalid private key format");

                // X is ALWAYS 20 bytes (no matter if the key length is 512 or 1024 bits)
                dsaParameters.X = Normalize(pvk.Value, 20);
                DSA dsa = DSA.Create();
                dsa.ImportParameters(dsaParameters);
                return dsa;
            }
Example #12
0
            // methods
            private void Decode(byte[] data)
            {
                ASN1 encryptedPrivateKeyInfo = new ASN1(data);
                if (encryptedPrivateKeyInfo.Tag != 0x30)
                    throw new CryptographicException("invalid EncryptedPrivateKeyInfo");

                ASN1 encryptionAlgorithm = encryptedPrivateKeyInfo[0];
                if (encryptionAlgorithm.Tag != 0x30)
                    throw new CryptographicException("invalid encryptionAlgorithm");
                ASN1 algorithm = encryptionAlgorithm[0];
                if (algorithm.Tag != 0x06)
                    throw new CryptographicException("invalid algorithm");
                _algorithm = ASN1Convert.ToOid(algorithm);
                // parameters ANY DEFINED BY algorithm OPTIONAL
                if (encryptionAlgorithm.Count > 1)
                {
                    ASN1 parameters = encryptionAlgorithm[1];
                    if (parameters.Tag != 0x30)
                        throw new CryptographicException("invalid parameters");

                    ASN1 salt = parameters[0];
                    if (salt.Tag != 0x04)
                        throw new CryptographicException("invalid salt");
                    _salt = salt.Value;

                    ASN1 iterationCount = parameters[1];
                    if (iterationCount.Tag != 0x02)
                        throw new CryptographicException("invalid iterationCount");
                    _iterations = ASN1Convert.ToInt32(iterationCount);
                }

                ASN1 encryptedData = encryptedPrivateKeyInfo[1];
                if (encryptedData.Tag != 0x04)
                    throw new CryptographicException("invalid EncryptedData");
                _data = encryptedData.Value;
            }
Example #13
0
            // Note: PKCS#8 doesn't define how to generate the key required for encryption
            // so you're on your own. Just don't try to copy the big guys too much ;)
            // Netscape:	http://www.cs.auckland.ac.nz/~pgut001/pubs/netscape.txt
            // Microsoft:	http://www.cs.auckland.ac.nz/~pgut001/pubs/breakms.txt
            public byte[] GetBytes()
            {
                if (_algorithm == null)
                    throw new CryptographicException("No algorithm OID specified");

                ASN1 encryptionAlgorithm = new ASN1(0x30);
                encryptionAlgorithm.Add(ASN1Convert.FromOid(_algorithm));

                // parameters ANY DEFINED BY algorithm OPTIONAL
                if ((_iterations > 0) || (_salt != null))
                {
                    ASN1 salt = new ASN1(0x04, _salt);
                    ASN1 iterations = ASN1Convert.FromInt32(_iterations);

                    ASN1 parameters = new ASN1(0x30);
                    parameters.Add(salt);
                    parameters.Add(iterations);
                    encryptionAlgorithm.Add(parameters);
                }

                // encapsulates EncryptedData into an OCTET STRING
                ASN1 encryptedData = new ASN1(0x04, _data);

                ASN1 encryptedPrivateKeyInfo = new ASN1(0x30);
                encryptedPrivateKeyInfo.Add(encryptionAlgorithm);
                encryptedPrivateKeyInfo.Add(encryptedData);

                return encryptedPrivateKeyInfo.GetBytes();
            }