The CryptoSys API gives you the ability to call fast, efficient cryptographic functions in Visual Basic, VBA, VB.NET, C/C++, C#, and ASP. It can be called from VBA applications like Access, Excel and Word. It provides four of the major block cipher algorithms, a stream cipher algorithm, all the major secure message digest hash algorithms, the HMAC and CMAC message authentication algorithms, a data compression facility, a password-based key derivation function (PBKDF2), and a secure random number generator.
The block cipher algorithms provided are the Advanced Encryption Standard (AES) as specified in FIPS PUB 197; the original Data Encryption Standard (DES); Triple DES (TDEA, 3DES, DES-EDE3); and Bruce Schneier's Blowfish. Key Wrap algorithms for AES and Triple DES are provided [new in version 4.1]. The message digest hash functions are MD5, the Secure Hash Algorithm (SHA-1), SHA-256, SHA-384, SHA-512, and [new in version 4.1] SHA-224. The HMAC algorithm is provided for all these hash algorithms and the CMAC algorithm for the block ciphers Triple DES and AES. The PC1 stream cipher is fully compatible with RC4. The random number generator (RNG) generates cryptographically-secure random numbers to the strict NIST SP800-90 standard, now an Approved Random Number Generator for FIPS PUB 140-2.
The CryptoSys API functions allow you to encrypt, decrypt, hash and authenticate data in a variety of formats, as well as generating secure random keys to use in your applications. Your input data can generally be in a byte array, encoded as a hexadecimal string, or in a file. The functions can process the data in a one-off manner, or, for longer inputs, you can call the "update" functions sequentially after initialising. The block cipher algorithms work in Electronic Codebook (ECB), Cipher Block Chaining (CBC), Cipher Feedback (CFB), Output Feedback (OFB) and Counter (CTR) modes. You can generate random keys and nonces in a secure manner. All functions are thread-safe.
The CryptoSys API provides functions to carry out primitive cryptographic operations intended to be used as part of a security-related application. It is up to you the programmer to ensure that keys, passwords and other private data in your application are kept secret, and to ensure that appropriate security policies and procedures are followed by end users.
This manual assumes you are familiar with the basics of cryptography and can program to a reasonably advanced level.
To get started, read the sections on Installation and General Programming Issues and the section on your programming language:
Dim strData As String Dim nRet As Long strData = "Hello world" Debug.Print strDataCode in C/C++ is shown as:
char *str = "Hello world";
printf("%s\n", str);
Code in VB.NET (VB200x) is shown as:
Dim nDataLen As Integer Dim abData() As Byte If strData.Length = 0 Then Exit Function abData = System.Text.Encoding.Default.GetBytes(strData) nDataLen = abData.LengthCode in C# is shown as:
public static string ToHex(byte[] binaryData)
{
int nBytes = binaryData.Length;
Int32 nChars = 2 * nBytes;
if (nBytes == 0) return String.Empty;
StringBuilder sb = new StringBuilder(nChars);
nChars = CNV_HexStrFromBytes(sb, nChars, binaryData, nBytes);
return sb.ToString(0, nChars);
}
Code in VBScript/ASP is shown as:
Dim oGen
Set oGen = Server.CreateObject("diCryptOCX.gen")
Response.Write "Version=" & oGen.Version & Chr(13) & Chr(10)
Output from code samples is shown as:
Result=OKAll functions called directly in the CryptoSys API begin with 3 or 4 capital letters followed by an underscore "_", e.g.
nRet = API_ErrorLookup(strMsg, Len(strMsg), nCode)
For VB users, there are some wrapper functions provided in the module basCryptoSys.bas
which avoid the complications of having to pre-dimension strings, etc. These
begin with lowercase letters and have no underscore. They are shown in our examples as follows:
strErrMsg = apiErrorLookup(nCode)
Except where otherwise noted, the CryptoSys API executable, sample source code and this manual were written by David Ireland and are copyright (c) 2001-8 by DI Management Services Pty Limited, all rights reserved. They may not be distributed or reproduced separately by any means whatsoever without express permission. Users holding a valid developer's licence are permitted to distribute the executable as part of a value-added application according to the terms of their licence.
You may obtain latest version of CryptoSys API from <http://www.cryptosys.net>.
For a good introduction to the principles of cryptography refer to Bruce Schneier's Applied Cryptography [SCHN] or William Stallings Cryptography and Network Security [STAL]. For a more advanced treatment, see Handbook of Applied Cryptography by Menezes, van Oorschot and Vanstone [MENE].
The block and key lengths supported in the CryptoSys API package are as follows:
| Algorithm | Block length | Key length |
|---|---|---|
| DES | 8 bytes (64 bits) | 8 bytes (only 56 bits used out of 64) |
| Triple DES (TDEA, 3DES) | 8 bytes (64 bits) | 24 bytes (only 168 bits used out of 192) |
| Blowfish | 8 bytes (64 bits) | up to 56 bytes (variable up to 448 bits) |
| AES | 16 bytes (128 bits)* | 16 or 24 or 32 bytes (128/192/256 bits) |
* The deprecated older-style AES functions still support 192- and 256-bit block lengths but these were not adopted in the FIPS 197 standard.
The block cipher confidentiality modes in this module comply with Recommendation for Block Cipher Modes of Operation [SP80038A]. To quote from Section 5.3 of that document:
The input to the encryption processes of the CBC, CFB, and OFB modes includes, in addition to the plaintext, a data block called the initialization vector (IV), denoted IV. The IV is used in an initial step in the encryption of a message and in the corresponding decryption of the message.
The IV need not be secret; however, for the CBC and CFB modes, the IV for any particular execution of the encryption process must be unpredictable, and, for the OFB mode, unique IVs must be used for each execution of the encryption process.
In Electronic Codebook (ECB) mode, each block is encrypted independently. In Cipher Block Chaining (CBC) mode, an initialization vector (IV) is added to the first block of plaintext before encryption and the resultant ciphertext is added to the next block of plaintext before encryption, and so on. Decryption is the reverse process. The IV does not need to be kept secret and must be communicated to the receiving party along with the ciphertext.
Block ciphers in ECB or CBC mode require their input to be an exact multiple of the block length. Any odd bytes need to be padded to the next multiple. In general, this is the user's responsibility. However, for encrypting files, CryptoSys API adds a padding string using the convention described in Padding below. For all other encryption functions in this API, it is the user's responsibility to provide and handle appropriate padding where necessary for ECB and CBC modes. See Padding.
Cipher Feedback mode (CFB), Output Feedback mode (OFB) and Counter mode (CTR) do not require padding. We include CFB and OFB modes here for completeness where users may need to communicate with a system that requires it. We recommend using either CBC or CTR modes if you have the choice. CBC mode is supported in most encryption systems.
The CTR mode in this package treats the entire "IV" as a 64- or 128-bit "counter". So if the IV provided
is, say, 0xFFFFFFFFFFFFFFFD for a 64-bit block cipher, then the counter values used will be:
fffffffffffffffd fffffffffffffffe ffffffffffffffff 0000000000000000 0000000000000001 ...It's up to the programmer to ensure that unique IV or counter values are provided for each message encrypted with the same key. Using an IV generated each time with the
RNG_NonceData or
RNG_NonceDataHex function should be perfectly adequate
as the odds against producing a duplicate value are billions to one.
There are many conventions used in practice, see our web page Using Padding in Encryption. It's up to you and your recipient which method you use, but you must agree on one method and use it consistently. If your data is always an exact multiple of the block length and the sender and the recipient agree then you can omit the padding string.
We recommend the convention from section 6.3 of RFC 3852 [CMS] (formerly RFC 3369 and RFC 2630), PKCS #5 [PKCS5] and PKCS #7 [PKCS7]; namely:
For a 64-bit block size: Append a padding string of between 1 and 8 bytes to make the total length an exact multiple of 8 bytes. The value of each byte of the padding string is set to the number of bytes added; namely, 8 bytes of value 0x08, 7 bytes of value 0x07, ..., 2 bytes of 0x02, or one byte of value 0x01. The length of the plaintext to be encrypted thus will be a multiple of 8 bytes and it will be possible to recover the message unambiguously from the decrypted ciphertext.See the functionsFor a 128-bit block size (e.g. for AES), replace "8 bytes" in the above paragraph with "16 bytes" and replace "0x08" with "0x10", and reword accordingly.
PAD_BytesBlock,
PAD_UnpadBytes,
PAD_HexBlock and
PAD_UnpadHex.
A stream cipher operates on streams of plaintext one bit or byte at a time. The PC1 stream cipher in this API has a variable key size and operates on one byte at a time. By an amazing coincidence the PC1 algorithm produces identical results to the proprietary RC4 stream cipher which is in common use, for example, in encrypting PDF files. So you can substitute "RC4" wherever you find "PC1" in this document. The key can be any number of bytes long. The algorithm is very fast. The output is always the same length as the input. There is no 'decrypt' mode: to decipher just encrypt again with the same key.
A message digest hash function is a cryptographic primitive used for digital signatures and password protection. It maps a message of arbitrary length to a fixed-length hash value or "message digest". A cryptographic hash should be one-way and collision-resistant. "One-way" means that, given an n-bit hash value, it should require work equivalent to about 2^n hash computations to find any message that hashes to that value. "Collision-resistant" means that finding any two messages which hash to the same value should require work equivalent to about 2^n/2 hash computations. In other words, it should be computationally infeasible to find the original message from the digest or to create another message that produces the same result.
SHA-1 is a 160-bit (20-byte) hash function specified in FIPS PUB 180-2 Secure Hash Standard [FIPS180].
SHA-256 is the newer standard intended as a companion for the new Advanced Encryption Standard (AES) to provide a similar level of enhanced security. SHA-256 is a 256-bit (32-byte) hash and is meant to provide 128 bits of security against collision attacks. SHA-256 is also specified in FIPS PUB 180-2 [FIPS180].
SHA-384 and SHA-512 provide greater levels of security, but at a greater computing cost. Both use the same algorithm but SHA-384 has a different starting value and a shorter digest value.
MD5 is an older, less-secure but faster hash algorithm still in common use.
A message authentication code (MAC) is used to establish the authenticity and, hence, the integrity of a message. MACs have two functionally distinct parameters, a message input (data, text) and a secret key known only to the message originator and intended receiver.
MACs based on cryptographic hash functions are known as HMACs. The HMAC algorithm is described in [FIPS198] and RFC 2104 [HMAC]. HMACs can have a key of any length and produce a digest of the same length as the underlying message digest function.
The CMAC algorithm is based on a symmetric key block cipher and is equivalent to the one-key CBC MAC1 (OMAC1) algorithm. CMAC is described in SP800-38B [SP80038B]. CMAC uses either Triple DES or one of the three AES functions. The key length for CMAC is the same as the underlying block cipher. The output is the same length as the block length: 64 bits for Triple DES and 128 bits for AES.
It is permissible to truncate a MAC value, at a cost of reduced security.
Compressing data before encryption not only makes for shorter messages to be transmitted or stored, but also improves security by reducing the redundancy in the plaintext and making cryptanalysis harder.
CryptoSys API includes compression (deflate) and decompression (inflate) functions based on Jean-loup Gailly's excellent zlib product.
You will need to devise a packet format to store the uncompressed length of the data along with the compressed data itself. There is an example of this posted on our web site - see Using Compression with CryptoSys. Just remember to compress before you encrypt.
Many procedures use a random session key to encrypt the body of the message. If this key
is ever compromised - because the random numbers are predictable or can be manipulated before
being generated -
an opponent who has had access to your encrypted messages can decipher them at his leisure.
You never use the standard VB6 Rnd() or C stdlib rand()
functions to generate your keys!
For more examples of potential problems see [GUTM]
and [KELS98].
The underlying RNG functions use the algorithms recommended in NIST SP 800-90 [SP80090] (the "DRBG Standard") to provide a Deterministic Random Bit Generator (DRBG). The HMAC_DRBG mechanism is used with SHA-1 as the underlying hash function. This outputs a sequence of binary bits that appears to be statistically independent and unbiased. The output is effectively random so long as internal actions of the process are hidden from observation. In particular the algorithm provides good Backtracking Resistance and, depending how it is used, good Prediction Resistance.
Entropy is accumulated at startup and whenever certain functions in the library are called. Only inobtrusive methods of collecting entropy are used, so you can use the API safely in any application. The "Fortuna" method of pooling is used to prevent certain attacks from someone who controls some but not all of the entropy sources (see chapter 10 of [FERG03]). The more times your application calls the functions in the library before needing some random data, the more entropy will be accumulated. The user cannot control how or when the Fortuna entropy is added to the RNG process - this is by design. The advantage of the Fortuna system is that the level of entropy does not need to be measured. There is, however, a period of vulnerability just after start up when there may not be sufficient entropy in the pools. This can be overcome by initializing with a seed file.
We strongly recommend that you use and initialize with a seed file wherever possible.
RNG_Initialize
function to specify a seedfile with a known minimum amount of entropy
to initialise the PRNG. This seed file is updated automatically when used. You
can optionally call the
RNG_UpdateSeedFile
from time to time in your
application, and use
RNG_MakeSeedFile
to create a new one. The security of this
method is as good as the security you have over the seed file. If an attacker
controls the seed file, it does not mean they control the random output data; it
just means that using a seedfile does not increase the security strength of the PRNG.
RNG_BytesWithPrompt function
when generating random data to force the user to
generate entropy using random keystrokes and mouse movements.
RNG_MakeSeedFile
also uses such a prompt.
This works provided you know the user's keyboard strokes and mouse movements are secure
(e.g. are not being transmitted over a network).
RNG_KeyBytes function.
If you assume zero security strength for the
internally-generated entropy and you add input with, say, 128 bits of security
strength, then the output from the RNG will have at least 128 bits of security
strength.
User-supplied entropy (a.k.a. a "seed") is added as "additional input" to the generation process. It does not affect the accumulation pools and cannot be used by an attacker to control the output.
Remember it's not how "random" your user-supplied entropy is, but how little an
attacker knows about it. Using the current time is no use. If you can provide
32 bytes* of data of which an attacker knows nothing and cannot later discover,
then you have added 128 bits of security strength.
* The bytes must have been selected randomly from the range 0 to 255.
For more details on the security aspects of the random number generator, see the technical details published on our web site.
CryptoSys API also lets you generate nonces - a term used in security engineering meaning "number used once". Use a nonce where random but not-necessarily-unpredictable numbers are required: e.g. for initialization vectors, SSL cookies and random padding data.
Use the setup.exe program to install
CryptoSys API onto your computer. To uninstall,
use the the Start>Settings>Control Panel>Add/Remove Programs option from Windows.
Instructions on how to distribute the product to third-party users are provided
with the Licensed Developer version - see the file distrib.txt for more details.
Important: You must use the setup.exe program to install the Personal and Server Trial versions on your system
and you
must have administrator rights when installing or uninstalling either of these versions.
diCryptoSys.dll which is a Win32 DLL. This file must
exist in the library search path on the user's system for all programming language interfaces.
The executable diCryptoSys.dll is not registered with RegSvr32 (it can't be).
The VB6/VBA and C/C++ interfaces access this core executable directly.
diCryptOCX.dll is an ActiveX DLL which exposes various classes to allow
programming access from ASP, VBScript and other COM applications including VB.
This DLL does require registering.
To register, copy the diCryptOCX.dll to a convenient folder, open a command-line
window, and type
REGSVR32 diCryptOCX.dll
diCrSysAPINet.dll is a .NET Class Library which exposes various classes
to allow programming access from C# and VB.NET projects.
This file is referenced from your .NET project. It is not registered.
Ciphertext is not text!The input to and output from an encryption function is, strictly speaking, a bit string. A `bit string' is an ordered sequence of `bits', each of value either `0' or `1'. There isn't a convenient `bit string' type in the usual programming languages so we use an ordered sequence of `bytes' instead, 8 bits to one byte, and we almost always choose to work with values that are an exact multiple of 8 like 64 bits or 256 bits to make life easier.
The input to an encryption function is usually a representation of a text string like "Hello world!". Different systems store text in different ways. You need to convert the text to an unambiguous sequence of bytes before you encrypt it. For ECB and CBC modes you need to add padding bytes as well to ensure the input block is an exact multiple of the cipher block size.
Do not store ciphertext bytes in a string.
Once encrypted, the output is another sequence of bytes known as ciphertext. This sequence of bytes is generally not printable - it shows up as garbage. You can safely save this sequence of bytes directly to a binary file. It's often more convenient to encode the ciphertext bytes into a hexadecimal or base64 string, which is much easier to handle. But you do not convert the ciphertext back to text. It won't work.
When decrypting, after you've deciphered the ciphertext back to plaintext, you still have a sequence of bytes. You need to convert these bytes back to a string of text before you can read it, provided your decryption was successful.
Use the functions below to convert a string of text to an unambiguous array of bytes and vice versa.
In VB6/VBA, use the StrConv function.
Dim abData() As Byte Dim Str As String Dim i As Long Str = "Hello world!" ' Convert string to bytes abData = StrConv(Str, vbFromUnicode) For i = 0 To UBound(abData) Debug.Print Hex(abData(i)); "='" & Chr(abData(i)) & "'" Next ' Convert bytes to string Str = StrConv(abData, vbUnicode) Debug.Print "'" & Str & "'"
48='H' 65='e' 6C='l' 6C='l' 6F='o' 20=' ' 77='w' 6F='o' 72='r' 6C='l' 64='d' 21='!' 'Hello world!'
In VB.NET use System.Text.Encoding.
Dim abData() As Byte Dim Str As String Dim i As Long Str = "Hello world!" ' Convert string to bytes abData = System.Text.Encoding.Default.GetBytes(Str) For i = 0 To UBound(abData) Console.WriteLine(Hex(abData(i)) & "='" & Chr(abData(i)) & "'") Next ' Convert bytes to string Str = System.Text.Encoding.Default.GetString(abData) Console.WriteLine("'" & Str & "'")You could be more explicit by replacing
.Default with .GetEncoding(1252),
and then use the appropriate code page for your character set (1252 is Western European).
In C#, use System.Text.Encoding, which has identical behaviour to the function in VB.NET.
byte[] abData;
string Str;
int i;
Str = "Hello world!";
// Convert string to bytes
abData = System.Text.Encoding.Default.GetBytes(Str);
for (i = 0; i < abData.Length; i++)
{
Console.WriteLine("{0:X}", abData[i]);
}
// Convert bytes to string
Str = System.Text.Encoding.Default.GetString(abData);
Console.WriteLine("'{0}'", Str);
In C and C++, the distinction between a string and an array of bytes is often blurred.
A string is a zero-terminated sequence of char types and
bytes are stored in the unsigned char type.
A string needs an extra character for the null terminating character;
a byte array does not, but it needs its length to be stored in a separate variable.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void pr_hexbytes(const unsigned char *bytes, int nbytes)
/* Print bytes in hex format + newline */
{
int i;
for (i = 0; i < nbytes; i++)
printf("%02X ", bytes[i]);
printf("\n");
}
int main()
{
char szStr[] = "Hello world!";
unsigned char *lpData;
long nbytes;
char *lpszCopy;
/* Convert string to bytes */
/* (a) simply re-cast */
lpData = (unsigned char*)szStr;
nbytes = strlen(szStr);
pr_hexbytes(lpData, nbytes);
/* (b) make a copy */
lpData = malloc(nbytes);
memcpy(lpData, (unsigned char*)szStr, nbytes);
pr_hexbytes(lpData, nbytes);
/* Convert bytes to a zero-terminated string */
lpszCopy = malloc(nbytes + 1);
memcpy(lpszCopy, lpData, nbytes);
lpszCopy[nbytes] = '\0';
printf("'%s'\n", lpszCopy);
free(lpData);
free(lpszCopy);
return 0;
}
48 65 6C 6C 6F 20 77 6F 72 6C 64 21 48 65 6C 6C 6F 20 77 6F 72 6C 64 21 'Hello world!'
The types char and unsigned char
might be identical on your system, or they might not be.
We strongly recommend that you explictly distinguish between strings and byte arrays in your code by using
the correct type and consistently treating them differently.
If your string is a Unicode string, then it consists of a sequence of wchar_t types.
Converting wide-character strings to a sequence of bytes in C is more problematic.
You can either convert the Unicode string directly to a string of bytes (in which case every second byte will be zero for
US-ASCII characters),
or use the stdlib wcstombs function or the Windows WideCharToMultiByte function
to convert to a sequence of multi-byte characters (some will be one byte long, some two)
and then convert the multi-byte string to bytes (you can do this with a simple cast).
Each party encrypting and decrypting must agree on which way to do it.
unsigned char* in C/C++).
The Hex version expects its input as a hexadecimal-encoded string consisting only of the characters [0-9A-Fa-f]
where two hex characters represent an 8-bit byte.
In all these cryptographic algorithms, the underlying operations are carried out on 8-bit bytes (sometimes referred to as octets). See Storing and representing ciphertext.
In practice, especially with VB and VBScript, you may find it more convenient to use the 'Hex' versions and pass all your data to the API functions as hexadecimal-encoded strings.
Use the CNV_BytesFromHexStr
and CNV_HexStrFromBytes functions to
convert between bytes and hexadecimal strings.
Use the Visual Basic StrConv function to convert between a String
and an array of Byte values.
See Converting strings to bytes and vice versa.
Note that the CNV_BytesFromHexStr function will - by design - filter invalid hex characters
and return the resulting bytes from whatever is left without error.
The hex versions of the encryption functions are stricter
and will fail if any invalid hex characters are found in the input.
If your input data is in Unicode or UTF-16 format (e.g. your operating system is set up for CJK characters),
then you are strongly recommended to convert your input data to unambiguous hexadecimal format before trying to
use the functions in this API.
Do not try and use the Visual Basic String type or it will end in tears.
For various historical reasons the Hex encryption functions return their results in upper case and
the hash digest functions in lower case.
Just be careful if you use the case-sensitive strcmp() function in the C string.h library
or if your Visual Basic options are set to Option Compare Binary.
It's your decision which way you do it, but please be consistent.
Long in VB6/VBA and a long in C/C++, but an Integer in VB.NET
and an int in C#.
The wrapper functions provided in the .NET and ActiveX
interfaces behave differently (and more conveniently) - please
refer to the detailed documentation on those interfaces.
Functions either
The exception is the _Init functions which return a non-zero context handle on success or zero if an
error has occurred. Always check the return value before continuing.
Use the _InitError
function to find out the code for the error that has occurred.
The value itself of the context handle is unimportant, but do not change its value.
To call the CryptoSys API functions
from a classic Visual Basic project or VBA application,
just add the module basCryptoSys.bas to your project
(VBA users should delete the first line Attribute VB_Name = "basCryptoSys").
The VB functions work in the same way as you would call the Win32 API functions from VB. You must use the correct variable types and must pre-dimension strings and byte arrays that are to receive output or you will suffer the wrath of the great god Gee-pee-eff.
For examples, see the test code
provided in the distribution in the folder C:\Program Files\CryptoSys\VB6.
Dim sData As String * 40or
Dim sData As String sData = String(40, " ")If you know the output string needs to be the same size as the input, do this:
Dim strInput As String Dim strOutput As String strInput = "......" strOutput = String(Len(strInput), " ")To create a byte array of a given length:
Dim abData() As Byte Dim nLen As Long nLen = 40 ReDim abData(nLen - 1)Note that byte arrays in VB are indexed from 0 to nLen - 1.
To create a byte array of the same length as an existing array, do this:
Dim abOutput() As Byte ReDim abOutput(Ubound(abInput))
To find the length of an existing byte array:
nLen = UBound(abData) - LBound(abData) + 1Be careful, as this will cause a run-time error if
abData() has not been ReDim'd.
Look at the code for the function cnvHexStrFromBytes in basCryptoSys.bas
to see how this can be handled.
Integer types are never used in CryptoSys API.
Only Long types are used.
Compile error: ByRef argument type mismatchit means you have omitted the "(0)" after a Byte parameter, e.g.
Dim abData() As Byte
' ...
nRet = CRC_Bytes(abData, nBytes, 0) ' WRONG: compile error
nRet = CRC_Bytes(abData(0), nBytes, 0) ' CORRECT
To use with a C or C++ program, include the diCryptoSys.h file with your source code
and link with the diCryptoSys.lib library. The only non-ANSI C requirement
is that your complier supports the __stdcall
calling convention to call Win32 API functions from a Win32 DLL.
The sample C code API_Examples.c provided in the distribution carries out a variety
of tests using known test vectors. There are examples given for each function.
You'll also realise that this manual is written primarily for Visual Basic programmers. Apologies, sort of, because we know you can easily work what to do from the examples given in the sample C programs and the rest of this manual.
The VB6/VBA functions and C/C++ functions are identical in form. The function names are identical, the arguments are the same (even though we may have used different parameter names in the VB and C syntaxes), and the same warnings given in the Remarks section apply to both. Just be careful to add an extra character for output string types in C.
The following type conversions apply:-
| Visual Basic | C/C++ |
|---|---|
ByVal x As String | char *x |
ByRef x As Byte | unsigned char *x |
ByVal x As Long | long x |
Earlier versions used the Boolean type for the bEncrypt variable. This has been
changed [Version 4.0] in the Declarations to take a 32-bit Long type,
which still works in VB6 even if the variable passed has been dimensioned as a Boolean type,
so this should not break any existing code.
We recommend that you use the defined constants ENCRYPT and DECRYPT in your VB6 and C code.
Here is some minimal code:-
/* myapisource.c */
#include <stdio.h>
#include "diCryptoSys.h"
int main()
{
char *message = "abc";
long ret;
char digest[41];
ret = SHA1_StringHexHash(digest, message);
printf("SHA1(%s)=\t%s\n", message, digest);
printf("Correct =\t%s\n", "a9993e364706816aba3e25717850c26c9cd0d89d");
return 0;
}
To create myapisource.exe with MSVC++:
cl myapisource.c diCryptoSys.libRunning this program should result in
SHA1(abc)= a9993e364706816aba3e25717850c26c9cd0d89d Correct = a9993e364706816aba3e25717850c26c9cd0d89d
implib diCryptoSys.lib diCryptoSys.dllTo compile with Borland C++:
bcc32 myapisource.c diCryptoSys.lib
char strings require an extra char for the NUL terminating
character, so add one more to the size a VB programmer would use, e.g.
char sDigest_sha1[41]; /* SHA-1 digest is 40 hex chars plus NUL */ char sDigest_sha2[65]; /* SHA-256 digest is 64 hex chars plus NUL */or
#include <stdlib.h>
char *buf;
buf = malloc(API_MAX_HASH_CHARS + 1);
/* ... */
free(buf);
API_SHA1_CHARS
and API_SHA1_BYTES rather than hard-coded numbers, e.g.
char sDigest_sha1[API_SHA1_CHARS + 1];See the constants in
diCryptoSys.h.
For examples, see the test code API_Examples.c and APICheck.c
provided in the distribution.
diCrSysAPINet.dll library file into a convenient folder.diCrSysAPINet.dll.using CryptoSysAPI;or (for VB.NET)
Imports CryptoSysAPIto your code.
Alternatively, with C#, you can just include the source code module CryptoSysAPI.cs in your project
and there is no need to reference the class library DLL.
There are two different types of methods used in the .NET interface:-
We recommend that you use the static methods if you only have a single block of data to operate on.
For examples, see the test code TestAPIcsharp.cs and TestAPIvbnet.vb
provided in the distribution.
In Version 3.1 we suggested using direct upgrades of the VB6 code in VB.NET with all the pre-dimensioning and other unsafe practices. The .NET Class Library interface is cleaner, safer and more convenient. If you are writing VB.NET code from scratch, please use the .NET Class Library interface. If you need to upgrade old VB6 code, see Upgrading VB6 to VB.NET.
CryptoSysAPI.chm supplied with the distribution
(Hint: it should be in the folder C:\Program Files\CryptoSys\DotNet).
diCryptOCX.dll is an ActiveX wrapper that provides an interface to most functions in the
CryptoSys API.
Strictly it's an ActiveX DLL, not an OCX, but we think three-letter acronyms with an "X" in them are cool.
diCryptOCX.dll into a convenient directory on the target machine.regsvr32 diCryptOCX.dll
diCryptOCX.dll
(Project>References>Browse...) then
Dim oGen = New diCryptoOCX.gen Debug.Print "Version=" & oGen.Version
Dim oGen
Set oGen = Server.CreateObject("diCryptOCX.gen")
Response.Write "Version=" & oGen.Version
Note: Almost all the functions require the data to be encoded in hexadecimal. Handling byte array types in VBScript is fraught with problems so we don't even offer the option.
For examples, see the test code apiocxtests.asp and other ASP test pages
provided in the distribution (look in the folder C:\Program Files\CryptoSys\COM).
API_Version function.
The function will demonstrate that the API is properly installed.
Here is some example source code in VB6, C, C#, VB.NET and ASP, respectively.
Public Sub ShowVersion()
Dim nRet As Long
nRet = API_Version()
Debug.Print "Version=" & nRet
End Sub
#include <stdio.h>
#include "diCryptoSys.h"
int main(void)
{
long version;
version = API_Version();
printf("Version=%ld\n", version);
return 0;
}
using CryptoSysAPI;
static void ShowVersion()
{
int ver;
ver = General.Version();
Console.WriteLine("Version={0}", ver);
}
Imports CryptoSysAPI
Shared Sub ShowVersion()
Dim ver As Integer
ver = General.Version()
Console.WriteLine("Version={0}", ver)
End Sub
<%
Dim oGen
Set oGen = Server.CreateObject("diCryptOCX.gen")
Response.Write "Version=" & oGen.Version & Chr(13) & Chr(10)
%>
diCryptoSys.dll. It is intended to meet FIPS 140-2 security level 1.
The cryptographic boundary for CryptoSys API
is defined as the enclosure of the computer on which the cryptographic module is installed.
As a pure software product, CryptoSys API provides no physical security by itself.
The computer itself must be appropriately physically secured.
HKCU\Software\DI Management.HKLM\Software\DI Management.
Do not attempt to change these entries.In addition to this automatic software integrity test, the integrity of the entire DLL file can be independently verified by the user using published SHA-1 and MD5 message digest and CRC-32 values before and after installation.
* The error log file will be given a filename "apierr.log". If the process does not have permissions to write to that directory, no log file be created.
You can make settings in the machine's registry to prevent the message box displaying and to change the destination directory of the log file. See Optional Registry Settings. It is not possible to prevent the DLL from exiting if a critical error happens.
The user may call the power-up self-tests on demand with the API_PowerUpTests
function. In the event that such an "on demand" test fails, the module will log the error event and return an error
code but will not terminate the process.
Note that the automatic self-tests fail only in exceptional circumstances. You should never see one in practice unless the software module has been tampered with.
Disclaimer Modifying the registry can cause serious problems that may require you to reinstall your operating system. We cannot guarantee that problems resulting from the incorrect use of the registry can be solved. Use the information provided at your own risk.
[HKEY_LOCAL_MACHINE\Software\DI Management\CryptoSys\Options]NoMessageBox[HKEY_LOCAL_MACHINE\Software\DI Management\CryptoSys\Options]ErrorLogDir[HKEY_LOCAL_MACHINE\Software\DI Management\CryptoSys\Options]NoErrorLogThe description for Event ID ( 8xxx ) in Source ( diCryptoSys ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer.For correct formatting of the message, create the REG_SZ and REG_DWORD values in the key below. The message will still be recorded even if this entry is not present.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\diCryptoSys]EventMessageFileTypesSupportedLong to Integer.
CryptoSys API always uses 32-bit integers.
Declare Function Foobarto
Declare Ansi Function Foobar
strBuffer = String(n, " ")to
strBuffer = New String(" "c, n)
Note the 'c' after the " ". This is required for the Strict On option.
System.Text.Encoding.Default.GetBytes(Str) and
System.Text.Encoding.Default.GetString(abData) to convert between text strings abd bytes
instead of StrConv(Str, vbFromUnicode) and StrConv(abData, vbUnicode).
Old-style:
AES_Hex(strOutput, strInput, strHexKey, 128, 128, True) ' Deprecated AES_Hex(strOutput, strInput, strHexKey, 192, 128, True) ' Deprecated AES_Hex(strOutput, strInput, strHexKey, 256, 128, True) ' Deprecated
Replace with:
AES128_Hex(strOutput, strInput, strHexKey, True) AES192_Hex(strOutput, strInput, strHexKey, True) AES256_Hex(strOutput, strInput, strHexKey, True)The older-style but deprecated AES functions with variable 128/192/256 block sizes have been retained for compatibility with earlier versions.
Input Data: Input data to the block encipher functions in ECB or CBC mode must be an exact multiple of the block length (16 bytes for AES, 8 bytes for the others) or the functions will return an error. It is the user's responsibility to provide padding where necessary and to remove the padding after decryption. Failure to do this will result in one of these errors:-
Input not multiple of 8 bytes long Input not multiple of block sizeSee Padding for more guidance on preparing your plaintext for encryption.
This rule on input lengths does not apply to the file encryption functions which automatically provide their own padding.
Keys and IV: All the keys and initialization vectors provided in hex format must be of the exact required length or the function will return an error:-
Invalid key length Invalid initialization vector
Note also that the CNV_BytesFromHexStr function will - by design - filter invalid hex characters and return
the resulting bytes from whatever is left without error. The hex versions of the encryption functions are stricter and will
fail if any invalid hex characters are found in the input.
See Hexadecimal versus Bytes for more details of the hex conversion functions.
The core executable diCryptoSys.dll is a Win32 DLL compiled with
Microsoft Visual C++ 2005.
All programming language interfaces require this DLL to exist in the library search path of the user's system.
The core cryptographic functions are written in pure ANSI C with extensive internal checks for memory leaks and overflow issues.
The executable diCryptoSys.dll is compatible with all versions of 32-bit Windows
(95/98/Me/NT4/2K/XP/2003/Vista).
It does not require any other special libraries to work apart from the standard Win32 libraries available in all
32-bit versions of Windows.
It is totally independent of the Microsoft Cryptographic API.
A version of the DLL compiled for x64 is also provided.
The wrapper executable diCryptOCX.dll is an ActiveX DLL
created with Microsoft Visual Basic 6.0 SP6.
It calls the functions in the core Win32 DLL via diCryptoSys.tlb, which
is available in the ActiveX source code. The source code for this wrapper DLL is provided in the distribution.
The executable diCryptOCX.dll must be registered on the end-user's system using REGSVR32.EXE.
For more details on its use, see Using with COM/ASP.
The wrapper executable diCrSysAPINet.dll is a .NET Class Library
created with Microsoft .NET Framework Version 2.0.50727 and
Microsoft Visual C# 2005, compiled for all platforms. This should be upwards compatible with all later versions.
It calls the functions in the core Win32 DLL using System.Runtime.InteropServices.
The source code for this wrapper DLL is provided in the distribution.
For more details on its use, see Using with .NET.
AES complies with:
Triple DES (TDEA, 3DES, des-ede3) complies with:
DES complies with these now-withdrawn standards:
The block cipher modes of operation comply with
The SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 algorithms comply with:
The MD5 algorithm complies with:
The PBKDF2 algorithm complies with:
The random number generator conforms to
The AES functions have a separate set of functions for each of the three key sizes.
All operate with a block size of 16 bytes. All expect a key of the respective length to be provided.
CAUTION: all three sets share the same context for the Init-Update-Final functions.
Blowfish can have a key of variable length from one to 56 bytes.
The Byte variants need you to specify the key length, but the
Hex variants will use whatever length is provided in the key hex
string.
The block and IV are always 8 bytes long.
BLF_HexBLF_HexModeBLF_BytesBLF_BytesModeBLF_B64ModeBLF_FileBLF_FileHexBLF_InitBLF_InitHexBLF_InitErrorBLF_UpdateBLF_UpdateHexBLF_FinalThe key for DES is always 8 bytes long; the block length is 8 bytes. There is no need to specify the key length when calling the DES functions, but the input variables must be long enough. The parity bits in the key are ignored.
DES_HexDES_HexModeDES_BytesDES_BytesModeDES_B64ModeDES_FileDES_FileHexDES_InitDES_InitHexDES_InitErrorDES_UpdateDES_UpdateHexDES_FinalDES_CheckKeyDES_CheckKeyHexThe key for TDEA is always 24 bytes long; the block length is 8 bytes. There is no need to specify the key length when calling the TDEA functions, but the input variables must be long enough. The parity bits in the key are ignored.
TDEA_HexTDEA_HexModeTDEA_BytesTDEA_BytesModeTDEA_B64ModeTDEA_FileTDEA_FileHexTDEA_InitTDEA_InitHexTDEA_InitErrorTDEA_UpdateTDEA_UpdateHexTDEA_FinalCIPHER_KeyWrap - Wraps (encrypts) a content-encryption key with a key-encryption key.CIPHER_KeyUnwrap - Unwraps (decrypts) a content-encryption key with a key-encryption key.HASH_BytesHASH_FileHASH_HexFromBytesHASH_HexFromFileHASH_HexFromHexMAC_BytesMAC_HexFromBytesMAC_HexFromHex
All the SHA-1 functions (except SHA1_BytesHash) output the message digest as a String
in hexadecimal format. You must set the length of the output string to a minimum of
40 characters before calling the digest functions (41 characters in a C program).
See Pre-dimensioning a string
for instructions on how to do this.
SHA1_StringHexHashSHA1_BytesHexHashSHA1_BytesHashSHA1_FileHexHashSHA1_InitSHA1_AddBytesSHA1_AddStringSHA1_HexDigestSHA1_ResetSHA1_HmacSHA1_HmacHexThe SHA-256 functions are identical in syntax and usage to their SHA-1 equivalents, except the string to receive the message digest must be set to a minimum of 64 characters (65 in a C program). See Pre-dimensioning a string.
SHA2_StringHexHashSHA2_BytesHexHashSHA2_BytesHashSHA2_FileHexHashSHA2_InitSHA2_AddBytesSHA2_AddStringSHA2_HexDigestSHA2_ResetSHA2_HmacSHA2_HmacHexThe MD5 functions are identical in syntax and usage to their SHA-1 equivalents, except the string to receive the message digest must be set to a minimum of 32 characters (33 in a C program). See Pre-dimensioning a string.
MD5_StringHexHashMD5_BytesHexHashMD5_BytesHashMD5_FileHexHashMD5_InitMD5_AddBytesMD5_AddStringMD5_HexDigestMD5_ResetMD5_HmacMD5_HmacHex
RNG_KeyBytes
RNG_KeyHex
RNG_BytesWithPrompt
RNG_HexWithPrompt
RNG_NonceData
RNG_NonceDataHex
RNG_Test
RNG_Number (supersedes RNG_Long)
RNG_Initialize
RNG_MakeSeedFile
RNG_UpdateSeedFile
PAD_BytesBlock
PAD_UnpadBytes
PAD_HexBlock
PAD_UnpadHex
These functions carry out conversions between bytes and hexadecimal-encoded strings, and bytes and base64-encoded strings.
CNV_BytesFromHexStrCNV_HexStrFromBytesCNV_HexFilterCNV_BytesFromB64StrCNV_B64StrFromBytesCNV_B64FilterThese functions compute a CRC-32 checksum of some given data. They all return the value of the checksum directly.
CRC_BytesCRC_FileCRC_StringThese functions allow you to check the version and other module details, carry out the self-tests on demand, and securely wipe data.
API_CompileTimeAPI_ErrorLookupAPI_LicenceTypeAPI_ModuleNameAPI_PowerUpTestsAPI_VersionWIPE_DataWIPE_FileThese still work but are no longer documented in this manual. See http://www.cryptosys.net/CryptoSysDeprecated.html.
AES_BytesAES_BytesModeAES_EcbAES_EcbHexAES_FileAES_FileHexAES_FinalAES_HexAES_HexModeAES_InitAES_InitErrorAES_InitHexAES_UpdateAES_UpdateHexbf_BlockDecbf_BlockEncbf_FileDecbf_FileEncbf_Finalbf_Initbf_StringDecbf_StringEncBLF_EcbBLF_EcbHexRAN_DESKeyGenerateRAN_DESKeyGenHexRAN_KeyGenerateRAN_KeyGenHexRAN_LongRAN_NonceRAN_NonceHexRAN_SeedRAN_TDEAKeyGenerateRAN_TDEAKeyGenHexRAN_TestRNG_KeyGenerateRNG_KeyGenHexRNG_LongAES128_B64Mode encrypts or decrypts data
represented as a base64 string
using a specified mode. The key and initialization vector
are represented as base64 strings.
Public Declare Function AES128_B64Mode Lib "diCryptoSys.dll"
(ByVal strOutput As String, ByVal strInput As String,
ByVal strKey As String, ByVal bEncrypt As Boolean,
ByVal strMode As String, ByVal strIV As String) As Long
nRet = AES128_B64Mode(strOutput, strInput, strKey, bEncrypt, strMode, strIV)
String of sufficient length to receive the output.String containing the input data in base64.String containing the key in base64.Boolean direction flag:
set as True to encrypt or False
to decrypt.String specifying the confidentiality mode:String containing the initialization vector (IV), if required,
in base64.
long _stdcall AES128_B64Mode(char *strOutput, const char *strInput,
const char *strKey, int bEncrypt, const char *strMode, const char *sIV);
Long: If successful, the return value is 0;
otherwise it returns a non-zero error code.
Aes128.Decrypt Method (String, String, Mode, String, EncodingBase)
public static string Decrypt(string inputStr, string keyStr, Mode mode, string ivStr, EncodingBase encodingBase);
Aes128.Encrypt Method (String, String, Mode, String, EncodingBase)
public static string Encrypt(string inputStr, string keyStr, Mode mode, string ivStr, EncodingBase encodingBase);
Aes128.Decrypt Method (String, String, Mode, String, EncodingBase)
Public Shared Function Decrypt(ByVal inputStr As String, ByVal keyStr As String, ByVal mode As Mode, ByVal ivStr As String, ByVal encodingBase As EncodingBase) As String
Aes128.Encrypt Method (String, String, Mode, String, EncodingBase)
Public Shared Function Encrypt(ByVal inputStr As String, ByVal keyStr As String, ByVal mode As Mode, ByVal ivStr As String, ByVal encodingBase As EncodingBase) As String
Encrypted/decrypted data in encoded string or empty string on error.
Refer to the .NET Help File for more details."").
The key strKey must also represent exactly 16 bytes, the required key length.
The output string strOutput must be set up with at least the same
number of characters as the input string before calling.
The variables strOutput and strInput should be different.
AES128_HexMode,
except the data is in base64 format.
Dim nRet As Long Dim strOutput As String Dim strInput As String Dim strKey As String Dim strIV As String Dim bEncrypt As Boolean Dim sCorrect As String ' Case #4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key ' Key : 0x56e47a38c5598974bc46903dba290349 strKey = "VuR6OMVZiXS8RpA9uikDSQ==" ' IV : 0x8ce82eefbea0da3c44699ed7db51b7d9 strIV = "jOgu776g2jxEaZ7X21G32Q==" ' Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf ' b0b1b2b3b4b5b6b7b8b9babbbcbdbebf ' c0c1c2c3c4c5c6c7c8c9cacbcccdcecf ' d0d1d2d3d4d5d6d7d8d9dadbdcdddedf strInput = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/" _ & "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==" ' Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa ' 0f3af07a9a31a9c684db207eb0ef8e4e ' 35907aa632c3ffdf868bb7b29d3d46ad ' 83ce9f9a102ee99d49a53e87f4c3da55 sCorrect = "ww4y/+3Ad05q/2rwhp9xqg868HqaManGhNsgfrDvjk" _ & "41kHqmMsP/34aLt7KdPUatg86fmhAu6Z1JpT6H9MPaVQ==" ' Set strOutput to be same length as strInput strOutput = String(Len(strInput), " ") Debug.Print "KY="; strKey Debug.Print "IV="; strIV Debug.Print "PT="; strInput nRet = AES128_B64Mode(strOutput, strInput, strKey, ENCRYPT, "CBC", strIV) Debug.Print "CT="; strOutput; nRet Debug.Print "OK="; sCorrect strInput = strOutput nRet = AES128_B64Mode(strOutput, strInput, strKey, DECRYPT, "CBC", strIV) Debug.Print "P'="; strOutput; nRetThis should result in output as follows:
KY=VuR6OMVZiXS8RpA9uikDSQ== IV=jOgu776g2jxEaZ7X21G32Q== PT=oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/ AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w== CT=ww4y/+3Ad05q/2rwhp9xqg868HqaManGhNsgfrDvjk 41kHqmMsP/34aLt7KdPUatg86fmhAu6Z1JpT6H9MPaVQ== 0 OK=ww4y/+3Ad05q/2rwhp9xqg868HqaManGhNsgfrDvjk 41kHqmMsP/34aLt7KdPUatg86fmhAu6Z1JpT6H9MPaVQ== P'=oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/ AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w== 0
AES128_HexMode
AES128_BytesMode
AES128_Bytes encrypts or decrypts an array of Bytes
in one step in Electronic Codebook (EBC) mode.
Public Declare Function AES128_Bytes Lib "diCryptoSys.dll"
(ByRef abOutput As Byte, ByRef abData As Byte, ByVal nDataLen As Long, ByRef abKey As Byte,
ByVal bEncrypt As Boolean) As Long
nRet = AES128_Bytes(abOutput(0), abData(0), nDataLen, abKey(0), bEncrypt)
Byte array of sufficient length to receive the output.Byte array containing the input data.Long equal to length of the input data in bytes.Byte array containing the key.Boolean direction flag:
set as True to encrypt or False
to decrypt.
long _stdcall AES128_Bytes(unsigned char *output, const unsigned char *input,
long nbytes, const unsigned char *key, int bEncrypt);
Long: If successful, the return value is 0;
otherwise it returns a non-zero error code.
This function is equivalent to
nRet = AES128_BytesMode(abOutput(0), abData(0), nDataLen, abKey(0), bEncrypt, "ECB", 0)
Dim nRet As Long
Dim abBlock() As Byte
Dim abKey() As Byte
Dim abPlain() As Byte
Dim abCipher() As Byte
Dim nBytes As Long
'FIPS-197
'C.1 AES-128 (Nk=4, Nr=10)
'PLAINTEXT: 00112233445566778899aabbccddeeff
'KEY: 000102030405060708090a0b0c0d0e0f
' Convert input to bytes
abKey = cnvBytesFromHexStr("000102030405060708090a0b0c0d0e0f")
abPlain = cnvBytesFromHexStr("00112233445566778899aabbccddeeff")
abCipher = cnvBytesFromHexStr("69c4e0d86a7b0430d8cdb78070b4c55a")
abBlock = abPlain
nBytes = UBound(abBlock) - LBound(abBlock) + 1
Debug.Print "KY="; cnvHexStrFromBytes(abKey)
Debug.Print "PT="; cnvHexStrFromBytes(abBlock)
' Encrypt in one-off process
nRet = AES128_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), ENCRYPT)
Debug.Print "CT="; cnvHexStrFromBytes(abBlock)
Debug.Print "OK="; cnvHexStrFromBytes(abCipher)
Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abCipher, vbUnicode))
' Now decrypt back to plain text
nRet = AES128_Bytes(abBlock(0), abBlock(0), nBytes, abKey(0), DECRYPT)
Debug.Print "P'="; cnvHexStrFromBytes(abBlock)
Debug.Assert (StrConv(abBlock, vbUnicode) = StrConv(abPlain, vbUnicode))
This should result in output as follows:
KY=000102030405060708090A0B0C0D0E0F PT=00112233445566778899AABBCCDDEEFF CT=69C4E0D86A7B0430D8CDB78070B4C55A OK=69C4E0D86A7B0430D8CDB78070B4C55A P'=00112233445566778899AABBCCDDEEFF
AES128_BytesMode encrypts or decrypts an array of Bytes
using a specified mode.
The key and IV data are in byte arrays.
Public Declare Function AES128_BytesMode Lib "diCryptoSys"
(ByRef abOutput As Byte, ByRef abData As Byte, ByVal nDataLen As Long, ByRef abKey As Byte,
ByVal bEncrypt As Boolean,
ByVal strMode As String, ByRef abInitV As Byte) As Long
nRet = AES128_Bytes(abOutput(0), abData(0), nDataLen, abKey(0),
bEncrypt, strMode, abInitV(0))
Byte array of sufficient length to receive the output.Byte array containing the input data.Long equal to length of the input data in bytes.Byte array containing the key.Boolean direction flag:
set as True to encrypt or False
to decrypt.String specifying the confidentiality mode:Byte containing the
initialization vector (IV), or zero (0) for ECB mode.
long _stdcall AES128_BytesMode(unsigned char *output, const unsigned char *input,
long nbytes, const unsigned char *key, int bEncrypt,
const char *lpszMode, const unsigned char *iv);
Long: If successful, the return value is 0;
otherwise it returns a non-zero error code.
Aes128.Decrypt Method (Byte[], Byte[], Mode, Byte[])
public static byte[] Decrypt(byte[] input, byte[] key, Mode mode, byte[] iv);
Aes128.Encrypt Method (Byte[], Byte[], Mode, Byte[])
public static byte[] Encrypt(byte[] input, byte[] key, Mode mode, byte[] iv);
Aes128.Decrypt Method (Byte[], Byte[], Mode, Byte[])
Public Shared Function Decrypt(ByVal input() As Byte, ByVal key() As Byte, ByVal mode As Mode, ByVal iv() As Byte) As Byte()
Aes128.Encrypt Method (Byte[], Byte[], Mode, Byte[])
Public Shared Function Encrypt(ByVal input() As Byte, ByVal key() As Byte, ByVal mode As Mode, ByVal iv() As Byte) As Byte()
Encrypted/decrypted data in byte array or empty array on error.
Refer to the .NET Help File for more details.0).
The output array abOutput must be at least as long as the input array.
abOutput and abData may be the same.
Note the (0) after the byte array variables.
Dim nRet As Long
Dim strOutput As String
Dim strInput As String
Dim sCorrect As String
Dim abKey() As Byte
Dim abInitV() As Byte
Dim abResult() As Byte
Dim abData() As Byte
Dim nDataLen As Long
' Set up input in byte arrays
strInput = "Now is the time for all good men"
sCorrect = "C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177"
abKey = cnvBytesFromHexStr("0123456789ABCDEFF0E1D2C3B4A59687")
abInitV = cnvBytesFromHexStr("FEDCBA9876543210FEDCBA9876543210")
abData = StrConv(strInput, vbFromUnicode)
nDataLen = UBound(abData) - LBound(abData) + 1
' Pre-dimension output array
ReDim abResult(nDataLen - 1)
Debug.Print "KY="; cnvHexStrFromBytes(abKey)
Debug.Print "IV="; cnvHexStrFromBytes(abInitV)
Debug.Print "PT="; cnvHexStrFromBytes(abData)
' Encrypt in one-off process
nRet = AES128_BytesMode(abResult(0), abData(0), nDataLen, abKey(0), _
ENCRYPT, "CBC", abInitV(0))
Debug.Print "CT="; cnvHexStrFromBytes(abResult)
Debug.Print "OK="; sCorrect
' Now decrypt back
nRet = AES128_BytesMode(abData(0), abResult(0), nDataLen, abKey(0), _
DECRYPT, "CBC", abInitV(0))
strOutput = StrConv(abData(), vbUnicode)
Debug.Print "P'="; strOutput
' Check
Debug.Assert (strOutput = strInput)
This should result in output as follows:
KY=0123456789ABCDEFF0E1D2C3B4A59687 IV=FEDCBA9876543210FEDCBA9876543210 PT=4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E CT=C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177 OK=C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E177 P'=Now is the time for all good men
AES128_File encrypts or decrypts a file
using a specified mode. The key and initialization vector
are passed as arrays of bytes.
Public Declare Function AES128_File Lib "diCryptoSys.dll"
(ByVal strFileOut As String, ByVal strFileIn As String,
ByRef abKey As Byte,
ByVal bEncrypt As Boolean, ByVal strMode As String, ByRef abInitV As Byte) As Long
nRet = AES128_File(strFileOut, strFileIn, abKey(0), bEncrypt, strMode, abInitV(0))
String with the full path name of the output
file to be created.String with the full path name of the input file
to be processed.Byte array containing the key.Boolean direction flag:
set as True to encrypt or False
to decrypt.String specifying the confidentiality mode: