private static unsafe SafeLocalAllocHandle EncodePublicKey(PublicKey key)
        {
            SafeLocalAllocHandle invalidHandle = SafeLocalAllocHandle.InvalidHandle;

            CAPIBase.CERT_PUBLIC_KEY_INFO2 *handle = null;
            string s = key.Oid.Value;

            byte[] rawData = key.EncodedParameters.RawData;
            byte[] source  = key.EncodedKeyValue.RawData;
            uint   num     = (uint)(((Marshal.SizeOf(typeof(CAPIBase.CERT_PUBLIC_KEY_INFO2)) + System.Security.Cryptography.X509Certificates.X509Utils.AlignedLength((uint)(s.Length + 1))) + System.Security.Cryptography.X509Certificates.X509Utils.AlignedLength((uint)rawData.Length)) + source.Length);

            invalidHandle = CAPI.LocalAlloc(0x40, new IntPtr((long)num));
            handle        = (CAPIBase.CERT_PUBLIC_KEY_INFO2 *)invalidHandle.DangerousGetHandle();
            IntPtr destination = new IntPtr(((long)((ulong)handle)) + Marshal.SizeOf(typeof(CAPIBase.CERT_PUBLIC_KEY_INFO2)));
            IntPtr ptr2        = new IntPtr(((long)destination) + System.Security.Cryptography.X509Certificates.X509Utils.AlignedLength((uint)(s.Length + 1)));
            IntPtr ptr3        = new IntPtr(((long)ptr2) + System.Security.Cryptography.X509Certificates.X509Utils.AlignedLength((uint)rawData.Length));

            handle->Algorithm.pszObjId = destination;
            byte[] bytes = new byte[s.Length + 1];
            Encoding.ASCII.GetBytes(s, 0, s.Length, bytes, 0);
            Marshal.Copy(bytes, 0, destination, bytes.Length);
            if (rawData.Length > 0)
            {
                handle->Algorithm.Parameters.cbData = (uint)rawData.Length;
                handle->Algorithm.Parameters.pbData = ptr2;
                Marshal.Copy(rawData, 0, ptr2, rawData.Length);
            }
            handle->PublicKey.cbData = (uint)source.Length;
            handle->PublicKey.pbData = ptr3;
            Marshal.Copy(source, 0, ptr3, source.Length);
            return(invalidHandle);
        }
        private static unsafe byte[] EncodePublicKey(PublicKey key, X509SubjectKeyIdentifierHashAlgorithm algorithm)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            SafeLocalAllocHandle handle = EncodePublicKey(key);

            CAPIBase.CERT_PUBLIC_KEY_INFO2 *cert_public_key_infoPtr = (CAPIBase.CERT_PUBLIC_KEY_INFO2 *)handle.DangerousGetHandle();
            byte[] sourceArray      = new byte[20];
            byte[] destinationArray = null;
            fixed(byte *numRef = sourceArray)
            {
                uint   length         = (uint)sourceArray.Length;
                IntPtr pbComputedHash = new IntPtr((void *)numRef);

                try
                {
                    if ((algorithm == X509SubjectKeyIdentifierHashAlgorithm.Sha1) || (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm))
                    {
                        if (!CAPISafe.CryptHashCertificate(IntPtr.Zero, 0x8004, 0, cert_public_key_infoPtr->PublicKey.pbData, cert_public_key_infoPtr->PublicKey.cbData, pbComputedHash, new IntPtr((void *)&length)))
                        {
                            throw new CryptographicException(Marshal.GetHRForLastWin32Error());
                        }
                    }
                    else
                    {
                        if (X509SubjectKeyIdentifierHashAlgorithm.CapiSha1 != algorithm)
                        {
                            throw new ArgumentException("algorithm");
                        }
                        if (!CAPISafe.CryptHashPublicKeyInfo(IntPtr.Zero, 0x8004, 0, 1, new IntPtr((void *)cert_public_key_infoPtr), pbComputedHash, new IntPtr((void *)&length)))
                        {
                            throw new CryptographicException(Marshal.GetHRForLastWin32Error());
                        }
                    }
                    if (X509SubjectKeyIdentifierHashAlgorithm.ShortSha1 == algorithm)
                    {
                        destinationArray = new byte[8];
                        Array.Copy(sourceArray, sourceArray.Length - 8, destinationArray, 0, destinationArray.Length);
                        destinationArray[0] = (byte)(destinationArray[0] & 15);
                        destinationArray[0] = (byte)(destinationArray[0] | 0x40);
                    }
                    else
                    {
                        destinationArray = sourceArray;
                        if (sourceArray.Length > length)
                        {
                            destinationArray = new byte[length];
                            Array.Copy(sourceArray, 0, destinationArray, 0, destinationArray.Length);
                        }
                    }
                }
                finally
                {
                    handle.Dispose();
                }
            }

            return(EncodeExtension(destinationArray));
        }