CryptoAPI

Commands related to cryptographical operations

SYNOPSIS

package require twapi_crypto
3des iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
aes_128 iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
aes_192 iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
aes_256 iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
asn1_encode_string OID
asn1_decode_string OID
capi_algid ALGID
capi_decrypt_bytes BINDATA HKEY ?-hhash HHASH? ?-oaep BOOLEAN? ?-nopadcheck BOOL?
capi_decrypt_string BINDATA HKEY ?-hhash HHASH? ?-oaep BOOLEAN? ?-nopadcheck BOOL?
capi_encrypt_bytes BINDATA HKEY ?-hhash HHASH? ?-pad PADTYPE? ?-final BOOL?
capi_encrypt_string STRING HKEY ?-hhash HHASH? ?-pad PADTYPE?
capi_hash_bytes HHASH BINVALUE
capi_hash_create HCRYPT ALGID ?HKEY?
capi_hash_dup HHASH
capi_hash_free HHASH
capi_hash_session_key HHASH HKEY
capi_hash_sign HHASH KEYSPEC ?options?
capi_hash_string HHASH STRING ?ENC?
capi_hash_value HHASH
capi_hash_verify HHASH SIG HKEY ?options?
capi_key_algid HKEY ?ALGID? ?options?
capi_key_blocklen HKEY
capi_key_certificate HKEY
capi_key_dss_p HKEY
capi_key_dss_q HKEY
capi_key_dss_g HKEY
capi_key_effective_keylen HKEY
capi_key_export HKEY BLOBTYPE ?-wrapper HWRAPPER?
capi_key_free HKEY
capi_key_iv HKEY ?IV?
capi_key_keylen HKEY
capi_key_mode HKEY ?MODE?
capi_key_mode_bits HKEY ?MODEBITS?
capi_key_padding HKEY ?PADMODE?
capi_key_permissions HKEY ?PERMS?
capi_key_salt HKEY ?SALT?
capi_keyblob_algid KEYBLOB
capi_keyblob_blob KEYBLOB
capi_keyblob_concealed ALGID CONCEALEDKEY
capi_keyblob_create VER ALGID BLOBTYPE KEYBYTES
capi_keyblob_plaintext ALGID PLAINTEXTKEY
capi_keyblob_type KEYBLOB
capi_keyblob_version KEYBLOB
capi_parse BINSTRING ?options?
capi_parse_file FILEPATH ?options?
crypt_acquire ?options?
crypt_algorithms HCRYPT
crypt_csp HCRYPT
crypt_csp_type HCRYPT
crypt_derive_key HCRYPT ALGID PASSPHRASE ?options?
crypt_public_key_export HCRYPT KEYSPEC ?-encoding native|pem|der?
crypt_public_key_import HCRYPT KEY ?-encoding native|pem|der?
crypt_keyx_keysize_increment HCRYPT
crypt_free HCRYPT
crypt_generate_key HCRYPT ALGORITHM ?options?
crypt_get_security_descriptor HCRYPT
crypt_implementation_type HCRYPT
crypt_import_key HCRYPT KEYBLOB ?options?
crypt_key_container_delete KEYCONTAINER ?options?
crypt_key_container_name HCRYPT
crypt_key_container_names HCRYPT
crypt_key_free HCRYPTKEY
crypt_key_specifiers HCRYPT
crypt_keypair HCRYPT keytype
crypt_keyset_type HCRYPT
crypt_set_security_descriptor HCRYPT ?SECD?
crypt_session_key_size HCRYPT
crypt_sig_keysize_increment HCRYPT
crypt_symmetric_key_size HCRYPT
csp_types
csps
des iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
hmac DATA KEY ?PRF? ?CHARSET?
md5 DATA ?CHARSET?
oid OID_OR_NAME
oidname OID_OR_NAME
oids ?PATTERN?
pbkdf2 PASSPHRASE KEYSIZE PRF SALT NITERATIONS
pkcs7_decrypt PKCS7MSG STORES ?options?
pkcs7_encrypt BINDATA RECIPIENTS ENCALGOID ?options?
pkcs7_sign BINDATA HCERT HASHALGOID ?options?
pkcs7_verify PKCS7MSG ?options?
protect_data BINDATA ?options?
sha1 DATA ?CHARSET?
sha256 DATA ?CHARSET?
sha384 DATA ?CHARSET?
sha512 DATA ?CHARSET?
unprotect_data BINDATA ?options?

DESCRIPTION

This package provides procedures related to cryptographic services provided by the Windows platforms.

Overview

This page describes the base commands related to the Win32 CryptoAPI (CAPI) which includes functions related to encryption, decryption, signatures and ancillary services.

Other functions provided by CAPI are documented in the Certificates and SSPI pages.

This documentation expects the reader is familiar with the use of cryptography. An overview of the concepts in CAPI is provided but the API itself is fairly complex and a series of blog posts on the use of these commands may prove useful. The reader may also wish to refer to the Windows SDK CryptoAPI documentation.

Cryptographic Service Providers

A Cryptographic Service Providers (CSP) on Windows is a software module that implements a set of cryptographical functions such as encryption or key storage. There may be multiple such modules on a system, each implementing one of more cryptographic algorithms for one or more cryptographic functions. Applications implement cryptographic operations by calling a standard interface defined by Windows and implemented by the CSPs.

Some CSP's come with the Windows operating system while others are implemented by third parties. The feature set implemented by each CSP is different and can depend on factors such as the operating system version, and because of US export restrictions, the country. Based on the supported features, CSP's have an associated CSP type. For example, a CSP of type PROV_RSA_FULL supports digital signatures and encryption using the RSA public key algorithm. On the other hand, a CSP of type PROV_DSS uses the DSA algorithm and only supports hashes and signatures. When creating a Cryptographic contexts, an application needs to specify a CSP type that supports the desired operations. The following types are recognized: prov_rsa_full, prov_rsa_sig, prov_dss, prov_fortezza, prov_ms_exchange, prov_ssl, prov_rsa_schannel, prov_dss_dh, prov_ec_ecdsa_sig, prov_ec_ecnra_sig, prov_ec_ecdsa_full, prov_ec_ecnra_full, prov_dh_schannel, prov_spyrus_lynks, prov_rng, prov_intel_sec, prov_replace_owf, prov_rsa_aes. Refer to the Windows SDK for details about the features provided by each. For most applications, the default prov_rsa_full is sufficient.

Two standard providers shipped as part of Windows are Microsoft Base Cryptographic Provider and the Microsoft Strong Cryptographic Provider. On most systems, the latter is the default when no specific CSP is selected and is sufficient in most cases unless some special functionality like hardware based cryptography is desired.

The commands csps and csp_types return the list of CSP's and CSP types on the system.

Keys and key containers

The keys used for cryptographic operations are stored in key containers within a CSP's control. The keys are not generally exposed directly to an application but rather the CSP carries out the operations using the keys on the application's behalf.

A CSP may be associated with multiple key containers, each identified by a name. The specific key container and the keys within that container that are used for an operation depends on the Cryptographic contexts is bound at the time the context is created via the crypt_acquire command. This command also allows creation of new key containers within a CSP if they do not exist.

Depending on the options specified and the account under which they are created, key containers are created with restricted access. The exact access depends on the account group membership (e.g. whether an adminitrator or not) and operating system version. Applications can set specific access rules by setting a DACL on the container using crypt_set_security_descriptor.

To delete key containers, use the crypt_key_container_delete command.

A key container may be created as a user key set or a computer key set. These are distinguished based on where they are stored and who has access to them. Refer to the Windows SDK CryptoAPI documentation for details. It is possible to change the default access permissions for a key container. The crypt_get_security_descriptor and crypt_set_security_descriptor commands can be used retrieve and change the security descriptor for a key container.

Depending on the CSP chosen, key containers may be empty when created. The command crypt_generate_key adds randomly generated keys to the container. On the other hand, the command crypt_derive_key will add a key derived from a passphrase. In both cases, the algorithm with which the key will be used and the purpose (encryption, signing etc.) can be specified so the appropriate type of key is generated. The container may contain multiple keys and appropriate key must be chosen when cryptographic operations are invoked. A raw key of a specified number of bits derived from a passphrase can be generated using the pbkdf2 command.

The properties for a key may be retrieved or set using the commands in the table below. Note that a key is always associated with a specific cryptographic algorithm.

capi_key_algid Numeric id for the associated algorithm.
capi_key_blocklen Block length for the encryption algorithm.
capi_key_certificate Associated certificate.
capi_key_dss_p Modulus prime number P if the key is a DSS key.
capi_key_dss_q Modulus prime number Q if the key is a DSS key.
capi_key_dss_g Generator G if the key is a DSS key.
capi_key_effective_keylen Effective key length of the key.
capi_key_iv Initialization vector.
capi_key_keylen Actual key length.
capi_key_mode Cipher mode, such as CBC, ECB etc.
capi_key_mode_bits Number of feedback bits for OFB and CFB modes.
capi_key_padding Padding method.
capi_key_permissions Operations that are permitted for the key.
capi_key_salt Salt value.

Keys received from other applications can be imported into a cryptographic context with the crypt_import_key command. Conversely, a key that needs to be communicated to another application can be exported with the capi_key_export command. Public keys can be imported and exported in a portable format with crypt_public_key_import and crypt_public_key_export respectively. When importing and exporting keys, the keys are passed around as _key blobs_. The type and format of a key blob is specified by one of the values in the table below.

concealed The returned key blob is in the format returned by the TWAPI conceal command.
opaque The returned key blob is in a format is a vendor-specific format that can only be used with the same CSP.
plaintext The returned key blob is a PLAINTEXTKEYBLOB blob.
privatekey The returned key blob is a PRIVATEKEYBLOB containing the public and private keys. If the -wrapper option is specified, it must be the handle to a symmetric key in which case the blob is encrypted with that key.
publickey The returned key blob is a PUBLICKEYBLOB containing the public key of a key pair.
rfc3217 The returned key blob is in the format specified by RFC3217. Both HKEY and the wrapping key specified by the -wrapper option must be symmetric keys.
simple The returned key blob is a SIMPLEBLOB where the symmetric key specified by HKEY is wrapped by a key exchange key specified with the -wrapper option.

The details of the format of each of the above, except concealed which is TWAPI-specific, are described in the SDK documentation. In addition to capi_key_export, key blobs can be explicitly constructed with the capi_keyblob_create command. The commands capi_keyblob_plaintext and capi_keyblob_concealed are shortcuts for making key blobs in plaintext and concealed formats. Individual fields of a key blob can be retrieved through the commands capi_keyblob_version, capi_keyblob_type, capi_keyblob_algid and capi_keyblob_blob.

Cryptographic contexts

In order to perform cryptographic operations, an application must choose a CSP, the algorithms to use and their parameters including keys. The command crypt_acquire takes these are parameters and returns a handle to a cryptographic context that binds the desired combination together. This handle can then be used in further cryptographic operation.

Once a context is created, the various parameters associated with it can be retrieved.

crypt_algorithms Returns the list of algorithms implemented in the context.
crypt_csp Returns the name of the owning CSP.
crypt_csp_type Returns the type of the CSP.
crypt_csp_version Returns the version of the owning CSP.
crypt_keyx_keysize_increment Returns the valid increments for the key exchange key sizes.
crypt_implementation_type Returns the implementation type (hardware, software etc.) of the context.
crypt_key_container_name Returns the name of key container currently associated with the context.
crypt_key_container_names Returns the names of the other key containers owned by the CSP.
crypt_key_specifiers Returns the key specifiers supported by the context.
crypt_keypair Returns a handle to one of the key pairs in the container.
crypt_keyset_type Returns whether the key set in the container is per-user or per-machine.
crypt_session_key_size Returns the size of the session key.
crypt_sig_keysize_increment Returns the valid increments for the signature key sizes.
crypt_symmetric_key_size Returns the size of the symmetric key.

When no longer needed, cryptographic contexts must be freed with the crypt_free command.

Algorithm identifiers

CAPI internally uses numeric identifiers for cryptographic algorithms. Algorithms can also be identified by ASN.1 OID's. In addition, TWAPI uses allows use of mnemonics to identify algorithms as per the table below. The command capi_algid can be used to map any of the above forms to the numeric algorithm identifier. Most commands that need algorithm identifiers to be supplied will also accept any of the forms.

3des Triple DES
3des_112 Triple DES with 112-bit effective key length
aes Advanced Encryption Standard (AES)
aes_128 128-bit AES
aes_192 192-bit AES
aes_256 256-bit AES
at_keyexchange Maps to the key exchange algorithm for the CSP in use
at_signature Maps to the signature algorithm for the CSP in use
des Data Encryption Standard (DES)
desx DES-X
dh_ephem Diffie-Hellman ephemeral key exchange
dh_sf Diffie-Hellman store and forward key exchange
dss_sign DSA public key signature
ecdh Elliptic curve Diffie-Hellman key exchange
ecdsa Elliptic curve digital signature
hash_replace_owf One way function hashing
hughes_md5 Hughes MD5
hmac HMAC keyed hash
mac MAC keyed hash
md2 MD2 hashing
md4 MD4 hashing
md5 MD5 hashing
no_sign No signature algorithm
rc2 RC2 block encryption
rc4 RC4 block encryption
rc5 RC5 block encryption
rsa_keyx RSA public key exchange
rsa_sign RSA public key signature
sha SHA hashing
sha1 SHA-1 hashing
sha_256 256-bit SHA-2
sha_384 384-bit SHA-2
sha_512 512-bit SHA-2

Note that not all algorithms are supported on all platforms.

ASN.1 object identifiers

An ASN.1 object identifier (OID) is a dotted decimal string such as 1.2.3.4 that represents a ASN.1 class or attribute. Many CAPI command arguments use OID's to represent types and values such as algorithm identifiers. OID's can be passed in their dotted decimal form, or, for some commonly used ones, a mnemonic identifer. The list of mnemonic identifiers can be obtained through the oids command. Mapping to and from a specific mnemonic can be done through the oidname and oid commands. The utility commands asn1_encode_string and asn1_decode_string can be used to convert OID's to and from binary formats.

Hashes and MACs

CAPI supports functionality related to generating cryptographic hashes and message authentication codes (MAC). The related TWAPI commands are shown below.

capi_hash_bytes Incrementally hashes a binary string.
capi_hash_create Creates a hash context.
capi_hash_dup Duplicates a hash context.
capi_hash_free Frees a hash context.
capi_hash_session_key Incrementally hashes the secret session key.
capi_hash_string Incrementally hashes a string.
capi_hash_value Returns the hashed value.
hmac Calculates the HMAC hash using a specified PRF.
md5 Calculates the MD5 hash.
sha1 Calculates the SHA1 hash.
sha256 Calculates the SHA-256 hash.
sha384 Calculates the SHA-384 hash.
sha512 Calculates the SHA-512 hash.

Cryptographic operations

The package implements the following commands related to encryption and signatures.

3des Encrypts, decrypts or generates an IV (3DES algorithm)
aes_128 Encrypts, decrypts or generates an IV (AES 128-bits algorithm)
aes_192 Encrypts, decrypts or generates an IV (AES 192-bits algorithm)
aes_256 Encrypts, decrypts or generates an IV (AES 256-bits algorithm)
capi_encrypt_bytes Encrypts a binary string with optional hashing.
capi_encrypt_string Encrypts a string with optional hashing.
capi_decrypt_bytes Decrypts a binary string with optional hashing.
capi_decrypt_string Decrypts a string with optional hashing.
capi_hash_sign Signs a hash using a private key.
capi_hash_verify Verifies the signature of a hash.
des Encrypts, decrypts or generates an IV (DES algorithm)

Data protection

Windows provides facilities to encrypt and protect data based on the user credentials such that it can only be retrieved on the same system with the same credentials. The protect_data and unprotect_data commands provide access to this facility. The TWAPI base module also provides the conceal/reveal commands to protect data within the current process. See the base module reference for details.

Parsing cryptographic objects

Cryptographic objects such as certificates, stores signed messages etc. may be of different formats and encodings. The command capi_parse analyses and parses a binary string containing a serialized cryptographic object, possibly of an unknown type. The command capi_parse_file is similar except it reads the serialized data directly from a file.

Commands

3des iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
Implements cryptographic operations using the 3DES algorithm.

The iv subcommand returns a randomly generated initialization vector suitable for 3DES. No additional arguments are allowed.

For encrypt and decrypt commands, BYTES is the binary string to be encrypted or the ciphertext to be decrypted. CONCEALEDKEY is the 3DES key in concealed form. The returned value is the encrypted ciphertext or decrypted plaintext respectively. The following options affect encryption or decryption operation.
-iv IV A binary string to be used as the initialization vector of the operation.
-mode MODE The cipher mode to be used for the operation. See capi_key_mode.
aes_128 iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
aes_192 iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
aes_256 iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
Implements cryptographic operations using the AES algorithm for 128, 192 and 256 keys respectively.

The iv subcommand returns a randomly generated initialization vector of a suitable length for the algorithm. No additional arguments are allowed.

For encrypt and decrypt commands, BYTES is the binary string to be encrypted or the ciphertext to be decrypted. CONCEALEDKEY is the key in concealed form. The returned value is the encrypted ciphertext or decrypted plaintext respectively. The following options affect encryption or decryption operation.
-iv IV A binary string to be used as the initialization vector of the operation.
-mode MODE The cipher mode to be used for the operation. See capi_key_mode.
asn1_encode_string OID
Returns the specified OID in ASN.1 binary encoded format.
asn1_decode_string OID
Returns the specified ASN.1 binary OID in string format.
capi_algid ALGID
Returns the numeric decimal algorithm identifier for the algorithm ALGID which may be in any of the forms described in Algorithm identifiers. If ALGID is non-numeric, an error is raised if it cannot be mapped to a numeric id.
capi_decrypt_bytes BINDATA HKEY ?-hhash HHASH? ?-oaep BOOLEAN? ?-nopadcheck BOOL?
When the -final option is not specified, the command decrypts the passed binary string BINDATA and returns the plaintext result. If the option -hhash is specified HHASH should be the handle of a hash context. This will be updated with the decrypted data. The option -pad can only be used with RSA. If unspecified or oaep, OAEP padding is assumed. A value of pkcs1 implies PKCS #1 format padding. The value nopadcheck specifies no check for padding should be done.

The -final option may be used to decrypt a message in streaming mode where the message is decrypted in parts or segments. In this case, all except the last segment of the message should be passed to the command with the -final option specified to be a boolean false value. The return value is the plaintext corresponding to the passed segment. For the last segment, the caller must either leave out the -final option or specify it as a boolean true value.
capi_decrypt_string BINDATA HKEY ?-hhash HHASH? ?-oaep BOOLEAN? ?-nopadcheck BOOL?
Decrypts the passed binary string BINDATA converts it from UTF-8 encoding and returns the plaintext result. Note that it is assumed that the original encrypted text was UTF-8 encoded. If the option -hhash is specified HHASH should be the handle of a hash context. This will be updated with the decrypted data. The option -pad can only be used with RSA. If unspecified or oaep, OAEP padding is assumed. A value of pkcs1 implies PKCS #1 format padding. The value nopadcheck specifies no check for padding should be done.
capi_encrypt_bytes BINDATA HKEY ?-hhash HHASH? ?-pad PADTYPE? ?-final BOOL?
When the -final option is not specified, the command encrypts the passed binary string BINDATA and returns the result. HKEY should be the handle of the key to be used for the operation. If the option -hhash is specified HHASH should be the handle of a hash context. This will be updated with BINDATA. The option -pad can only be used with RSA. If unspecified or oaep, OAEP padding is used. The only other valid value is pkcs1 for PKCS #1 format padding.

The -final option may be used to encrypt a message in streaming mode where the message is encrypted in parts or segments. In this case, all except the last segment of the message should be passed to the command with the -final option specified to be a boolean false value. The return value is the ciphertext corresponding to the passed segment. For the last segment, the caller must either leave out the -final option or specify it as a boolean true value.

Note that the maximum length of data that can be encrypted depends on the algorithm and parameters like key size.
capi_encrypt_string STRING HKEY ?-hhash HHASH? ?-pad PADTYPE?
Encrypts the passed string STRING after encoding it in UTF-8 and returns the result. If the option -hhash is specified HHASH should be the handle of a hash context. This will be updated with BINDATA. The option -pad can only be used with RSA. If unspecified or oaep, OAEP padding is used. The only other valid value is pkcs1 for PKCS #1 format padding.
capi_hash_bytes HHASH BINVALUE
Updates the hash context specified by HHASH with the result of hashing the binary string BINVALUE.
capi_hash_create HCRYPT ALGID ?HKEY?
Creates a hash context and returns a handle to it. HCRYPT is a handle to a cryptographic context as returned by crypt_acquire. ALGID is an algorithm identifier as described in Algorithm identifiers. If the algorithm is a key-based hash, HKEY must be a handle to the key. Otherwise it should be unspecified or NULL.

The returned hash context should be freed when no longer needed by calling capi_hash_free.
capi_hash_dup HHASH
Creates a new hash context that is the duplicate of an existing hash context and returns a handle to it.

The returned hash context should be freed when no longer needed by calling capi_hash_free.
capi_hash_free HHASH
Frees a hash context previously created through capi_hash_create or capi_hash_dup.
capi_hash_session_key HHASH HKEY
Updates the hash context specified by HHASH with result of hashing the session key referenced by the handle HKEY.
capi_hash_sign HHASH KEYSPEC ?options?
Returns a binary string that is the signature generated by signing the specified hash context. HHASH specifies the hash context. KEYSPEC should be either keyexchange or signature indicating which of the private keys in the cryptographic context associated with HHASH should be used to sign the hash.

Once this command is called, commands that add data to the hash, such as capi_hash_string cannot be invoked.

The following options may be specified with the command.
-nohashoid BOOLEAN If true, the hash object OID is not placed in the RSA public key encryption. If false (default), the hash OID in the default signature is as specified in the definition of DigestInfo in PKCS #1.
Note the supported options depend on both the CSP and the hashing algorithm.
capi_hash_string HHASH STRING ?ENC?
Converts STRING into a binary string using the specified encoding ENC (defaults to utf-8) and updates the hash context specified by HHASH with the result.
capi_hash_value HHASH
Returns the hashed value from the specified hash context as a binary string. The HHASH handle should not be used with capi_hash_bytes or capi_hash_string once this command is called.
capi_hash_verify HHASH SIG HKEY ?options?
Verifies that the signature computed on a hash context HHASH with public key HKEY is the same as SIG. Returns 1 if the signature matches, else 0.

Once this command is called, commands that add data to the hash, such as capi_hash_string cannot be invoked.

The following options may be specified with the command.
-nohashoid BOOLEAN If true, the hash object OID is not expected to the present and is not checked. If false (default), the hash OID in the default signature is expected to be as specified in the definition of DigestInfo in PKCS #1.
Note the supported options depend on both the CSP and the hashing algorithm.
capi_key_algid HKEY ?ALGID? ?options?
If no optional arguments are specified, returns the numeric id for the algorithm associated with the key. Otherwise sets it to ALGID. Additional options such as key size may be specified. See crypt_generate_key for valid options.
capi_key_blocklen HKEY
If HKEY references a session key, returns the block length of the key cipher with a value of 0 indicating it is a stream cipher. If HKEY references a public/private key pair, the return value is the encryption granularity. In both cases, the return value is in number of bits.
capi_key_certificate HKEY
Returns the certificate associated with the key, if any, as a DER-encoded binary string.
capi_key_dss_p HKEY
Returns the modulus prime number P if HKEY is a DSS key handle. The return value is a binary string in little-endian form.
capi_key_dss_q HKEY
Returns the modulus prime number Q if HKEY is a handle to a DSS key. The return value is a binary string in little-endian form.
capi_key_dss_g HKEY
Returns the generator G if HKEY is a DSS key handle. The return value is a binary string in little-endian form.
capi_key_effective_keylen HKEY
Returns the effective key length of the key.
capi_key_export HKEY BLOBTYPE ?-wrapper HWRAPPER?
Exports the key referenced by the specified handle HKEY. The return value is a list containing 5 elements. The first element is a numeric value corresponding to the blob type. The second is the version number of the blob format. The third is a reserved value that should be ignored by applications. The fourth is the numeric algorithm identifier. Finally, the fifth value is a binary key blob whose format and structure depends on BLOBTYPE. See Keys and key containers for more on key blobs.
capi_key_free HKEY
Frees a handle to a cryptographic key.
capi_key_iv HKEY ?IV?
If IV is not specified, the command returns the current initialization vector as a binary string. Otherwise IV is set as the initialization vector. HKEY must be a handle to a block cipher session key.
capi_key_keylen HKEY
Returns the actual key length in bits. This includes any parity and zeroed bits. HKEY can be a handle to any type of key.
capi_key_mode HKEY ?MODE?
If MODE is not specified, returns the cipher mode used with the key. The return value is one of cbc, ecb, ofb, cfb and cts. If MODE is specified it must be one of the aforementioned values and the cipher mode is set accordingly. Note that not all CSP's support all modes for a given algorithm. In particular, the Microsoft provided CSP's only support the `ecb`, `cbc` and `cfb` modes. HKEY must be a handle to a block cipher session key.
capi_key_mode_bits HKEY ?MODEBITS?
If MODEBITS is not specified, returns the number of feedback bits for OFB and CFB modes. Otherwise sets the corresponding parameter to MODEBITS. HKEY must be a handle to a block cipher session key.
capi_key_padding HKEY ?PADMODE?
If PADMODE is not specified, returns the padding method used with the key. Otherwise sets the padding method to PADMODE. HKEY must be a handle to a block cipher session key.

The possible values for PADMODE are
pkcs5 Padding as specified by PKCS #5
random Random bytes of padding.
zeroes Padding filled with zeroes.
Note that not all CSP's and algoritms every padding method. As of Windows 10, Microsoft CSP's only support PKCS5.
capi_key_permissions HKEY ?PERMS?
If PERMS is not specified, returns the list of operations that are permitted for the key. The permissions are returned and specified as a list containing zero or more elements from the following:
archive Key can be exported only on the initial key creation.
decrypt Usable for decryption.
encrypt Usable for encryption.
export Key can be exported.
export_key Key can be used to encrypt other exported keys.
import_key Key can be used decrypt keys being imported.
mac Key can be used with message authentication codes.
read Allow key values to be read.
write Allow key values to be written.
capi_key_salt HKEY ?SALT?
If SALT is not specified, returns a binary string of bytes that are used as the salt value in little endian form. If SALT is specified, it is used as the salt value for the key.
capi_keyblob_algid KEYBLOB
Returns the algorithm associated with a key blob.
capi_keyblob_blob KEYBLOB
Returns the raw key structures within a key blob.
capi_keyblob_concealed ALGID CONCEALEDKEY
Constructs and returns a key blob that is of type concealed. See Keys and key containers about more on key blobs.
capi_keyblob_create VER ALGID BLOBTYPE KEYBYTES
Constructs and returns a key blob that can be passed to a command such as crypt_import_key. See Keys and key containers about more on key blobs.
capi_keyblob_plaintext ALGID PLAINTEXTKEY
Constructs and returns a key blob that is of type plaintext. See Keys and key containers about more on key blobs.
capi_keyblob_type KEYBLOB
Returns the type of a key blob.
capi_keyblob_version KEYBLOB
Returns the version of a key blob.
capi_parse BINSTRING ?options?
Parses a serialized form of a cryptographic object, stored as a binary string BINSTRING, which may be in one of several different formats and encodings and whose type may be a certificate, certificate store, a CTL or a CRL.

The following options may be specified with the command.
-contenttype CONTENTTYPE Specifies the type of cryptographic object expected. See below for the possible values. If unspecified, or if CONTENTTYPE is any, the command will attempt to guess the type of content. Otherwise, it will raise an error if the content is not of the specified type.
-format FORMAT Specifies the format of the data. FORMAT must be on of the values binary, base64, asn1hex or any. If the option is unspecified or any, the command will attempt to guess the format. Otherwise, it will raise an error if the data format is not that specified.
-typesonly If specified as true, the actual content is not included in the returned dictionary. Only the information related to format and object type is returned. Defaults to false.
The return value is a dictionary with at least the keys shown in the table below.
formattype The associated value is one of binary, base64 or asn1hex depending on the format of the data.
contenttype The associated value indicates the type of data that was parsed. The parsed data is stored in additional keys in the returned dictionary that depend on this type. This is discussed below.
The possible values in the contenttype key of the returned dictionary and the semantics of each are shown in the table below. Note that the return dictionary also contains additional keys that depend on this value.
cert The data is a certificate. The returned dictionary has two additional keys store and certificate that contain handles to a certificate store and certificate context. These must be released after use with cert_store_release and cert_release respectively.
certpair TBD.
crl The data is a CRL. The returned dictionary has two additional keys store and crl that contain handles to a certificate store and CRL context. These must be released after use with cert_store_release and crl_release respectively.
ctl The data is a CTL. The returned dictionary has two additional keys store and ctl that contain handles to a certificate store and CTL context. These must be released after use with cert_store_release and ctl_release respectively.
pfx The data is a PFX (PKCS#12) packet. No additional keys are returned in the dictionary. The application can use the cert_temporary_store command to import the PFX packet.
pkcs10 The data is a PKCS#10 message.
pkcs7signed The data is a PKCS#7 signed message. The returned dictionary has two additional keys store and message that contain handles to a certificate store and signed message. These must be released after use with cert_store_release and capi_msg_release respectively.
pkcs7signedembed The data is an embedded PKCS#7 signed message. The returned dictionary has two additional keys store and message that contain handles to a certificate store and signed message. These must be released after use with cert_store_release and capi_msg_release respectively.
pkcs7unsigned The data is a PKCS#7 unsigned message. The returned dictionary has an additional key, message that contains a handle to a signed message. This must be released with capi_msg_release.
rsapublickey The data is RSA public key encoded as defined by the ASN.1 RSAPublicKey definition in RFC3279. The returned dictionary has the key rsapublickey containing the key in an internal form.
serializedcert The data is a serialized certificate. The returned dictionary has two additional keys store and certificate that contain handles to a certificate store and certificate context. These must be released after use with cert_store_release and cert_release respectively.
serializedcrl The data is a serialized CRL. The returned dictionary has two additional keys store and crl that contain handles to a certificate store and CRL context. These must be released after use with cert_store_release and crl_release respectively.
serializedctl The data is a serialized CTL. The returned dictionary has two additional keys store and ctl that contain handles to a certificate store and CTL context. These must be released after use with cert_store_release and ctl_release respectively.
serializedstore The data is a serialized certificate store. The returned dictionary has an additional key store that contains a handle to a certificate store created from the data. This must be released after use with cert_store_release.
subjectpublickeyinfo The data is as per ASN.1 SubjectPublicKeyInfo definition in RFC3279. The returned dictionary has the key subjectpublickeyinfo containing the key in an internal form that can be passed to crypt_public_key_import.
capi_parse_file FILEPATH ?options?
Parses a cryptographic object in the same manner as capi_parse except that the object is read from the file FILEPATH. See the documentation of capi_parse for details.
crypt_acquire ?options?
Returns a handle to a cryptographic context for a key container in a CSP.

The handle must be freed when no longer required by calling crypt_free.
-create BOOLEAN If specified as true, the key container is created if it does not exist. If false (default) an error is generated if the key container does not exist.
-csp CSP Specifies the name of the CSP to be used. If unspecified, the default Microsoft CSP for the system is used.
-csptype CSPTYPE Indicates the type of CSP. Defaults to prov_rsa_full. See Cryptographic Service Providers for all possible types.
-keycontainer KEYCONTAINER Specifies the name of the key container. If unspecified or an empty string, the default container for the CSP is used.
-keysettype KEYSETTYPE KEYSETTYPE must be user (default) or machine. Normally the key container is stored in the user's profile. If KEYSETTYPE is machine, the key container is treated as a computer container. This is needed when an application must access the keys from a process where the user profile is not loaded.
-silent BOOLEAN Normally, the CSP may prompt the user for any information that may be required to create the context. If this option is specified as true, the user is never prompted. Instead the command will raise an error if a user prompt was required.
-verifycontext BOOLEAN If specified as true, the context is intended for use for operations that are using ephemeral keys or which do not need access to private keys. Such operations include hashing, encrypting and signature verification. Operations involving decryption and signing require private keys and should set this option to false. The default for this option depends on whether a named key container is specified or not. If -keycontainer is not specified or is specified as an empty string denoting the default key container, this option defaults to true. Otherwise it defaults to false. Note that some CSP's (including Microsoft's) raise an error if the option is set to true for named containers. See the Microsoft knowledgebase article for more details.
Compatibility note In versions prior to 4.2, the key container was passed as the first argument, and not via the -keycontainer option. Although that will still work, it is deprecated and may raise an error in future releases.
crypt_algorithms HCRYPT
Returns the list of algorithms implemented in the specified cryptographic context. Each element of the list is a dictionary with keys shown in the table below.
algid The numeric algorithm identifier.
defkeylen The default length of a key.
description Description of the algorithm.
minkeylen Minimum length of a key.
maxkeylen Maximum length of a key.
name Name of the algorithm.
protocols Cryptographic protocols supported by the algorithm. This is a list containing zero or more elements from amongst ipsec, pct1, signing, ssl2, ssl3 and tls1.
Applications must ignore any additional keys in the table.
crypt_csp HCRYPT
Returns the name of the CSP owning the cryptographic context HCRYPT.
crypt_csp_type HCRYPT
Returns the type of the CSP owning the cryptographic context HCRYPT.
crypt_derive_key HCRYPT ALGID PASSPHRASE ?options?
Generates a cryptographic key based on a pass phrase and returns a handle to it which must be freed using capi_key_free. HCRYPT is the handle to the cryptographic context in which the key is to be created and ALGID should specify the algorithm identifier for the cryptographic algorithm with which the key will be used. PASSPHRASE is the pass phrase from which the key will be derived. This must be in the form returned by one of the TWAPI password or credential input commands so as to avoid inadvertent leakage. If the pass phrase comes from some other source, you can use the conceal command to convert to this form although this is not recommended as the original plain text pass phrase is then exposed at the script level and may show up on any error stacks etc. The command supports the following options:
-exportable BOOLEAN If true (default), the key can be exported later with capi_key_export. If false, the derived key can be used in cryptographic operations with the containing CSP but cannot be exported.
-iterations NUMITERS Number of iterations to execute if -method option is specified as pbkdf2. Ignored otherwise. Default is 100000.
-method KEYDERIVATIONMETHOD Specifies the method by which the key is derived from the pass phrase. See description below for details.
-prf ALGID Specifies the pseudo-random function (PRF) to use in the key derivation. If specified, ALGID must be sha1 (default) or sha_256. Ignored if -method is not pbkdf2.
-salt BINSTRING Specifies a binary string to use as the salt value if -method option is specified as pbkdf2. Ignored otherwise.
-size KEYSIZE Specifies the desired number of bits in the derived key. If unspecified or 0, the derived key size is based on the specified algorithm.
The method by which the passphrase is transformed into a key is controlled by the -method option. If the value KEYDERIVATIONMETHOD is pbkdf2 (default), the command pbkdf2 is used for generating the key passing it the values specified for -iterations, -salt and -size.

Otherwise, the key is derived based on the method described in the Windows SDK documentation. KEYDERIVATIONMETHOD must be a algorithm identifier that refers to a hash. The key is derived by hashing the UTF-8 encoding of the passphrase and passing the hash value to the CryptDeriveKey Win32 API. Refer to the SDK documentation for details regarding how the function derives keys.
crypt_public_key_export HCRYPT KEYSPEC ?-encoding native|pem|der?
Returns the public key of a key pair in a specified encoding. KEYSPEC must be either keyexchange or signature and specifies a key pair in the cryptographic context indicated by HCRYPT. The -encoding option controls the encoding of the returned public key as shown in the following table.
der DER encoded ASN.1 type SubjectPublicKeyInfo.
pem PEM encoded ASN.1 type SubjectPublicKeyInfo.
native Internal Tcl string format.
crypt_public_key_import HCRYPT KEY ?-encoding native|pem|der?
Imports the public key KEY into the cryptographic context specified by HCRYPT and returns a handle to it. The option -encoding specifies the encoding of KEY as described for the crypt_public_key_export command. If the option is not specified or is specified as an empty string, the command will attempt to guess the encoding.
crypt_keyx_keysize_increment HCRYPT
Returns the number of bits by which the key exchange key size can be incremented. The crypt_algorithms command returns the minimum and maximum key lengths for each algorithm in the context. This command returns the valid increments between the minimum and maximum values for the key exchange algorithm for the context.
crypt_free HCRYPT
Frees a cryptographic context returned by crypt_acquire.
crypt_generate_key HCRYPT ALGORITHM ?options?
Generates a new key or public/private key pair in the cryptographic context HCRYPT and returns a handle to it. ALGORITHM specifies the algorithm with which the keys will be used and must be one of keyexchange, signature, or the OID of an algorithm in either dotted decimal or mnemonic form.

The following options may be specified with the command:
-archivable BOOLEAN If true, the key can be exported until its handle is freed after which it is no longer exportable.
-exportable BOOLEAN If true, the key is exportable. If false, session keys and private keys are not exportable.
-pregen BOOLEAN If true, specifies an initial Diffie-Hellman or DSS key generation. Not applicable for other algorithms.
-userprotected BOOLEAN If true, the user is notified by some CSP-specific means for some uses of the key.
-size KEYSIZE Specifies the key size to override the default key size. Since default key sizes are platform dependent, Microsoft recommends key size be explicitly set.
The returned handle must be freed by calling crypt_key_free.
crypt_get_security_descriptor HCRYPT
Returns the security descriptor associated with a CSP key container whose handle is HCRYPT.
crypt_implementation_type HCRYPT
Returns the implementation type of the context. This is one of the values software, hardware, removable, mixed (combination of the others), or unknown. Applications should be aware other values might be returned as well.
crypt_import_key HCRYPT KEYBLOB ?options?
Imports a key blob into the cryptographic context specified by HCRYPT and returns a handle to the imported key. The returned key handle must be freed by passing it to capi_key_free when no longer required. KEYBLOB is in one of the formats returned by capi_key_export.

The command accepts the following options
-exportable BOOLEAN If true (default), the imported key can be exported at a later time. If false the key cannot be exported although it can be used for cryptographic operations.
-ipsechmac BOOLEAN TBD
-oaep BOOLEAN TBD
-userprotected BOOLEAN If specified as true, the user is notified in a CSP-dependent manner whenever the key is used. Default is false.
-wrapper HWRAPPER If KEYBLOB was in an encrypted form, this option must be specified and HWRAPPER should be the handle to the key that can decrypt the key blob.
crypt_key_container_delete KEYCONTAINER ?options?
Deletes the key container identified by the specified options. KEYCONTAINER specifies the name of the key container to be deleted in the CSP. If the empty string, the default container is deleted. Since this can impact other applications, the -force option must be specified when deleting the default container.
-csp CSP Specifies the name of the CSP for the key container. If unspecified, the default Microsoft CSP for the system is used.
-csptype CSPTYPE Indicates the type of CSP. Defaults to prov_rsa_full. See Cryptographic Service Providers for all possible types.
-force Must be specified when deleting the default container.
-keysettype KEYSETTYPE KEYSETTYPE must be user (default) or machine. Normally the key container is stored in the user's profile. If KEYSETTYPE is machine, the key container is treated as a computer container.
The command will raise an error if the container does not exist.
crypt_key_container_name HCRYPT
Returns the name of key container for the cryptographic context.
crypt_key_container_names HCRYPT
Returns the names of the other key containers owned by the CSP other than the one current one.
crypt_key_free HCRYPTKEY
Deprecated. Use capi_key_free instead.
crypt_key_specifiers HCRYPT
Returns the key specifiers supported by the CSP. This is a list from zero or more values from keyexchange and signature. Note that this does not mean the corresponding key pair currently exists in the context, only that the CSP supports that functionality. Applications should be aware other values might be returned in the list as well and should be ignored for future compatibility.
crypt_keypair HCRYPT keytype
Returns a handle to one of two public/private key pairs in a key container. HCRYPT is a handle to the CSP key container. keytype must be either keyexchange or signature and specifies which of the two key pairs in the container.

The returned handle must be freed by calling crypt_key_free.
crypt_keyset_type HCRYPT
Returns user or machine depending on whether the key set in the container is per-user or per-machine.
crypt_set_security_descriptor HCRYPT ?SECD?
Sets the security descriptor associated with a CSP key container whose handle is HCRYPT.
crypt_session_key_size HCRYPT
Returns the size of the session key in the container.
crypt_sig_keysize_increment HCRYPT
Returns the number of bits by which the signature key size can be incremented. The crypt_algorithms command returns the minimum and maximum key lengths for each algorithm in the context. This command returns the valid increments between the minimum and maximum values for the signature algorithm for the context.
crypt_symmetric_key_size HCRYPT
Returns the size of the symmetric key in the container.
csp_types
Returns a list of pairs, each representing a CSP type on the system. The first element of each pair is a CSP type and the second is the name of the CSP.
csps
Returns a list of pairs, each representing a CSP on the system. The first element of each pair is a CSP type and the second is the name of the CSP.
des iv|encrypt|decrypt BYTES CONCEALEDKEY ?options?
Implements cryptographic operations using the DES algorithm.

The iv subcommand returns a randomly generated initialization vector suitable for DES. No additional arguments are allowed.

For encrypt and decrypt commands, BYTES is the binary string to be encrypted or the ciphertext to be decrypted. CONCEALEDKEY is the DES key in concealed form. The returned value is the encrypted ciphertext or decrypted plaintext respectively. The following options affect encryption or decryption operation.
-iv IV A binary string to be used as the initialization vector of the operation.
-mode MODE The cipher mode to be used for the operation. See capi_key_mode.
hmac DATA KEY ?PRF? ?CHARSET?
Computes the HMAC hash for the specified data DATA. The key KEY used in computation of the HMAC is and must be in a concealed form.

The pseudo random function used in calculating the MAC is specified by PRF which defaults to SHA-1. If explicitly specified, PRF should be an appropriate algorithm identifier such as sha_256.

DATA must be a binary string unless CHARSET is specified in which case it is converted to a binary string using the specified character set encoding CHARSET using the Tcl encoding command and the HMAC is calculated on the result.

The command returns the computed HMAC as a binary string.
md5 DATA ?CHARSET?
Returns the MD5 digest for DATA. If CHARSET is not specified or is an empty string, DATA is assumed to be a binary string. Otherwise, it is converted to a binary string using the specified encoding CHARSET and the digest is calculated on the result.
oid OID_OR_NAME
If OID_OR_NAME is an OID dotted decimal string, returns it as is. Otherwise, treats it as a mnemonic and returns the corresponding dotted decimal OID. The oid_ prefix is optional so either common_name or oid_common_name are accepted. An error is raised if there is no matching mnemonic.

For a list of mnemonics, see the oids command.
oidname OID_OR_NAME
If OID_OR_NAME is an OID dotted decimal string, returns its mnemonic if there is one. Otherwise, if the passed argument is a dotted decimal OID, returns it. If neither condition is met, raises an error.

For a list of mnemonics, see the oids command.
oids ?PATTERN?
Returns a dictionary mapping OID mnemonics matching PATTERN to their dotted decimal OID's.
pbkdf2 PASSPHRASE KEYSIZE PRF SALT NITERATIONS
Generates a key of the specified number of bits KEYSIZE based on the specified pass phrase PASSPHRASE using the PBKDF2 algorithm defined by RFC 2898. PASSPHRASE must be in concealed form as returned by a password input command like read_credentials.

PRF specifies the pseudo random function and must be either sha1 or sha_256. SALT and NITERATIONS are used as defined in the RFC.

The returned key is in a concealed form.
pkcs7_decrypt PKCS7MSG STORES ?options?
Decrypts the PKCS7 message PKCS7MSG and returns the corresponding plaintext. STORES should be a list of one or more certificate store handles one of which must contain a certificate matching one of the recipients listed in the message and which has an associated private key.

The following options may be specified.
-certvar CERTVAR If specified and CERTVAR is not the empty string, a handle to a certificate context for the certificate used for decryption is stored in the variable CERTVAR in the caller's context. This must be released later by calling cert_release.
-encoding ENCODING If unspecified or the empty string, the command attempts to determine the encoding itself. Otherwise, ENCODING must be der or pem depending on whether PKCS7MSG uses DER- or PEM-encoding. For performance reasons, the encoding should be explicitly specified when possible.
-silent BOOL If the decryption key is user protected, the user is notified when the key is used. If -silent is true, the user is not notified for such keys and the command returns an error instead. Default is false.
pkcs7_encrypt BINDATA RECIPIENTS ENCALGOID ?options?
Encrypts the binary string BINDATA using a generated session key for the symmetric encryption algorithm specified by the OID ENCALGOID. The session key is itself encrypted using each of the public keys corresponding to the list of certificate contexts RECIPIENTS. The return value is formatted as an enveloped PKCS7 message as defined in RFC 2315.

The following option may be specified with the command.
-encoding ENCODING Specifies the encoding in which the encoded message is returned. ENCODING may be der or pem (default) for DER- and PEM-encoding respectively.
pkcs7_sign BINDATA HCERT HASHALGOID ?options?
Computes the hash of the binary string BINDATA, signs it with the private key corresponding to the certificate HCERT and returns it as a PKCS7 formatted message as defined in RFC 2315. HASHALGOID is the OID of the hashing algorithm to be used. The following options may be specified.
-detached BOOL If false (default), the content BINDATA is included in the message. If true, the PKCS7 packet is constructed as a detached packet without the content.
-encoding ENCODING Specifies the encoding in which the encoded message is returned. ENCODING may be der or pem (default) for DER- and PEM-encoding respectively.
-includecerts none|leaf|all If unspecified or all, the signing certificate HCERT along with all certificates in its certificate chain are included in the PKCS7 message. If leaf, only the signing certificate is included and if none, no certificates are included in the message.
-silent BOOL If the signing key is user protected, the user is notified when the key is used for signing. If -silent is true, the user is not notified for such keys and the command returns an error instead. Default is false.
-usersignerkeyid BOOL By default or if false, the certificate issuer and serial number is used to identify the signer. If this option is true, the key identifier is used for this purpose instead.
pkcs7_verify PKCS7MSG ?options?
Verifies the signature of a PKCS7 signed message PKCS7MSG. If the signature verifies successfully, the command returns ok. Otherwise, it returns one of the error status values specified for cert_verify.

In addition to verifying the signature on the message, the command also verifies that the signing certificate is valid by calling cert_verify. All options for that command are therefore accepted by pkcs7_verify as well.

In addition to those options, the command accepts the following options:
-certvar CERTVAR If specified and CERTVAR is not the empty string, a handle to a certificate context for the signing certificate is stored in the variable CERTVAR in the caller's context. This must be released later by calling cert_release.
-contentvar CONTENTVAR If specified and CONTENTVAR is not the empty string, the content of the message is stored in the variable CONTENTVAR in the caller's context.
-encoding ENCODING If unspecified or the empty string, the command attempts to determine the encoding itself. Otherwise, ENCODING must be der or pem depending on whether PKCS7MSG uses DER- or PEM-encoding. For performance reasons, the encoding should be explicitly specified when possible.
protect_data BINDATA ?options?
Encrypts and signs the binary data BINDATA so that it can only be recovered by a process running under the same user credentials on the same system through unprotect_data.

The following options may be specified:
-audit BOOLEAN If true, an audit event is generated. Default is false.
-description DESCRIPTION A descriptive string that is stored with the encrypted data.
-hwnd HWND The handle to the parent window if a dialog is to be shown to the user.
-localmachine BOOLEAN If false (default), only the same user can decrypt the data. If true, any user on the same machine can do the decryption.
-noui BOOLEAN If true, the operation fails if any user dialog is required to be shown. Default is false.
-prompt PROMPTSTRING If specified, the user is shown a dialog with the specified PROMPTSTRING to set the security level of the encrypted data. The user will also be prompted at the time the data is decrypted.
sha1 DATA ?CHARSET?
sha256 DATA ?CHARSET?
sha384 DATA ?CHARSET?
sha512 DATA ?CHARSET?
Return the SHA-1, SHA-256, SHA-384 or SHA-512 digests respectively for DATA. If CHARSET is not specified or is an empty string, DATA is assumed to be a binary string. Otherwise, it is converted to a binary string using the specified encoding CHARSET and the digest is calculated on the result.
unprotect_data BINDATA ?options?
Decrypts and verifies the signature on the binary data BINDATA which must have been encrypted with the protect_data command. The command will raise an error if BINDATA was encrypted under different user or machine credentials. The command returns the decrypted data.

The following options may be specified:
-withdescription BOOLEAN By default the command returns just the decrypted data. If specified as true, the command returns a list of two elements - the decrypted data and a descriptive string that is stored with the encrypted data.
-hwnd HWND The handle to the parent window if a dialog is to be shown to the user.
-noui BOOLEAN If true, the operation fails if any user dialog is required to be shown. Default is false.
-prompt PROMPTSTRING If specified, the user is shown a dialog with the specified PROMPTSTRING.

COPYRIGHT

Copyright © 2007-2016 Ashok P. Nadkarni

Tcl Windows API 4.7.1