# CRYPTO Examples > [HTML Version](cryptoexamples.htm) **Example 1: Symmetric key generation** Here we generate two 128 bit keys, returning the first one in a hex string format, and writing the other in raw binary format to a file. Note in both cases we are using the _dst_ parameter (and not the _key_ parameter) for the returned key. The _src_, _decoding_, _cipher_, and _key_ parameters aren't used. Also note that although hex format for binary keys is convenient for string handling and printing purposes, handling it directly in an X variable would be the most compact (and would also eliminate the possibility of it being accidentally exposed in a subroutine trace). \++include ashinc:crypto.def map1 keybits,b,2,128 \! 128 bit key length map1 hexkey\$,s,32 \! 128 bits = 16 bytes (32 hex chars) map1 status,f \! return status \! return hex key directly in hexkey\$ (dst) param: xcall CRYPTO, CRYPTOP\_GENKEY, status, "", "", hexkey\$, "hex", \& CRYPF\_NONE, CRYPTO\_CIPHER\_NA,"", keybits if status = 32 then \! (expecting 32 hex characters) print "key (in hex format):";hexkey\$ else print "Error: ";status endif \! now generate another, writing it in binary format to file xcall CRYPTO, CRYPTOP\_GENKEY, status, "", "", "testkey.bin", "", \& CRYPF\_DSTFILE, CRYPTO\_CIPHER\_NA, "", keybits if status = 16 then \! (expecting 16 bytes) print "key written to testkey.bin" else print "Error: ";status endif Note: CRYPTOP\_GENKEY provides the same functionality as the openssl rand utility. In fact, the second example (above) is directly equivalent to: openssl rand 16 > test.key **Example 2: Encrypt/decrypt a string using AES-128-ECB** Here we generate a new random key (in raw binary format) and use it to encrypt a string, which is then encoded in base64. (This is a typical approach to encrypting sensitive fields within an XML web service request.) Error checking has been removed to simplify the example. \++include ashinc:crypto.def map1 keybits,b,2,128 \! 128 bit key map1 symkey,x,16 \! raw symmetric key (128 bits = 16 bytes) map1 src\$,s,50 \! plain text string to encrypt map1 enc\$,s,90 \! encrypted/encoded output map1 dec\$,s,50 \! decrypted string (to test decryption) map1 status,f \! return status \! generate key into key var xcall CRYPTO, CRYPTOP\_GENKEY, status, "", "", symkey, "", \& CRYPF\_NONE, CRYPTO\_CIPHER\_NA,"", keybits \! now use it to encrypt the src\$ src\$ = "This is a secret" xcall CRYPTO, CRYPTOP\_ENCRYPT, status, src\$, "", enc\$, "base64", \& CRYPF\_SRCTEXT, CRYPTO\_CIPHER\_AES,symkey, keybits, CRYPTO\_MODE\_ECB, CRYPTO\_PAD\_PKCS5 print "status=";status;" cipher text = ";enc\$ \! now decrypt it to see if we get the original back \! (we'll use out of the encryption as the input of the decryption) xcall CRYPTO, CRYPTOP\_DECRYPT, status, enc\$, "base64", dec\$, "", \& CRYPF\_SRCTEXT, CRYPTO\_CIPHER\_AES, symkey, keybits, CRYPTO\_MODE\_ECB, CRYPTO\_PAD\_PKCS5 if dec\$ = src\$ then print "Success: decrypted string matches original\!" else print "Error: decrypted string doesn't match original\!" endif Note that the _dst_ parameter here must be large enough to hold the encrypted/encoded message. For block ciphers like AES, the raw encrypted message length will be rounded up to the next multiple of the block (key) size, so for a 50 byte source, the encrypted version could be 64 bytes long. The base64 encoding will increase it further by a ratio of 4/3 (rounded up to next multiple of 4), so we would need 88 bytes to be safe. You can use a dynamic string output variable, but you must pre-initialize it to at least the minimum required size (if in doubt, err on the high side\!). **Example 3: Encrypt/decrypt a file using AES-128-ECB** This is similar to Example 2 except that we'll use files for the source and destination, and a hex string variable for the key. This will be equivalent to the following openssl command strin1g: "openssl enc -aes-128-ecb -in msg.dat -out msg.enc -a -e -nosalt -K " + hexkey\$ \++include ashinc:crypto.def map1 keybits,b,2,128 \! 128 bit key map1 hexkey\$,s,32 \! hex encoded key map1 status,f \! return status map1 src\$,s,50 \! source filespec map1 dst\$,s,50 \! dest filespec map1 decoding\$,s,10 \! source file decoding map1 encoding\$,s,10 \! dest file encoding map1 cflags,b,4 \! generate 128 bit key in hex format xcall CRYPTO, CRYPTOP\_GENKEY, status, "", "", hexkey\$, "hex", CRYPF\_NONE, CRYPTO\_CIPHER\_NA,"", keybits src\$ = "msg.dat" decoding\$ = "" \! no decoding of source (treat as raw) dst\$ = "msg.enc" encoding\$ = "base64" \! encode the dest after encryption cflags = CRYPF\_KEYHEX \! key is in hex format cflags = cflags or CRYPF\_SRCFILE \! source is a file cflags = cflags or CRYPF\_DSTFILE \! destination is a file ? "encrypting ";src\$;" into ";dst\$;" ..." xcall CRYPTO, CRYPTOP\_ENCRYPT, status, src\$, decoding\$, dst\$, encoding\$, \& cflags, CRYPTO\_CIPHER\_AES, hexkey\$, keybits, CRYPTO\_MODE\_ECB, CRYPTO\_PAD\_PKCS5 if status >= 0 then print status;" bytes output to ";dst\$ else print "error: ";status end endif \! now decrypt it into msg.dec (which should match the original msg.dat) src\$ = "msg.enc" \! source for decryption is the encrypted file decoding\$ = "base64" \! pre-decode encrypted file before decryption dst\$ = "msg.dec" \! decrypted file encoding\$ = "" \! no post-decryption encoding ? "decrypting ";src\$;" into ";dst\$; " ..." xcall CRYPTO, CRYPTOP\_DECRYPT, status, src\$, decoding\$, dst\$, encoding\$, \& cflags, CRYPTO\_CIPHER\_AES, hexkey\$, keybits, CRYPTO\_MODE\_ECB, CRYPTO\_PAD\_PKCS5 if status >= 0 then print "Decrypted file (";dst\$;") should now match original" else print "error: ";status endif Note that in this case, it isn't necessary to specify whether the files contain text or binary data. (Treating it as binary is always safe.) Also note that for the decryption, the decoding option must match the encoding for the encryption. (We base64-encoded the encrypted file; so we need to first base64-decode it before decrypting.) **Example 4: RSA encrypt/decrypt a string** Here we RSA-encrypt the 16 byte raw symmetric key (generated in Example 2), using a public key stored in the file testpub.pem. This is similar to the openssl rsautl command sequence: echo \$KEY | openssl rsautl -encrypt -inkey tetpub.pem -pubin | openssl enc -base64 Note that the source for this operation may itself be a key (e.g. the symmetric key used to encrypt something else that we want to transmit secretly to the remote side), but from the perspective of the RSA encryption operation, it's just an arbitrary message to encrypt. This technique would apply to RSA public/private key encryption of any message, provided it is no longer than the RSA modulus (typically either 1024 or 2048 bits, i.e. 128/256 bytes). \++include ashinc:crypto.def map1 symkey,x,16 \! raw 128 bit symmetric key (generated in Example 2) map1 symkey2,x,16 \! (to test decryption) map1 status,f \! return status map1 dst\$,s,346 \! dest string map1 keyfile\$,s,30 \! PEM file (public or private key) map1 cflags,b,4 cflags = CRYPF\_KEYFILE \! key is a file (cryptopub.pem) cflags = cflags or CRYPF\_PUBKEY \! use the public key keyfile\$ = "testpub.pem" \! public key file if lookup(keyfile\$)= 0 then print keyfile\$;" not found\! See doc notes to create" end endif xcall CRYPTO, CRYPTOP\_ENCRYPT, status, symkey, "", dst\$, "base64", \& cflags, CRYPTO\_CIPHER\_RSA, keyfile\$ if status >= 0 print "Encryption success: ";status;" encrypted/encoded bytes output" else print "Encryption error: status=";status end endif \! now decrypt it into rawkey2 (which should match the original msg.dat) \! (this would normally be done by the remote counterpart) cflags = cflags and not CRYPF\_PUBKEY \! clear PUB flag (we're using private key here) keyfile\$ = "test.pem" \! private key file xcall CRYPTO, CRYPTOP\_DECRYPT, status, dst\$, "base64", symkey2, "", \& cflags, CRYPTO\_CIPHER\_RSA, keyfile\$ if status >= 0 and symkey = symkey2 then print "Decryption success: decrypted symkey matches the original" else print "Decryption error: status=";status endif Notes: • The size of the encrypted output for RSA encryption is always the same as the RSA modulus (1024 or 2048 bits), adjusted for the encoding. In this case, since base64 encoding expands the message by 4/3, we need at least 256 \* 4/3 bytes (rounded up to next multiple of 4) or 344 bytes to hold the output. We mapped dst\$ as 346 here to allow for a trailing null and even size. • The keybits parameter is not used with the RSA cipher • You can generate the test.pem (private key) and testpub.pem (public key) files for this example using openssl as follows: openssl genrsa -out test.pem 2048 openssl rsa -in test.pem -pubout > testpub.pem **Example 5: Encode binary data** Here we encode 16 bytes of binary data as a 32 byte hex string: \++include ashinc:crypto.def map1 xdata map2 xdata'bytes(16),b,1 map1 hexdata\$,s,32 \! hex encoded key (from example 1) map1 status,f \! return status map1 x,f for x = 1 to 16 \! generate 16 binary bytes xdata'bytes(x) = x next x \! encode it in hex xcall CRYPTO, CRYPTOP\_ENCODE, status, xdata, "", hexdata\$, "hex", CRYPF\_NONE ? "hex encoded bytes: ";hexdata\$