From 84fedf4379a93d60e5be64770ec8228b7b25439b Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 22 Nov 2005 19:10:05 +0000 Subject: 2005-11-22 Sebastien Pouliot * PublicKey.cs: Completed implementation for both RSA and DSA public keys. svn path=/trunk/mcs/; revision=53358 --- .../ChangeLog | 5 + .../PublicKey.cs | 126 ++++++++++++++++++--- 2 files changed, 117 insertions(+), 14 deletions(-) (limited to 'mcs/class/System/System.Security.Cryptography.X509Certificates') diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/ChangeLog b/mcs/class/System/System.Security.Cryptography.X509Certificates/ChangeLog index 3d24210a348..e6bdd73a3a1 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/ChangeLog +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/ChangeLog @@ -1,3 +1,8 @@ +2005-11-22 Sebastien Pouliot + + * PublicKey.cs: Completed implementation for both RSA and DSA public + keys. + 2005-11-08 Sebastien Pouliot * OpenFlags.cs: Removed extra [Serializable] (not in 2.0). diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/PublicKey.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/PublicKey.cs index 1f4f840f5f4..0ad64d445e8 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/PublicKey.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/PublicKey.cs @@ -2,13 +2,12 @@ // PublicKey.cs - System.Security.Cryptography.PublicKey // // Author: -// Sebastien Pouliot (spouliot@motus.com) +// Sebastien Pouliot // Tim Coleman (tim@timcoleman.com) // // (C) 2003 Motus Technologies Inc. (http://www.motus.com) // Copyright (C) Tim Coleman, 2004 -// - +// Copyright (C) 2005 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -32,31 +31,40 @@ #if NET_2_0 && SECURITY_DEP -namespace System.Security.Cryptography.X509Certificates { +using Mono.Security; +using MSX = Mono.Security.X509; - // Note: Match the definition of framework version 1.2.3400.0 on http://longhorn.msdn.microsoft.com +namespace System.Security.Cryptography.X509Certificates { public sealed class PublicKey { + private const string rsaOid = "1.2.840.113549.1.1.1"; + private const string dsaOid = "1.2.840.10040.4.1"; + private AsymmetricAlgorithm _key; private AsnEncodedData _keyValue; private AsnEncodedData _params; private Oid _oid; - [MonoTODO] public PublicKey (Oid oid, AsnEncodedData parameters, AsnEncodedData keyValue) { - _oid = oid; - _params = parameters; - _keyValue = keyValue; + if (oid == null) + throw new ArgumentNullException ("oid"); + if (parameters == null) + throw new ArgumentNullException ("parameters"); + if (keyValue == null) + throw new ArgumentNullException ("keyValue"); + + _oid = new Oid (oid); + _params = new AsnEncodedData (parameters); + _keyValue = new AsnEncodedData (keyValue); } - internal PublicKey (Mono.Security.X509.X509Certificate certificate) + internal PublicKey (MSX.X509Certificate certificate) { - if (certificate.KeyAlgorithm == "1.2.840.113549.1.1.1") { + if (certificate.KeyAlgorithm == rsaOid) { _key = certificate.RSA; - } - else { + } else { _key = certificate.DSA; } @@ -76,12 +84,102 @@ namespace System.Security.Cryptography.X509Certificates { } public AsymmetricAlgorithm Key { - get { return _key; } + get { + if (_key == null) { + switch (_oid.Value) { + case rsaOid: + _key = DecodeRSA (_keyValue.RawData); + break; + case dsaOid: + _key = DecodeDSA (_keyValue.RawData, _params.RawData); + break; + default: + string msg = Locale.GetText ("Cannot decode public key from unknown OID '{0}'.", _oid.Value); + throw new NotSupportedException (msg); + } + } + return _key; + } } public Oid Oid { get { return _oid; } } + + // private stuff + + static private byte[] GetUnsignedBigInteger (byte[] integer) + { + if (integer [0] != 0x00) + return integer; + + // this first byte is added so we're sure it's an unsigned integer + // however we can't feed it into RSAParameters or DSAParameters + int length = integer.Length - 1; + byte[] uinteger = new byte [length]; + Buffer.BlockCopy (integer, 1, uinteger, 0, length); + return uinteger; + } + + static internal DSA DecodeDSA (byte[] rawPublicKey, byte[] rawParameters) + { + DSAParameters dsaParams = new DSAParameters (); + try { + // for DSA rawPublicKey contains 1 ASN.1 integer - Y + ASN1 pubkey = new ASN1 (rawPublicKey); + if (pubkey.Tag != 0x02) + throw new CryptographicException (Locale.GetText ("Missing DSA Y integer.")); + dsaParams.Y = GetUnsignedBigInteger (pubkey.Value); + + ASN1 param = new ASN1 (rawParameters); + if ((param == null) || (param.Tag != 0x30) || (param.Count < 3)) + throw new CryptographicException (Locale.GetText ("Missing DSA parameters.")); + if ((param [0].Tag != 0x02) || (param [1].Tag != 0x02) || (param [2].Tag != 0x02)) + throw new CryptographicException (Locale.GetText ("Invalid DSA parameters.")); + + dsaParams.P = GetUnsignedBigInteger (param [0].Value); + dsaParams.Q = GetUnsignedBigInteger (param [1].Value); + dsaParams.G = GetUnsignedBigInteger (param [2].Value); + } + catch (Exception e) { + string msg = Locale.GetText ("Error decoding the ASN.1 structure."); + throw new CryptographicException (msg, e); + } + + DSA dsa = (DSA) new DSACryptoServiceProvider (dsaParams.Y.Length << 3); + dsa.ImportParameters (dsaParams); + return dsa; + } + + static internal RSA DecodeRSA (byte[] rawPublicKey) + { + RSAParameters rsaParams = new RSAParameters (); + try { + // for RSA rawPublicKey contains 2 ASN.1 integers + // the modulus and the public exponent + ASN1 pubkey = new ASN1 (rawPublicKey); + if (pubkey.Count == 0) + throw new CryptographicException (Locale.GetText ("Missing RSA modulus and exponent.")); + ASN1 modulus = pubkey [0]; + if ((modulus == null) || (modulus.Tag != 0x02)) + throw new CryptographicException (Locale.GetText ("Missing RSA modulus.")); + ASN1 exponent = pubkey [1]; + if (exponent.Tag != 0x02) + throw new CryptographicException (Locale.GetText ("Missing RSA public exponent.")); + + rsaParams.Modulus = GetUnsignedBigInteger (modulus.Value); + rsaParams.Exponent = exponent.Value; + } + catch (Exception e) { + string msg = Locale.GetText ("Error decoding the ASN.1 structure."); + throw new CryptographicException (msg, e); + } + + int keySize = (rsaParams.Modulus.Length << 3); + RSA rsa = (RSA) new RSACryptoServiceProvider (keySize); + rsa.ImportParameters (rsaParams); + return rsa; + } } } -- cgit v1.2.3