views:

137

answers:

6

I would like to embed some C# .Net code that does some simple Encryption/Decryption functions into a web page. This will be an internal web page so users will be implicitly trusted. Is there any way to do this? I will need to hit user's Windows-MY key store (via CAPI) to pull out the keys for decryption and hit an LDAP server to grab public keys for encryption.

+3  A: 

You can use Silverlight.

Note, however, that you can do encryption in Javascript as well:

SLaks
I would like to use keys that are already in the user's Windows-MY key store and from what ive read neither Siverlight nor Javascript can access them
Petey B
@Petey: Then you need to write a browser plugin.
SLaks
Thanks SLaks (is that supposed to be a play on Ex Lax?), where should I start looking for information on browser plugins?
Petey B
@Petey: Which browser(s)? Google is your friend. (No; it's my initial)
SLaks
@SLaks: Not after sleeping with my wife he's not. I found the info I need on browser plugins, thanks again.
Petey B
+1  A: 

Silverlight or maybe a c# to JavaScript compiler, like Script#.

qstarin
+4  A: 

Define what you mean by "into a web page"? Web pages are run by browsers, which usually only know Javascript (and Java).

You could do it as a Silverlight application.

James Curran
Silverlight does not have the cryptograpghic functionality i need. Unless there is way to hit the Windows-MY keystore that i havnt found?
Petey B
+1  A: 

Consider writing a new ASP.NET application where your encryption/decryption logic lies within the application. Perhaps create a new webforms application with a page dedicated to fielding those requests.

Consider writing that encryption logic in a separate .NET assembly, and then reference that assembly from your ASP.NET application.

It's not clear whether you wanted this as a service, or whether users would be expecting to enter text in a textbox, and having it perform the encryption as they visit.

p.campbell
This would work, but i need a way to grab the user's private key for decryption from their Windows-MY keystore. Everything else could be done server side.
Petey B
A: 

You could use AJAX and call the encryption function you've used over the network.

Robaticus
A: 

I ended up faking a COM object using C# then using JavaScript to call that COM object and was able to interact with the CAPI through the browser that way.

JavaScript:

<html>
<head>
<script language="javascript">
var keystore = new ActiveXObject("RBCrypto.KeyStore");

function getCertList()
{
   try {
     keystore.openKeyStore("MY", true, false);
     var size = keystore.getStoreSize();

     var list = document.getElementById('list');
     list.size = size;

     for(var i = 0; i < size; i++)
     {
        var fname = keystore.getFriendlyName(i, true);
        var opt = new Option(fname, fname);
        list.options.add(opt);
     }
   }
   catch(err)
   {
     alert(err.description);
   }
}
</script>
</head>
<body onload="getCertList()">
   <center>
    <h2>KeyStore Test</h2>
    <hr />
    <br />
    <select id="list"></select>
   </center>
</body>
</html>

C#:

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace RBCrypto
{
    public interface AXInterface
    {
        void openKeyStore(string storeName, bool currentUser, bool readOnly);
        int getStoreSize();
        string getFriendlyName(int index, bool subjectNameIfEmpty);
    }

    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class KeyStore :AXInterface
    {
        public void openKeyStore(string storeName, bool currentUser, bool readOnly)
        {
            if (keystoreInitialized)
                throw new Exception("Key Store must be closed before re-initialization");

            try
            {
                if (currentUser) //user wants to open store used by the current user
                    certificateStore = new X509Store(storeName, StoreLocation.CurrentUser);
                else             //user wants to open store used by local machine
                    certificateStore = new X509Store(storeName, StoreLocation.LocalMachine);

                if (readOnly)
                    certificateStore.Open(OpenFlags.ReadOnly);
                else
                    certificateStore.Open(OpenFlags.ReadWrite);

                allCertificates = certificateStore.Certificates;

                if (allCertificates == null)
                {
                    certificateStore.Close();
                    throw new NullReferenceException("Certificates could not be gathered");
                }

                keystoreInitialized = true;
            }
            catch (ArgumentException ae)
            {
                throw ae;
            }
            catch (SecurityException se)
            {
                throw se;
            }
            catch (CryptographicException ce)
            {
                throw ce;
            }
            catch (NullReferenceException ne)
            {
                throw ne;
            }
        }

        ....
   }
}

C# AssemblyInfo:

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]

In order for this to work the user has to isntall your .dll on their machine (Make sure you specify to register your .dll as vsdraCOM in your installer) and they have to add your site to their trusted sites.

Petey B