﻿// CAPICOM constants 
var CAPICOM_STORE_OPEN_READ_ONLY = 0;
var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
var CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY = 6;
var CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
var CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
var CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
var CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
var CAPICOM_ENCODE_BASE64 = 0;
var CAPICOM_E_CANCELLED = -2138568446;
var CERT_KEY_SPEC_PROP_ID = 6;

function IsCAPICOMInstalled() {
    if (typeof (oCAPICOM) == "object") {
        if ((oCAPICOM.object != null)) {
            // We found CAPICOM!
            return true;
        }
    }
}

function ShowCertificate() {
    var txtCertificate = document.getElementById("txtCertificate");
    // only do this if the user selected a certificate
    if (txtCertificate.hash != "") {
        try {
            // Set the Certificate we would like to sign with
            var Certificate = FindCertificateByHash(txtCertificate.hash);
            Certificate.Display();
        }
        catch (e) {
            if (e.number != CAPICOM_E_CANCELLED) {
                alert("При считывании сертификата произошла ошибка: " + e.description);
                return false;
            }
        }
    }
}

function FindCertificateByHash(szThumbprint) {
    // instantiate the CAPICOM objects
    var MyStore = new ActiveXObject("CAPICOM.Store");

    // open the current users personal certificate store
    try {
        MyStore.Open(CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY);
    }
    catch (e) {
        if (e.number != CAPICOM_E_CANCELLED) {
            alert("An error occurred while opening your personal certificate store, aborting");
            return false;
        }
    }

    // find all of the certificates that have the specified hash
    var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, szThumbprint);
    return FilteredCertificates.Item(1);

    // Clean Up
    MyStore = null;
    FilteredCertificates = null;
}

function FilterCertificates() {
    // instantiate the CAPICOM objects
    var MyStore = new ActiveXObject("CAPICOM.Store");
    var FilteredCertificates = new ActiveXObject("CAPICOM.Certificates");

    // open the current users personal certificate store
    try {
        MyStore.Open(CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY);
    }
    catch (e) {
        if (e.number != CAPICOM_E_CANCELLED) {
            alert("An error occurred while opening your personal certificate store, aborting");
            return false;
        }
    }

    // find all of the certificates that:
    //   * Are good for signing data
    //	* Have PrivateKeys associated with then - Note how this is being done :)
    //   * Are they time valid
    var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_KEY_USAGE, CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE).Find(CAPICOM_CERTIFICATE_FIND_TIME_VALID).Find(CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY, CERT_KEY_SPEC_PROP_ID);
    return FilteredCertificates;

    // Clean Up
    MyStore = null;
    FilteredCertificates = null;
}

function GetCertificateInBytes(hash) {
    var cert = FindCertificateByHash(hash);
    if (cert != null)
        return cert.Export(1);
    else
        return null;
}

function SignData(data, hash) {
    // instantiate the CAPICOM objects
    var SignedData = new ActiveXObject("CAPICOM.SignedData");
    var Signer = new ActiveXObject("CAPICOM.Signer");
    var TimeAttribute = new ActiveXObject("CAPICOM.Attribute");

    // only do this if the user selected a certificate
    if (data != null && hash != null) {
        try {
            // Set the Certificate we would like to sign with
            Signer.Certificate = FindCertificateByHash(hash);
            SignedData.Content = data;

            // Set the time in which we are applying the signature
            var Today = new Date();
            TimeAttribute.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
            TimeAttribute.Value = Today.getVarDate();
            Today = null;
            Signer.AuthenticatedAttributes.Add(TimeAttribute);

            // Do the Sign operation
            var signingData = SignedData.Sign(Signer, false, CAPICOM_ENCODE_BASE64);
            return signingData;

        }
        catch (e) {
            if (e.number != CAPICOM_E_CANCELLED) {
                alert("An error occurred when attempting to sign the content, the errot was: " + e.description);
                return false;
            }
        }
    }
    else {
        alert("No Certificate has been selected.");
    }
}
