What are the key schemes, sizes, and encodings used in GUN db?
I didn't find a quick answer on searching so am adding the question here.
The keys look like:
let lee = await SEA.pair()
>lee.pub
"wfcQUDB44NhKFikH4NhWKVZfhQY-xGRpwnZIHjgmwRI.xLxhMgWvgvYHCc95L6Ni2RLmjJCMowWNbR3eQ1r4MOU"
For Signing/Verifying:
Gun uses ECDSA with the P-256 curve.
The keys are encoded in base64.
More specifically, the public key is a . delineated concatenation of the x and y output parameters from running exportKey on a JSON web key (JWK) CryptoKeyPair object obtained from the subtleCrypto.exportKey function (following key generation using subtleCrypto.generateKey with ECDSA P256 curve).
This has an overview of the x and y params.
For Encryption/Decryption:
Gun uses ECDH P-256 cruve with same process as above (public keys stored as lee.epub for OP example)
Related
I've generated a random 256 bit symmetric key, in a file, to use for encrypting some data using the OpenSSL command line which I need to decrypt later programmatically using the OpenSSL library. I'm not having success, and I think the problem might be in the initialization vector I'm using (or not using).
I encrypt the data using this command:
/usr/bin/openssl enc -aes-256-cbc -salt -in input_filename -out output_filename -pass file:keyfile
I'm using the following call to initialize the decrypting of the data:
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
keyfile is a vector<unsigned char> that holds the 32 bytes of the key. My question is regarding that last parameter. It's supposed to be an initialization vector to the cipher algorithm. I didn't specify an IV when encrypting, so some default must have been used.
Does passing nullptr for that parameter mean "use the default"? Is the default null, and nothing is added to the first cipher block?
I should mention that I'm able to decrypt from the command line without supplying an IV.
What is the default IV when encrypting with EVP_aes_256_cbc() [sic] cipher...
Does passing nullptr for that parameter mean "use the default"? Is the default null, and nothing is added to the first cipher block?
There is none. You have to supply it. For completeness, the IV should be non-predictable.
Non-Predictable is slightly different than both Unique and Random. For example, SSLv3 used to use the last block of ciphertext for the next block's IV. It was Unique, but it was neither Random nor Non-Predictable, and it made SSLv3 vulnerable to chosen plaintext attacks.
Other libraries do clever things like provide a null vector (a string of 0's). Their attackers thank them for it. Also see Why is using a Non-Random IV with CBC Mode a vulnerability? on Stack Overflow and Is AES in CBC mode secure if a known and/or fixed IV is used? on Crypto.SE.
/usr/bin/openssl enc -aes-256-cbc...
I should mention that I'm able to decrypt from the command line without supplying an IV.
OpenSSL uses an internal mashup/key derivation function which takes the password, and derives a key and iv. Its called EVP_BytesToKey, and you can read about it in the man pages. The man pages also say:
If the total key and IV length is less than the digest length and MD5 is used then the derivation algorithm is compatible with PKCS#5 v1.5 otherwise a non standard extension is used to derive the extra data.
There are plenty of examples of EVP_BytesToKey once you know what to look for. Openssl password to key is one in C. How to decrypt file in Java encrypted with openssl command using AES in one in Java.
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
I didn't specify an IV when encrypting, so some default must have been used.
Check your return values. A call should have failed somewhere along the path. Maybe not at EVP_DecryptInit_ex, but surely before EVP_DecryptFinal.
If its not failing, then please file a bug report.
EVP_DecryptInit_ex is an interface to the AES decryption primitive. That is just one piece of what you need to decrypt the OpenSSL encryption format. The OpenSSL encryption format is not well documented, but you can work it backwards from the code and some of the docs. The key and IV computation is explained in the EVP_BytesToKey documentation:
The key and IV is derived by concatenating D_1, D_2, etc until enough
data is available for the key and IV. D_i is defined as:
D_i = HASH^count(D_(i-1) || data || salt)
where || denotes concatentaion, D_0 is empty, HASH is the digest
algorithm in use, HASH^1(data) is simply HASH(data), HASH^2(data) is
HASH(HASH(data)) and so on.
The initial bytes are used for the key and the subsequent bytes for the
IV.
"HASH" here is MD5. In practice, this means you compute hashes like this:
Hash0 = ''
Hash1 = MD5(Hash0 + Password + Salt)
Hash2 = MD5(Hash1 + Password + Salt)
Hash3 = MD5(Hash2 + Password + Salt)
...
Then you pull of the bytes you need for the key, and then pull the bytes you need for the IV. For AES-128 that means Hash1 is the key and Hash2 is the IV. For AES-256, the key is Hash1+Hash2 (concatenated, not added) and Hash3 is the IV.
You need to strip off the leading Salted___ header, then use the salt to compute the key and IV. Then you'll have the pieces to feed into EVP_DecryptInit_ex.
Since you're doing this in C++, though, you can probably just dig through the enc code and reuse it (after verifying its license is compatible with your use).
Note that the OpenSSL IV is randomly generated, since it's the output of a hashing process involving a random salt. The security of the first block doesn't depend on the IV being random per se; it just requires that a particular IV+Key pair never be repeated. The OpenSSL process ensures that as long as the random salt is never repeated.
It is possible that using MD5 this way entangles the key and IV in a way that leaks information, but I've never seen an analysis that claims that. If you have to use the OpenSSL format, I wouldn't have any hesitations over its IV generation. The big problems with the OpenSSL format is that it's fast to brute force (4 rounds of MD5 is not enough stretching) and it lacks any authentication.
I have searched and found examples of AES with the default 256 key size and find it worked already. But when I want to use 128 key size, there is little information.
I have extracted code from the aes test from CryptoJS:
var C = CryptoJS;
var plainText = '00112233445566778899aabbccddeeff';
var key = '000102030405060708090a0b0c0d0e0f';
var encryptedText = C.AES.encrypt(C.enc.Hex.parse(plainText), C.enc.Hex.parse(key), { mode: C.mode.ECB, padding: C.pad.NoPadding }).ciphertext.toString();
console.log(encryptedText);
var decryptedText = C.AES.decrypt(C.lib.CipherParams.create({ ciphertext: C.enc.Hex.parse(encryptedText) }), C.enc.Hex.parse(key), { mode: C.mode.ECB, padding: C.pad.NoPadding }).toString();
console.log(decryptedText);
This worked, but if I want to use a different plain text like 'Hello World' then it failed. Also what if I want to use a password like 'my-key-001'? As I have read that CryptoJS expect to use 256 key size if I pass a password.
Your help is much appreciated.
This worked, but if I want to use a different plain text like 'Hello World' then it failed.
You have used the noPadding and that is the issue. The example is multiple of 16-byte that causes no problem, however your next plaintext is not. You can use noPadding if
your message is an exact multiple of the block size, though still not recommended.
you want to pad the message yourself, probably that is you want to test a new padding scheme that we don't see in your code.
You should you padding like
padding: CryptoJS.pad.Pkcs7
As I have read that CryptoJS expect to use 256 key size if I pass a password.
CryptoJS supports AES-128, AES-192, and AES-256. According to your key size it will select the key variants. If you use a password it will generate a 256-bit size. That is %40 times slower than AES-128 since it requires 14 rounds. However use a good password, see below.
Also what if I want to use a password like 'my-key-001'?
A password with high entropy is important otherwise the attackers can be successful by testing passwords. The key generation cannot increase entropy. Therefore you need a good way to generate high entropy passwords like using diceware.
How to encrypt in AES using CryptoJS with key size of 128?
Just provide a 128-bit key.
Does AES-128 has 128-bit security
Any block cipher, not only AES, has vulnerable to multi-target attacks. In that case it is not providing 128-bit security. Therefore you should use 192 or 256-bit keys.
For a more detailed see this question Has AES-128 been fully broken?
mode: C.mode.ECB
The ECB mode of operations is not advised, it is insecure and it leaks pattern. You should use modern encryption modes like AES-GCM which provides you not confidentiality but also, integrity and authentication.
While using GCM mode, make sure that you never use the same IV/nonce again under the same key. AES-GCM uses CTR mode for encryption and under the same key if the IV/nonce repeated then crig-dragging is possible. Also, it can leak the authentication key.
SAP servers are capable of encrypting and hashing data. But there doesn't appear to be a suitable API to call. SAP Note 1456433 talks about the class CL_SEC_SXML_XENCRYPTION. The signature of basic encryption is clearly geared towards SSF and unsuitable to basic private key encryption/decryption. I don't want/need envelopes and user certificates. Just private keys.
I found an AES library on GitHub AES library in ABAP and tweaked that to suit us. But it is very slow. I would like to use the encryption libraries SAP has. Clearly, the libraries are there but find a suitably exposed API seems the issue.
Does anybody know how to use basic encryption in SAP?
In SAP ABAP stack, using ABAP.
Eg (a call to use AES-CBC 128, with PKCS7 padding
where only a private key and data to encrypt is required. As example:
public static method encrypt_xstring
importing i_key type xstring
i_data type xstring
i_initialization_vector type xstring optional
i_padding_standard type char10 optional
i_encryption_mode type char10 optional
exporting e_data type xstring
Use case is encrypting data on clients with a private key and sending the data to SAP system. The source supports private keys and libraries like AES-CBC.
And we have encrypted data interchange working.
Next step is to use a supported and faster library.
EDIT: In case anyone needs to encryption / decryption properly in abap
And is looking at the answer. Use class CL_SEC_SXML_WRITER.
CL_SEC_SXML_WRITER was exactly what i was looking for
BUT SAP didnt expose it properly. It is only useful for encryption no decryption.
When interacting with external libraries. Where PKCS7 padding is used and SALTs
or Initialization vectors are required.
SAP offer an ENCRYPT_IV but no Decrypt_IV. Why ????
So you cant use the tool and remain compliant. :(
It is not considered safe to use AES-CBC without IV.
Why would SAP do that ?
ENCRYPT_IV instead of ENCRYPT but no DECRYPT_IV
The offer an Add Padding but no remove padding. OK roll your own padding removal, no big deal. Its like the must be another library for the other direction.
So i can use the tool to encrypt but not decrypt.
My main problem was decrypting quickly strings sent from a mobile device.
So still need to use the old ABAP code for that :(
I have similar requirements and I found the cl_sec_sxml_writer class. Please have a look at the following example. Note that the writer requires XSTRING parameters which is why I'm using conversion classes.
REPORT zged_aes.
DATA lv_message_string TYPE string.
" create message
DATA(lr_conv_sec) = cl_abap_conv_out_ce=>create( ).
lr_conv_sec->write( data = 'This is my secret' ).
" create key
DATA(lr_conv_key) = cl_abap_conv_out_ce=>create( ).
lr_conv_key->write( data = 'MySymmetricKey' ).
" encrypt using AES256
cl_sec_sxml_writer=>encrypt(
EXPORTING
plaintext = lr_conv_sec->get_buffer( )
key = lr_conv_key->get_buffer( )
algorithm = cl_sec_sxml_writer=>co_aes256_algorithm_pem
IMPORTING
ciphertext = DATA(lv_message) ).
" decrypt message
cl_sec_sxml_writer=>decrypt(
EXPORTING
ciphertext = lv_message
key = lr_conv_key->get_buffer( )
algorithm = cl_sec_sxml_writer=>co_aes256_algorithm_pem
IMPORTING
plaintext = DATA(lv_message_decrypted) ).
" convert xstring to string for output
cl_abap_conv_in_ce=>create( input = lv_message_decrypted)->read( IMPORTING data = lv_message_string ).
" output secret message
WRITE lv_message_string.
I tested it on a NetWeaver 7.50 SP 6 system.
I got the ENCRYPT_IV method to work alongside method DECRYPT of class CL_SEC_SXML_WRITER.
The caveat here is that I didn't generate the Symmetric Key and IV by making use of Class cl_abap_conv_out_ce.
I already had my keys and IV from a Java implementation test.
The only thing I needed was to create the Key and IV as an XSTRING and initializing them with the Hex format of my Java implementation (they were in Byte format.
Because of this, I first converted them to Hex and passed those values to the ABAP Xstring types).
When you execute
ssh-keygen -t ssh-dss
it generates two files: one containing the public and the other, the private key.
The ssh-keygen man-page says it always generates a 1024bit key, but when I open the public key file, I always get a 580 characters line (which would be
4640 bits in ASCII).
Am I missing something or thinking about it wrong? I've tried reading the algorithm, but it's very hard to calculate, considering the size of the prime numbers involved.
Is there a way I can validate if it's a 1024bit key from the quantity of characters in the id_dsa.pub file?
The files where ssh-keygen stores the public and private keys have some predefined format (PEM, ...), they are not a dump of the keys itself (remember, by example, that private key will be usually encrypted).
In this link (https://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html) you will find some good explanations about the different formats, and usage of tools like "openssl asn1parse" to display them:
The private key is an ASN.1 data structure, serialized to a byte string using DER, and then Base64-encoded. ASN.1 is roughly comparable to JSON (it supports various data types such as integers, booleans, strings and lists/sequences that can be nested in a tree structure). It’s very widely used for cryptographic purposes, but it has somehow fallen out of fashion with the web generation (I don’t know why, it seems like a pretty decent format).
A method to find the public key size is look in the ASN1 for the tag that stores it and verify the length of its data.
I have a client who is implementing ZNode which uses the aspnet_Membership table to store a password. This table contains an encrypted password, the password salt and is using the "PasswordFormat" of 2. From what I gather, "2" is a recoverable encrypted password.
The ColdFusion server is BlueDragon 9 Alpha. If you don't know BD, no worries, anything that ColdFusion supports "should" work and I have CF 10 to test it on as well.
If you know a better way to do this I'm all ears. I need to be able to create a user/password and store it in the ASP membership table via ColdFusion. In addition I need to be able to check the user/password for login.
When looking at the Web.config file, the ZnodeMembershipProvider is a "System.Web.Security.SqlMembershipProvider" type.
The machineKey entry looks like this: (took out the two key values)
<machineKey decryption="AES"
decryptionKey="[64 character string]"
validation="SHA1"
validationKey="[128 character string]"/>
If I try something like this:
Encrypt('myPassword', '[64 character string]', 'AES', 'Base64')
It says "Specified key is not a valid size for this algorithm."
I'm not very savy on encryption or .NET. Thanks in advance.
I believe that .NET Password tables use Triple-DES, not AES. Try this instead.
Encrypt('myPassword', '[64 character string]', '3DES', 'Base64')
This answer I wrote up, about DNN (Dot Net Nuke) authentication, should do the trick. (Assuming no differences between ACF and BD). Essentially there are few difference in how .NET and CF handle encryption. The primary differences are:
Encoding:
.NET uses UTF-16LE
CF always uses UTF-8. In ACF, this means you must use encryptBinary instead of encrypt. (I am not sure about OBD).
Key Format:
.NET uses hexadecimal
CF typically uses base64, so you may need to convert the keys first.
Encryption Mode:
.NET defaults to CBC mode (requires IV)
CF defaults to ECB (no IV required)
In case the other link dies, here is the full example. While it uses 3DES, the basic concept is the same for AES. Note: In Java, the larger key sizes (ie 192,256) are only available if the Sun Unlimited Strength Jurisdiction Policy Files are installed.
3DES Example:
// sample valus
plainPassword = "password12345";
base64Salt = "x7le6CBSEvsFeqklvLbMUw==";
hexDecryptKey = "303132333435363738393031323334353637383930313233";
// first extract the bytes of the salt and password
saltBytes = binaryDecode(base64Salt, "base64");
passBytes = charsetDecode(plainPassword, "UTF-16LE" );
// next combine the bytes. note, the returned arrays are immutable,
// so we cannot use the standard CF tricks to merge them
// NOTE: If BlueDragon does not include "org.apache.commons...."
// just loop through the arrays and merge them manually
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
dataBytes = ArrayUtils.addAll( saltBytes, passBytes );
// convert DNN hex key to base64 for ColdFusion
base64Key = binaryEncode(binaryDecode( hexDecryptKey, "hex"), "base64");
// create an IV and intialize it with all zeroes
// block size: 16 => AES, 8=> DES or TripleDES
blockSize = 8;
iv = javacast("byte[]", listToArray(repeatString("0,", blocksize)));
// encrypt using CBC mode
bytes = encryptBinary(dataBytes, base64Key, "DESede/CBC/PKCS5Padding", iv);
// result: WBAnoV+7cLVI95LwVQhtysHb5/pjqVG35nP5Zdu7T/Cn94Sd8v1Vk9zpjQSFGSkv
WriteOutput("encrypted password="& binaryEncode( bytes, "base64" ));