AES encryption in Perl 6? - raku

I'm trying to convert a module writing in Python to Perl 6, I find there is no AES method in Perl 6:
from Cryptodome.Cipher import AES
import base64
def aes(text, key):
pad = 16 - len(text) % 16
text = text + bytearray([pad] * pad)
encryptor = AES.new(key, 2, b"0102030405060708")
ciphertext = encryptor.encrypt(text)
return base64.b64encode(ciphertext)
Is there any module writing in Perl 6 that implemented AES method?

It seems that the OpenSSL module provides access to various AES ciphers. It depends on the openssl library being available (although on Windows I believe it downloads the DLL as part of the module installation process).
With that installed (zef install OpenSSL), one can:
use OpenSSL::CryptTools;
And then use encrypt/decrypt:
# Fake IV and key
my $iv = ('0' x 16).encode;
my $key = ('xy' x 16).encode;
# Encrypt.
my $ciphertext = encrypt("asdf".encode, :aes256, :$iv, :$key);
say $ciphertext;
# Decrypt.
say decrypt($ciphertext, :aes256, :$iv, :$key).decode;
See these tests for more examples.

Related

SHA-256 Hash and base64 encoding

With the string "123456Adrian Wapcaplet" I need to
generate the SHA-256 hash
take the least significant 128 bits of the hash
represent these bits in base64 encoding
I need help with #1 and #3. Below is how I generate this in Linux
$ echo -n "123456Adrian Wapcaplet" | shasum -a 256 | cut -c33-64 | xxd -r -p | base64
jNWe9TyaqmgxG3N2fgl15w==
Install the pgcrypto extension:
create extension pgcrypto;
Then you can use the digest function to do sha256. The rest of the functions you'll need are built in:
select encode(substring(digest('123456Adrian Wapcaplet', 'sha256') from 17), 'base64');
Note that there's an implicit cast from text to bytea performed here when calling digest. It will use the default encoding for the database. To avoid problems due to environmental differences you can specify the encoding for the conversion:
digest(convert_to('123456Adrian Wapcaplet', 'utf8'), 'sha256')

How can I calculate the same SSH fingerprint as Putty displays?

When first connecting to a new SSH host in Putty it displays a message asking me to verify the RSA fingerprint:
When viewing this same information on the network (e.g. through Wireshark), the same value is not shown, instead is shown as:
How can I calculate the fingerprint from the information shown in the Packet Capture?
The value shown in wireshark is the full public key from the server. The fingerprint (MD5 Hash value) of this value is shown to the user in putty as it's much easier (shorter) to read that expecting the user to match up the entire key.
To calculate the public key fingerprint it is necessary to first convert the hex stream given by Wireshark to the the byte stream equivilent then to calculate the MD5 hash from this and output in hexadecimal format.
A crude implementation of this in python is below which will take the wireshark value (HEX DH host Key copied as a HEX Stream) on STDIN and output the fingerprint on STDOUT:
import md5
import sys
# Accepts a wireshark encoded string on STDIN an outputs MD5 fingerprint to STDOUT
# The value copied from the 'HEX DH host Key' as a HEX Stream
wireshark_key = sys.stdin.readline()
# Change the HEX value into the raw byte stream, which will include non-printable characters
hex_string = wireshark_key.strip().decode("hex")
# Calculate the MD5 Hash of the byte stream and output in Hexidecimal format
md5_fingerprint = md5.new(hex_string).hexdigest()
# Tidy up the output so it matches what Putty displays
putty_fingerprint = ":".join([md5_fingerprint[i:i+2] for i in range(0, len(md5_fingerprint), 2)])
print(putty_fingerprint)
To run this, save the wireshark value (public key) to a file and then execute:
cat <key.txt> | python scriptname.py
The output should then match what is displayed by Putty on first connect as well as in the Event Log.
The following web pages were very useful in figured this all out:
http://passionateaboutis.blogspot.co.uk/2015/07/ssh-fingerprint-from-pcap.html
https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Public_Key_Authentication
Whilst this script may be useful for one off cases, if you need to obtain fingerprints for a large number of hosts, nmap and one of it's NSE scripts may be more efficient:
https://nmap.org/nsedoc/scripts/ssh-hostkey.html
Saving the output from NMAP to XML will automatically store the calculated fingerprint for all hsots.

Generating RSA public key on linux, converting to base64, and importing into VB.NET

I would like to hardcode a string into a VB.NET program containing the base64 String representation of an RSA public key I generate on a linux computer.
On the linux box:
I use ssh-keygen to generate the keypair
I use PHP to convert .ssh/id_rsa.pub to base64 using base64_encode()
In the VB Code, I hardcode the output I generated above into a string variable:
Dim publicKey As String = "QUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQTRrNHNPOFhyajhJUkM4WGhEMVJQYlhJbUROTnVwdEpvUEtYNzNhcHc1M0NFUGE3VVNRY0U2SXhyNENWM2FhVXBtR1Fsb1I4akNLVkNoUnhzOUVnT3JQcVNGMTFjL3ZPNzluMXdkU1VWZjhreC9uY1NiV25UUXBtb1paNlN5ZUM3ekhMbWh1Z0o5OWdsVjB3bXBhTXpPeitHa0JBeFBPYlV0MzFYalMxMlBzM0ZUZFBla2s5T0ptMFJxc1plM3krbHU2UURZbDEyejJyTU9lbFhJS2IxSUZ1SnF6SThqL2Y4Q3V2dGxCSmxhelRBWlkyekF1WTZWMXU4c2JnUmE2MTBxMzM3dUdMODErbytCUkRzS0dwN0xBRmRwM1R2ekE3MDZPeFVSSEF0YmRZOVkzaXFISFFzQ3ZQWXBqcVQ0MHVlZ1RHY05jd2JCdjZxa2xlckk2K25Ndz09"
Dim myRsa As New RSACryptoServiceProvider()
myRsa.ImportCspBlob(Convert.FromBase64String(publicKey))
I get a runtime exception about "bad version of provider"
Here's how I'd convert it (using phpseclib, a pure PHP RSA implementation):
<?php
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->loadKey(base64_decode('QUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQTRrNHNPOFhyajhJUkM4WGhEMVJQYlhJbUROTnVwdEpvUEtYNzNhcHc1M0NFUGE3VVNRY0U2SXhyNENWM2FhVXBtR1Fsb1I4akNLVkNoUnhzOUVnT3JQcVNGMTFjL3ZPNzluMXdkU1VWZjhreC9uY1NiV25UUXBtb1paNlN5ZUM3ekhMbWh1Z0o5OWdsVjB3bXBhTXpPeitHa0JBeFBPYlV0MzFYalMxMlBzM0ZUZFBla2s5T0ptMFJxc1plM3krbHU2UURZbDEyejJyTU9lbFhJS2IxSUZ1SnF6SThqL2Y4Q3V2dGxCSmxhelRBWlkyekF1WTZWMXU4c2JnUmE2MTBxMzM3dUdMODErbytCUkRzS0dwN0xBRmRwM1R2ekE3MDZPeFVSSEF0YmRZOVkzaXFISFFzQ3ZQWXBqcVQ0MHVlZ1RHY05jd2JCdjZxa2xlckk2K25Ndz09'));
$rsa->setPublicKey();
$publickey = $rsa->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_XML);
echo $publickey;

GnuPG 4096 bit limit

Why is RSA keys in GnuPG limited to 4096 bits?
Would it be illegal for me to modify the source to increase the max size?
ssh-keygen does not have this limitation (e.g., I can create a key that's 32768 bits long). Why is that?
At keylength.com there is this:-
To protect a 256-bit symmetric key (e.g. AES-256), you may consider using at the minimum a 17120-bit asymmetric system (e.g. RSA).
The 4096 bit limit can be raised as described in a short article entitled "Generate large keys with GnuPG", reproduced below. This was done for the gnupg package in homebrew to allow for 8192 bit keys: PR 4201. A word of caution about memory allocation for the larger keys: comp.security.pgp.tech.
Generate large keys with GnuPG | David Norman
If you'd like to generate larger keys than 4096 bits with GnuPG, you can compile
a new version that increases the upper limit of 4096. You'll probably find
yourself generating it as RSA. Download the patch to your un-tared gnupg-1.4.19
directory and apply it with:
usbdrive#sandisk-extreme64:~/gnupg-1.4.19$ patch -p0 < gnupg_1.4.19_large_keygen.patch
patching file g10/keygen.c
usbdrive#sandisk-extreme64:~/gnupg-1.4.19$ ./configure --enable-large-secmem
[...]
checking whether to allocate extra secure memory... yes
[...]
usbdrive#sandisk-extreme64:~/gnupg-1.4.19$ make -j2
usbdrive#sandisk-extreme64:~/gnupg-1.4.19$ make check
usbdrive#sandisk-extreme64:~/gnupg-1.4.19$ sudo make install
usbdrive#sandisk-extreme64:~/gnupg-1.4.19$ gpg --gen-key --enable-large-rsa
Without the --enable-large-rsa flag, the key generation process will
automatically downgrade the key to 4096.
To compile on a Mac, you'll need to download Xcode from the App Store first. The
patch increases the upper limit of the key size to 15489 bits. Without
increasing the secure memory limit, generating a key larger than about 7680-bits
will fail because it won't be able to allocate enough memory to the process.
Generating keys larger than around 7680-bits (192-bit symmetric equivalent) can
also make it impossible to decrypt messages with standard secure memory limits
set at compile time because the gpg binary won't be able to allocate enough
secure memory to decrypt the message, even small ones.
gnupg_1.4.19_xlarge_key_gen.patch
--- g10/keygen.c 2015-02-26 12:24:21.000000000 -0500
+++ g10/keygen.c 2015-03-02 22:12:09.028419377 -0500
## -1041,8 +1041,9 ##
nbits = 2048;
log_info(_("keysize invalid; using %u bits\n"), nbits );
}
- else if (nbits > 4096) {
- nbits = 4096;
+ else if (nbits > 15489) {
+ /* fallback to RFC3766 256-bit symmetric equivalency */
+ nbits = 15489;
log_info(_("keysize invalid; using %u bits\n"), nbits );
}
## -1251,7 +1252,8 ##
PKT_public_key *pk;
MPI skey[6];
MPI *factors;
- const unsigned maxsize = (opt.flags.large_rsa ? 8192 : 4096);
+ /* New large key limit RFC3766 256-bit symmetric equivalency */
+ const unsigned maxsize = (opt.flags.large_rsa ? 15489 : 4096);
assert( is_RSA(algo) );
## -1578,7 +1580,7 ##
static unsigned int
ask_keysize (int algo, unsigned int primary_keysize)
{
- unsigned nbits, min, def=2048, max=4096;
+ unsigned nbits, min, def=2048, max=15489;
int for_subkey = !!primary_keysize;
int autocomp = 0;
gnupg_1.4.19_xlarge_secmem.patch
--- configure 2015-02-27 03:37:52.000000000 -0500
+++ configure 2015-03-02 22:28:31.488401783 -0500
## -5076,7 +5076,7 ##
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $large_secmem" >&5
$as_echo "$large_secmem" >&6; }
if test "$large_secmem" = yes ; then
- SECMEM_BUFFER_SIZE=65536
+ SECMEM_BUFFER_SIZE=131072
else
SECMEM_BUFFER_SIZE=32768
fi
Article ends. Retrieved on 2016-02-26 from an archived copy of the original.
There is pretty sensible explanation (for similar question) by Fire Ant at Security Forums:
http://www.security-forums.com/viewtopic.php?p=317962#317962
All rights reserved there, but fair use citation of short excerpt shouldn't be inappropriate methinks:
Key sizes over 4096 are not currently supported in GPG. The reason for this is that 8192 keys are very slow. If you require a key greater than 4096-bit then you should really thing about what you are using that key for?
Why does it not support anything larger? Perhaps at the time of development of GnuPG (and the continued development of RSA for that matter) and the key sizes, computing limits at the time,both for the client side use cases and the potential of government agencies being able to break a 4096 key, developers and cryptographers felt a 4096 key was large enough. Really, 4096 is a really large key and would take a very long time to break with current technology. If a government agency was after you and really wanted to get your messages they would (in the US) get a court order to put a rootkit on your machines to not even worry about breaking encryption.
Now, I haven't looked at the source code specifically, but if you change the key size to anything larger than 4096, you might have problems with other users using your key if their software doesn't support a larger key size. For example, I have a 4096 key, a friend of mine cannot send me messages from an Android device because he cannot find an application that supports anything larger than 3072! Keep that in mind.
If you want to modify the source code, you can do so easily on Debian Linux with this script:
Raising GnuPG key size limits and making ideal .conf files.
Here is a link to a bash script that increases the GnuPG key size limit beyond 4096 bits. The page also provides an ideal GnuPG .conf file.
https://gist.github.com/anonymous/3d928a0bcbb3ed92c454
Please provide input and recommended changes.

Does the openssl command line do key strengthening?

If I run the openssl command line in hmac mode (as below), is the key used for the hmac used directly or is it hashed before using it as the key?
echo "foo" | openssl dgst -sha256 -binary -hmac "test" | openssl base64
Similarly, when encrypting a file with openssl (as below)is the pass phrase hashed with the salt? (If so how is it done? A pointer to the right source file would be even better.)
openssl enc -salt
The hmac option does not use salting or hashing; it just uses the passphrase directly as the key. See apps/dgst.c in the source distribution:
else if (!strcmp(*argv,"-hmac"))
{
if (--argc < 1)
break;
hmac_key=*++argv;
}
...
if (hmac_key)
{
sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
(unsigned char *)hmac_key, -1);
if (!sigkey)
goto end;
}
The enc command does seem to use some form of salting, at least in some cases. The relevant source file is apps/enc.c, but seems to come with some caveats:
/* Note that str is NULL if a key was passed on the command
* line, so we get no salt in that case. Is this a bug?
*/
if (str != NULL)
{
/* Salt handling: if encrypting generate a salt and
* write to output BIO. If decrypting read salt from
* input BIO.
*/
It then uses the function EVP_BytesToKey (in crypto/evp/evp_key.c) to generate a random key. This function seems to be a non-standard algorithm, which looked perhaps plausibly OK at a very brief glance but I couldn't attest to it beyond that.
Source snippets and comments are all from the OpenSSL 1.0.0 release.