newObjects (fromerly known as ZmeY soft) HashCryptStreams (part of AXPack1)
Home Products Docs & Libs
pixel.gif (49 bytes)
Products by category
ALP site
ISAPI filters
Forums (discussions)
Buy direct (RegNet)
Articles and samples
Documentation online

Read more ...
Click here
ALP is implemented as an Asynchronous Pluggable Protocol. It acts like a WEB server but without need of network. It executes WEB applications such as ASP pages and CGI applications. ALP makes Internet Explorer to be server and client. With ALP you can write stand-alone desktop applications, CD-ROM autoruns, use ASP for pure desktop software and still keep your code ready to run on WEB servers too.
Write desktop software in ASP and CGI!
download it

ASP Wire

Site navigation
ActiveX components

Binary and flat files

with ActiveX Pack1 ASP application is able to not just read/send binary files. They can be accessed as set of applciation defined records. And this is not limited to the files - any resource that behaves like file can be treated as like a DB table - memory streams, files, streams in OLE Compound files and so on.

Highlights of the day
Active Label ActiveX
Barcode ActiveX? Much more - the design and printing inside your WEB application
SQLite3 COM ActiveX embeds the SQLite3 database engine and interface to it. Supports paremeterized views and triggers.
Active Local Pages 1.2
Write desktop apps in ASP and CGI. Create wutorun CDs using WEB technologies - yes it is possible!
ActiveX Pack1 family
Desktop Windows, CE/CE.NET and PocketPC! About 50 powerful components for all the Windows platforms.
AXGate 1.1 (new)
Script dafely any ActiveX in Pocket IE. Build applications in HTML and use local resources and components in them.
IE ScriptBar
Create complex toolbars for Microsoft Internet Explorer easier than you may have expected.

Licensing types legend
(M) Single machine license
(U) Unlimited per-company license
(D) Unlimited development license
(S) Special type of licensing

Win free license for Active Local Pages!

Quick contact


Active visitors
Suggested links
newObjects (ZmeY soft)
Suggest this page to the other visitors. Click the button below to place this page in the list above .

 HashCryptStreams (part of AXPack1)   
Price: FREEWARE* Discount for resalers
Information Download Buy


This initial version adds support for cryptography and related tasks to the newObjects ActiveX Pack1 family (AXPack1). The HashCryptStreams.dll is distributed with the entire AXPack1 and the download links above point to the full packages containing also the other components of the family. Of course, this does not mean that you are required to redistribute all of them with the applications you are building. You can find installable packages and ZIP files with the AXPack1's DLL files from which you can get what you need and include it with your applications (The list of all the packages for download is here). It appears that exposing for download the whole family is more convenient than providing separate downloads for each of its component. 

1. Overview
2. How it looks in action
    a) Symmetric cryptography algorithms
    b) Hash and HMAC
    c) RSA
3. FAQ
4. What to download


The initial version of HashCryptStreams lays the foundation for cryptography support in AXPack1. This first version concentrates on the infrastructure and the programming interface. It provides support for some of the most popular symmetric cryptography algorithms, some hash functions with HMAC support and the RSA algorithm. Over the same infrastructure more algorithms will be provided with the next versions of HashCryptStreams enabling the developers to choose from wider set of algorithms without need to change their code.

What we have in version 1.0?

Hash functions with HMAC support: MD5, SHA-1, SHA-256

Symmetric cryptography algorithms: AES, DES and 3DES

Asymmetric cryptography: RSA algorithm

Goodies: Big number arithmetic (BigNumber object). 

Programming interface standard.

Most of you have already guessed that we want to create some kind of cryptography related programming interface standard with HashCryptStreams. Obviously this may look strange when you know that there is a CryptoAPI in Windows - so the question is why?

In contrast to the Windows CryptAPI HashCryptStreams defines a programming interface at a lower level of usage of the cryptography algorithms. The Windows API concentrates on providing standards based interface, while HashCryptStreams does that on the algorithm level. The need of such a programming interface appears when you need to deal with applications that do not conform to the standards or applications using standards not supported by the Windows Crypto API. In such case you need to do something yourself - pack the data as required by the other application, perform some specific operations and you have no choice but to go to a lower level. 

Is it easy to use? As much as possible. The hard part is to learn what custom or public standards you must obey in your particular case and then use HashCryptStreams (often in combination with objects like SFBinaryData from the AXPack1 core) to implement it.

I thought there were complete standards for cryptography, what all this means? 
In brief the situation is like this: You hear about certain algorithms and their usage - for instance you hear talks about how DES is no longer considered secure and one must move to 3DES at least or go for something even better like AES for example. However this is not the whole story. The algorithms are the simplest part of the applied cryptography, having them one faces another problem how to achieve a common ground with the other applications. One obvious problem behind all this is that most of the good symmetric algorithms are block based and when you encrypt something you get a cipher with size multiple of the block size and not equal to the size of the original data. So, you need to record the original size (or at least the remainder to the block size) when encrypting - in order to be able to truncate the rubbish after decrypting back. Here comes the question how to pad the data to the block size and so on and so on. Thus over the algorithms there are other standards that define how the meta-data about the encrypted data is packed. Unfortunately there are quite many applications following their own way to deal with these and the other problems and very often you cannot just call an encryption function and forget about the details. Once you are off the area covered by the SSL (Secure Socket Layer) and the digital signature oriented usage you would meet many variations of how and why the encryption algorithms are used and HashCryptStreams aims at providing a way to enable you write code for such scenarios even in VBScript/ASP.   

HashCryptStreams will include in the next versions built-in support for the most used PKCS standards, but will not go too much further than that. Instead it will improve in its main goals - making it easier for the developer to implement standard or non-standard cryptography schemes knowing only the requirements about the data packing and the general features of the algorithms involved, but not requiring him/her to know details about the specific algorithms.

How this looks in action

Lets first show a simple usage of a symmetric algorithm:

Set crypt = Server.CreateObject("newObjects.crypt.Symmetric")
crypt.Init "DES"
crypt.Key = "0123456789ABCDEF"
crypt.PadType = -1
cipher = crypt.Encrypt(mydata)

This is the simplest kind of usage when the whole data is processed in a single step. Of course it can be processed in chunks:

Set crypt = Server.CreateObject("newObjects.crypt.Symmetric")
crypt.Init "DES"
crypt.Key = "0123456789ABCDEF"
crypt.PadType = -1
' Assume infile is some file already opened for reading
' and outfile is a file opened for writing.
While Not infile.EOS
  chunk = infile.ReadBin(256)
    If Not infile.EOS Then
      ' Do not finalize encryption until the last chunk of data
      cipher = crypt.Encrypt(chunk,False)
      ' This is the last chunk of data - finalize so that the
      ' last block can be padded (see the PadType above)
      cipher = crypt.Encrypt(chunk,True) ' True is default for the second argument
    End If
    ' Write to the output file
    outfile.WriteBin cipher    

Aside of what you can see above the Symmetric object also can give you information about the block size of the algorithm. Knowing this you can perform your own padding or relay on the PadType property which when set to -1 pads with random bytes or repeats the specified value if it is > 0.

When you are doing something more than the basic operation you need more than just the encryption algorithm. Here comes the usefulness of the AXPack1 family as whole. One of the objects that would most often be needed with HashCryptStreams is SFBinaryData (from the AXPack1 core DLL - newobjectspack1.dll). What it gives you is advanced way to work with binary data buffers in memory. Whatever language you use, VBScript, Javascript, NSBasic etc., you would have problems working with binary data using the language capabilities only. Even in some languages offering more in that area it would be easier to relay on SFBinaryData for more efficient memory usage. In some cases you may need to combine more different kinds of operations involving read/write of streams, work with databases and so on. The fact that the AXPack1's objects are designed to copperate easily will simplify such tasks. 

To illustrate the above lets take an example where we would need to decrypt some data. However, we will want to make it harder, so lets assume that a file has been encrypted and the original file size has been encrypted with the file contents (before the actual data). The code below can be write in various forms, but we intentionally will use a way that involves more objects in order to illustrate how the can be used together:

' Create the objects we need
Set crypt = CreateObject("newObjects.crypt.Symmetric")
Set sf = CreateObject("newObjects.utilctls.SFMain")
Set sfbd = CreateObject("newObjects.utilctls.SFBinaryData")
' Open the files
Set infile = sf.OpenFile(infileName,&H40)
Set outfile = sf.CreateFile(outfileName)
' Init the Symmetric encryption object
crypt.Init alg
crypt.Key = key
' We will decrypt only - so there is no need to care about the padding method this time.
' The encrypted file contains the original file size in its first 4 bytes
' However we cannot read just 4 bytes because the block size can be bigger
' (usually is). So, to ensure we need to read entire block in a memory stream.
Set mem = sf.CreateMemoryStream
' How much to read, better read more than needed than less
blocksToRead = (crypt.BlockSize / 4) + 1
mem.WriteBin crypt.Decrypt(infile.ReadBin(crypt.BlockSize),False)
' Why memory stream? Well, you can use SFBinaryData for everything.
' we just used that in this example to make the task easy to understand
' Now use the binary data object to consume the size
sfbd.Size = 4
mem.Pos = 0
sfbd.Value = mem.ReadBin(4)
' Now get what we need and write the rest to the output
' Lets assume that the original size is in big endian and not in
' the native for Windows little endian byte order - just to make the things
' harder 
sfbd.ByteOrder = &H02
FileSize = sfbd.Unit(0,vbLong)
' Write the rest of the block to the output
mem.CopyTo outfile, crypt.BlockSize ' The number of bytes just needs to be bigger than the actual content
' mem is no longer needed lets dispose of it explicitly (not actually needed, 
' it will be freed as the script completes anyway.
Set mem = Nothing
' Decrypt the rest
  chunk = infile.ReadBin(256)
  If Not infile.EOS Then
    bindata = crypt.Decrypt(chunk,False)
    bindata = crypt.Decrypt(chunk,True)
  End If
  ' Write to the output file
  outfile.WriteBin bindata
Loop While Not infile.EOS
' Truncate the output file to the size we read before
outfile.Size = FileSize

Of course, this can be done with less code, but this way we can see how the different objects work together making the otherwise difficult problem a matter of configuring certain objects to match what we have to work with.

HashCryptStreams goes further. It provides two alternative programming interfaces for the same task - the first you can see in action above, the second is a stream filter that can be used to provide abstract file/stream interface which performs transparent encryption/decryption. Of course, this technique makes sense if the application is complex enough to benefit from separation of certain modules from the others. In simpler and more trivial usage scenarios using the stream filter is hardly justified because of the added work needed in order to make its usage transparent for the rest of the application. Here is a basic code snippet that configures a chain of streams and stream filter and then writes data through it - the data is encrypted while written. Of course, this code is illustration, in the real world the configuring part should be in a separate routine or module, while the code that uses it will be part of some application's task:

Set sf = Server.CreateObject("newObjects.utilctls.SFMain")
' Open the original file (read only)
Set infile = sf.OpenFile(Server.MapPath("original-image.gif"),&H40)
' Create the SFStreamCrypt object
Set crypt = Server.CreateObject("newObjects.crypt.SFStreamCrypt")
' We will encrypt while saving the file, thus we are going to use
' only the Write algorithm - so set up it. Set the algorithm 
crypt.WriteAlgorithm = myalg ' the name of the algorithm DES, AES etc.
' Set the key. This will fail if the key is not the correct length for the
' selected algorithm. Depending on how this is used it may be a good idea
' to check if the key is correct size and issue an error if it is not. 
crypt.WriteKey = Request("Key")
' By default the Write algorithm is configured for encryption, but
' we will specify this explicitly for the sake of the example.
crypt.WriteDecrypt = False
' As the algorithms are working with fixed size blocks the result
' may not match the size of the encrypted data. Thus we need to know the
' original size when we are decrypting. The best way for us is to keep the
' size with the encrypted file. So we will write it before the file data.
FileSize = infile.Size
Set bd = Server.CreateObject("newObjects.utilctls.SFBinaryData")
bd.Size = 8 ' We reserve 8 bytes for our purposes
bd.Unit(0,vbLong) = FileSize
' We will write this in the file first - see below
' Now open the output file
Set outfile = sf.CreateFile(Server.MapPath("encrypted-image.bin"))
' To make the encryption part of the file write operation we need to connect
' the SFStreamCrypt object with the output file and write through it. 
' Connect it
Set crypt.Stream = outfile
' In order to be able to write to the SFCryptStream we need to pack it into
' a SFStream object
Set outstream = Server.CreateObject("newObjects.utilctls.SFStream")
outstream.SetStream crypt
' Now write our binary data that contains the file size
outstream.WriteBin bd.Value
' And now read from the infile and write to the outfile through the stream chain
' For brevity we will transfer the whole file at once, usually this is done in small
' chunks in a cycle
outstream.WriteBin infile.ReadBin(infile.Size)
' Finalize the encryption - i.e. tell the SFStreamCrypt there will be no
' more data.
' Close everything

Notice the two lines in bold. They are the lines that construct the chain. The SFStreamCrypt object wont do anything if it is not connected to a stream object that actually controls some kind of a physical stream - file, network connection or something else. The part where we attach a SFStream to the SFStreamCrypt object is needed because we write to the created chain of stream filter and real stream from the script. If there was a component or an external application that can work with the standard IStream COM interface we could have omit that and pass the so configured object in the crypt variable to it and leave it to do the writing. Thus the stream filter may require some more coding but it enables you to offer to 3-d party components and applications a stream in which they can write (or read if the other direction is used) and thus make them perform encryption/decryption even if they do not support such feature. See details in the documentation (download NDL and see SFStreamCrypt in it)..

What about the hash and HMAC functions?

The interface to them is very similar to the programming interface for the symmetric cryptography algorithms. The difference is that the data is only inspected and the application uses the generated hash/HMAC. Again there are two kind of objects for that purpose - one providing direct access to the algorithms (HashObject) and one stream filter (SFStreamDigest). Like in the case with the symmetric algorithms they do the same but in different manner and again HashObject is the general purpose programming interface, while the SFStreamDigest is for applications that aim at isolation between their parts and providing added functionality transparently. All the same, the stream filter version does not worth to be used in simper scenarios, but can enable you to force modules, components or applications to generate hash/HMAC even if they do not support such feature.

Here we will illustrate only the HashObject which obviously will be more frequently used than the specialized stream filter programming interface version (SFStreamDigest - it is used much like the SFStreamCrypt - see details in NDL and the included examples). 

The simplest way to generate hash is like this:

Set h = CreateObject("newObjects.crypt.HashObject")
h.InitHash alg ' MD5, SHA1, SHA256 etc.
h.HashData somedata
digest = h.Value ' generated hash as hexdecimal
' Or if you want the generated hash as binary (VT_UI1 | VT_ARRAY)
digest = h.BinaryValue
' If you want to reuse it
' Then you can hash another data

Note that HashObject offers some flexibility about the data you pass to for processing. somedata in the above example can be a string or binary data whichever is more appropriate. Hash functions are very often used over text directly, most often over single byte encoded (even ASCII only) texts. To enable easy usage in such scenarios the HashData method has second optional parameter. If you pass a string variable as data argument you can specify the code page that must be used for conversion before the hash is generated. I.e. do not forget COM works internally always in UNICODE, when you pass a string to a function if you want it to be processed as ANSI text some code page must be used for the conversion. By default the default code page for system is used, but you can specify another. It is not customary practice to hash UNICODE texts, but this is also supported - if you specify code page -1. For example:

h.HashData sometext, 1251

Will hash sometext after converting it internally through the Windows Cyrillic code page.

What about HMAC? It is simple the same code with one more line will do the job:

Set h = CreateObject("newObjects.crypt.HashObject")
h.InitHash alg ' MD5, SHA1, SHA256 etc.
h.HashData somedata
h.Key = somekey
digest = h.Value ' generated hash as hexdecimal
' Or if you want the generated hash as binary (VT_UI1 | VT_ARRAY)
digest = h.BinaryValue
' If you want to reuse it
' Then you can hash another data

When bigger amounts of data must be processed it is not convenient to pass all the data in a single step. For that purpose instead of using the HashData method you can use the pair HashUpdate/HashFinalize methods which do the same but you can call HashUpdate many times to pass more and more data and finally call HashFinalize to end the process and obtain the digest of all the data you have put through the multiple calls to HashUpdate.


As we mentioned above the RSACrypt object from HashCryptStreams exposes the base algorithm and means to generate keys. From that point further the actual usage would differ depending on the standards or the custom requirements you must meet. A support for some PKCS standards will be added in the next versions.

The usage is as simple as:

Set rsa = CreateObject("newObjects.crypt.RSA")
rsa.PublicExp = pubkey_exp_part
rsa.Modulus = pubkey_modulus_part
cipher = rsa.Encrypt(data)

The other operations are as simple as this one and require only a few lines of code. The real trouble with RSA is how to embed it into your application. You need to decide what to encrypt with it, devise a format in which the data is prepared for encryption/decryption or choose a standard that defines such a format. If you are new to the public key cryptography the chapter About the Public Key algorithms in NDL will give you the principles not burdening you with the mathematics of the algorithm. Strangely on the WEB there are many and many articles about the algorithm itself, but only a few comment even partially the algorithm's general usage concepts. To fill the gap we placed that article in the documentation of the library - it describes why there must be standards or at least conventions about its usage, the features of the algorithm (and the similar ones) that naturally define its possible area of applications and usage patterns.


Q: Where is the documentation
A: In NDL. Download and install it. Lookup in the index the corresponding object (HashObject, Symmetric, RSA etc.) or go through the contents tree to the newObjects ActiveX Pack1/HashCryptStreams

Q: Does the library use the Windows CryptAPI
A: No, it is completely independent implementation, may be not the fastest available but available for all the Windows variants (desktop, CE/Pocket PC/Smartphone) in the same form with the same features everywhere. We may publish the extension API that would allow additional algorithms to be implemented by other vendors and accessed through the same programming interface. However the time will tell if there is a real need for this.

Q: How many and what kind of algorithms will be included in future versions
A: Only the most popular algorithms will be included in the DLL. Probably up to 5-6 more symmetric encryption algorithms and as many other hash functions. We have not decided yet about this but it is possible that we will include also some simple encoding algorithms (like Base64 for example) in this DLL in the form of symmetric algorithms without a key.

Q: How much it costs?
A: What you see in version 1.0 is freeware and will remain such. Some of the algorithms we will add later will require a license (one license will cover them all). Thus the same DLL would be possible to be used as freeware (With support for the part of the algorithms) when no license is available and with a license one will have more algorithms available. We will try to keep the freeware border at a level that enables most application build for the general public to cope without a license.

Q: Does the DLL depend on other modules?
A: No except for the stream filters (SFStreamCrypt and SFStreamDigest). If you want to use them from ASP/ALP, NSBasic or other environment on similar level you would need to drive them through the SFStream object. However this is about usage and not a requirement - the library will work alone, it would be just more convenient to have also the AXPack1 core components in order to simplify the related tasks you may need to perform. The included examples concentrate on this kind of usage, but most developers will not have trouble to use the library without the AXPack1 core if the size of the files redistributed with their application is crucial.

What to download

This page is an introduction and place for information about the HashCryptStreams.DLL. This library is part of our newObjects ActiveX Pack1 family (AXPack1) which we distribute as whole from 2003. Thus all the downloads by default contain all the AXPack1 binary files including HashCryptStreams.DLL. With the growth of the AXPack1 family it became a problem for the developers to gather all the needed files from different pages, thus we packed everything together. AXPack1 is a component library and while it includes an application that provides minimalistic programming environment (MicroScriptHost) it is mainly a library that is used by other applications. For example applications written in ALP, ASP, NSBasic, VB and virtually any other programming tool that has support for COM Automation. Thus the library reaches the end-user computers and devices as part of something else. The installable downloads are for developer's convenience in the first phases of the development when the application is not packed with an installer, for usage on WEB servers where the AXPack1 is used by ASP and other applications, for testing and performing administrative tasks in minimal but platform independent scripting environment and so on. These, installable downloads, cover only the most popular platforms on which AXPack1 is often needed and platforms on which programming is likely to be performed, everything else is supplied in raw form - the binary files in ZIP files.

The complete list of all the AXPack1 downloads is here.

Quick suggestions:

- If you are going to use AXPack1 on an IIS server download the PC only installable version and install it on the server machine.
- If you are going to develop for Pocket PC (regardless of the programming tool you are going to use) download the PC/Pocket PC combined download. After installing it on the PC you can invoke at any time installation to a Pocket PC device from the created start menu group.
- If your application will be packed with an installation in the end of its development gather the ZIP files containing binaries for the platforms on which the application will work and configure your installer to install the DLL-s from AXPack1 that you actually use. Get only the files you actually need - for instance it is very doubtful that you would want to use both SQLite COM and SQLite3 COM modules, thus include only the DB engine you have choosen.
- Want to play with scripting on some other device, smartphone, custom Windows CE device etc. Download the ZIP file with binaries for the device's OS version and processor type, copy then to the device (does not matter where - in a directory on a memory card for example). Then use a file manager you have on the device to start nwmicrohost.exe. From it you can register COM DLL manually without need of installer application - so register the DLL you are going to use and create some scripts. If you are not sure for the processor of the device get the most likely archives and try to start nwmicrohost.exe from each of them - the one that works is obviously for your platform (some devices come really bare-boned and it is not impossible to get a device with no means to find out what you have inside other than testing or opening it).

Copyright newObjects (ZmeY soft) 2001-2005