ECC private key is longer than public key - bouncycastle

I have generated ECC public and private key using secp192r1 curve. I get 75 for public and 125 for private encoded key array length. Why private key is longer than public key? Why private key is not longer two times than public? Why private key is not 192 bits = 24 bytes because of secp192r1?
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp192r1");
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(ecSpec, new SecureRandom());
KeyPair pair = g.generateKeyPair();
System.out.println(pair.getPublic().getEncoded().length);
System.out.println(pair.getPrivate().getEncoded().length);

Code fragment below outputs 24 bytes private key:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp192r1");
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(spec, new SecureRandom());
KeyPair pair = g.generateKeyPair();
ECPrivateKey ecPrivateKey = (ECPrivateKey)pair.getPrivate();
System.out.println(ecPrivateKey.getS().toByteArray().length);

Related

Node.JS encrypt using MD5 / ECB and padding w/PKCS7

I inherited a database that has the passwords utilizing the following functions to encrypt/decrypt in VB.NET
Public Shared Function EncryptString(ByVal Message As String, ByVal Passphrase As String) As String
Dim Results As Byte()
Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
Dim HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
Dim TDESKey As Byte() = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase))
Dim TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider()
TDESAlgorithm.Key = TDESKey
TDESAlgorithm.Mode = CipherMode.ECB
TDESAlgorithm.Padding = PaddingMode.PKCS7
Dim DataToEncrypt As Byte() = UTF8.GetBytes(Message)
Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor()
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length)
Return Convert.ToBase64String(Results)
End Function
Public Shared Function DecryptString(ByVal Message As String, ByVal Passphrase As String) As String
Dim Results As Byte()
Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
Dim HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
Dim TDESKey As Byte() = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase))
Dim TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider()
TDESAlgorithm.Key = TDESKey
TDESAlgorithm.Mode = CipherMode.ECB
TDESAlgorithm.Padding = PaddingMode.PKCS7
Dim DataToDecrypt As Byte() = Convert.FromBase64String(Message)
Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor()
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length)
Return UTF8.GetString(Results)
End Function
I am having a hard time encrypting the data to query the SQL server.
When using EncryptString with the following parameters:
Message = stack-overflow
Passphrase = Danielle
I get:
1c2wL+guV34oyVS0vkxwVA==
I need to do this encryption and decryption with node.js
I tried this but it did not work:
var crypto = require('crypto');
encrypt(text, paraphrase) {
const key =text;
const secret =paraphrase;
// Encryption
const cipher = crypto.createCipheriv("aes-192-ecb", Buffer.from(key, "base64"), null);
const encryptedSecret = cipher.update(secret, "utf8", "base64") + cipher.final("base64");
return(encryptedSecret);
};
I also tried installing MD5 by npm but I had no luck either.
Any help to encrypt and decrypt will be appreciated. Thank you all.
For the NodeJS code to be compatible with the VB code, TripleDES must be used instead of AES. The key must be derived with MD5. Since MD5 provides a 16 bytes key, TripleDES is applied in the double-length key variant (2TDEA), which combines two DES keys K1 and K2 to a TripleDES key K1|K2|K1. One possible implementation is:
var key16 = crypto.createHash('md5').update(passphrase).digest();
var cipher = crypto.createCipheriv("des-ede-ecb", key16, null);
var ciphertext = cipher.update(data, "utf8", "base64") + cipher.final("base64");
If des-ede-ecb is not supported, des-ede3-ecb can be used as an alternative. This implements TripleDES in the triple-length key variant (3TDEA), which combines three DES keys K1, K2 and K3 to a TripleDES key K1|K2|K3. For K3 = K1 this is equivalent to 2TDEA:
var key16 = crypto.createHash('md5').update(passphrase).digest();
var key24 = Buffer.concat([key16, key16.slice(0, 8)]);
var cipher = crypto.createCipheriv("des-ede3-ecb", key24, null);
Note that ECB is insecure (better a mode with an IV like GCM), as is key derivation via a cryptographic hash function (better a reliable key derivation function like PBKDF2) and the broken MD5 as such (better SHA256). TripleDES is deprecated and slow (better AES).
Edit:
The decryption is completely analog, e.g. for 2TDEA:
var key16 = crypto.createHash('md5').update(passphrase).digest();
var decipher = crypto.createDecipheriv("des-ede-ecb", key16, null);
var decrypted = decipher.update(ciphertext, "base64", "utf8") + decipher.final("utf8");

Replicating Asp.net Identity Password Hash to Chilkat

Hi I want to replicate the password hashing that is done in asp.net identity such that, the resulting value of password hashed by asp.net identity and the password hashed by Chilkat are same. Is that even possible?
In C# asp.net, we use Rfc2898DeriveBytes that does the pbkdf2 for us. How can I do the same in Chilkat?
private const int PBKDF2IterCount = 1000; // default for Rfc2898DeriveBytes
private const int PBKDF2SubkeyLength = 256 / 8; // 256 bits
private const int SaltSize = 128 / 8; // 128 bits
//[ComVisible(true)]
public string HashPassword(string password)
{
if (password == null)
{
throw new ArgumentNullException("password cannot be null");
}
// Produce a version 0 (see comment above) text hash.
byte[] salt;
byte[] subkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
{
salt = deriveBytes.Salt;
subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
var outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
return Convert.ToBase64String(outputBytes);
}
Currently, the parameters I am using at Chilkat are:
Function EncryptChilkat(sPassword As String) As String
Dim crypt As New ChilkatCrypt2
Dim success As Long
success = crypt.UnlockComponent("ACHIEV.CR1082018_dCrRA3zr4e1M ")
If (success <> 1) Then
Debug.Print crypt.LastErrorText
Exit Function
End If
Dim hexKey As String
Dim pw As String
pw = "pwd"
Dim pwCharset As String
pwCharset = "base64"
' Hash algorithms may be: sha1, md2, md5, etc.
Dim hashAlg As String
hashAlg = "HMCSHA1"
' The salt should be 8 bytes:
Dim saltHex As String
saltHex = "78578E5A5D63CB06"
Dim iterationCount As Long
iterationCount = 1000
' Derive a 128-bit key from the password.
Dim outputBitLen As Long
outputBitLen = 128
' The derived key is returned as a hex or base64 encoded string.
' (Note: The salt argument must be a string that also uses
' the same encoding.)
Dim enc As String
enc = "base64"
hexKey = crypt.Pbkdf2(pw, pwCharset, hashAlg, saltHex, iterationCount, outputBitLen, enc)
EncryptChilkat = hexKey
End Function
Check the binary values of both the password and the salt on both sides. Also check for trailing nulls, carriage returns, and line feeds.
Additionally, you can see which, if either, algorithm is misbehaving - I have a copy of Jither's .NET PBKDF2 implementation at my github repository including test vectors, and for your Chillkat, you can create what you need from my LibreOffice Calc sheet of PBKDF2 test vectors.
Run these through both implementations; whichever one fails is wrong.
If both succeed... then you're not giving both the same parameters.

TripleDes CBC Nodejs implementation throuble

i need to replicate in Nodejs the results of the 3DS CBC encrypt in http://tripledes.online-domain-tools.com/.
This is my code:
const crypto = require('crypto');
const cipher = crypto.createCipher('des-ede3-cbc', key);
password = Buffer.from('MYPASS', 'utf8');
let encrypted = [cipher.update(password)];
encrypted.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
console.log(encrypted.toString('hex'));
The result of tripledes.online-domain-tools.com is:
Note that the result should be 59 30 20 02 a5 8c dd 5e, but my code gives me 33 97 d8 b0 e3 00 d1 53.
What am i missing?
Edit2:
Following your suggestions, I changed my code (Also added some Tests made with the guide of the NIST Publication):
const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
let shortkey = Buffer.from(inputkey, keyformat);
let key = Buffer.alloc(24);
key.fill('\0');
for (i = 0; i < shortkey.length; i++) {
key[i] = shortkey[i];
}
let IV = Buffer.alloc(8);
const cipher = crypto.createCipheriv('des-ede3-cbc', key, IV);
password = Buffer.from(password, passwordformat);
let encryptedArr = [cipher.update(password)];
encryptedArr.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
return encrypted;
}
console.log(encrypt('1046913489980131','hex','0000000000000000','hex')); // works
console.log(encrypt('1007103489988020','hex','0000000000000000','hex')); // works
console.log(encrypt('10071034C8980120','hex','0000000000000000','hex')); // works
console.log(encrypt('1046103489988020','hex','0000000000000000','hex')); // works
console.log(encrypt('MYKEY','utf8','MYPASS','utf8')); // fails
Every Permutation Operation Known Answer Test of the NIST works great, but several other examples (including the one of the image) just fails
The reason i'm testing with this shady page is because my service provider is using it as reference.
This site made me some troubles for some time , well here is the implementation it uses internally to expand the key to be a 24 bytes !
i am going to talk about tripledes but i guess this would apply to other algorithms used by this site
step 1
it first checks if the key entered has the length that it expects it to be, (you can find a table at the bottom of that site telling the length of key for each Encryption algorithm)
if it does not it will complete with 0x00 bytes like this:
var key;// is a string containing the bytes wich will be used to encrypt the msg
var nullByte = 0x00;
var padding_needed;
for (var i=key.length ;i < expected_key_length ; ++)
{padding_needed =padding_needed + nullBute.tostring(16); }
key = key + padding_needed
so for example the length that it expects for 3DES is 24 bytes ; if you happen to enter just 15 bytes like this (112233445566778899aabbccddeeff) it will be like if you entered (112233445566778899aabbccddeeff00)
step2
in the case of tripledes the algorithm to expand the 16 bytes to 24 bytes key (which is the key length required by the algorithm) this site has a simple approach to do that
it copies the first 8 bytes and append it to the end of the key like this
key =key + key.substring(0,8);
and that is the key that is going to be given to the 3DES encryption function to work with
this simple approache is not used by openssl for example , open ssl uses the first 8 bytes of the MD5 of the key ,and append them to the 16 bytes of the original key to get the 24 bytes key that is required by 3DES, like this
key = key + (MD5(key)).substring(0,8);
Summary
in that tool if you enter the key 112233445566778899AABBCCDDEEFF is the same as if you entered 112233445566778899AABBCCDDEEFF00 and same as if you entered 112233445566778899AABBCCDDEEFF001122334455667788 so to solve your problem you should give your function the complete 24 bytes of key that you gave to that site and you will surely get the same results, beacause nodejs is probably is doing the same thing as openssl does to expand the key(uses md5)
PS
if you are using the cbc mode which is your case try to specify the IV to be 8 bytes of \x00 like this "0000000000000000"
the results will be the same !!
here is a working implementation of your code you can check it in the site
const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
let shortkey = Buffer.from(inputkey, keyformat);
let key = Buffer.alloc(24);
key.fill('\0');
for (i = 0; i < shortkey.length; i++) {
key[i] = shortkey[i];
}
let IV = Buffer.alloc(8);
var expansionStart = shortkey.length>16?shortkey.length:16;
for (i=expansionStart;i<24;i++){
key[i]=key[i-expansionStart];
}
console.log(key);
const cipher = crypto.createCipheriv('des-ede3-cbc', key, IV);
password = Buffer.from(password, passwordformat);
let encryptedArr = [cipher.update(password)];
encryptedArr.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
return encrypted;
}
var enc = encrypt("112233445566778899AABBCCDDEEFF","hex","password","utf8");
console.log(enc);

Kundera persistence entity definition with partition key and cluster key

I am trying to use Kundera for connecting to Cassandra. In my case I have an Entity X with Partition Key {A,B} and cluster key {C}.
We have multiple values of C for each A and B combination(primary key).
So in such case how should be define the entity?
#Embeddable
public class PrimayKey implements Serializable{
#Column(name = "A")
private String a;
#Column(name = "B")
private String b;
}
#Entity
#Table(name = "X")
public class X{
#EmbeddedId
private PrimayKey key;
#Column(name = "C")
private String c;
#Column(name = "D")
private String d;
}
Here if I go for a find by Primary Key its not working as we have multiple values of C and D for each A and B combination. In such case how should we define entity?
You can create an embeddable for partition key and then use it as a field in primary key. Kundera will automatically read the entities and consider the fields other than partition keys as clustering keys.
Cassandra equivalent Primary key : ((A, B), C)
Entity :
#Embeddable
public class PartitionKey {
#Column(name = "A")
private String a;
#Column(name = "B")
private String b;
}
#Embeddable
public class PrimayKey {
private PartitionKey key;
#Column(name = "C")
private String c;
}
Please refer this sample entity for more info.

Signing a string with HMAC-MD5 with C#

I got the following HMAC key (in hexadecimal format):
52320e181a481f5e19507a75b3cae4d74d5cfbc328f7f2b738e9fb06b2e05b55b632c1c3d331dcf3baacae8d3000594f839d770f2080910b52b7b8beb3458c08
I need to sign this string:
1100002842850CHF91827364
The result should be this (in hexadecimal format):
2ad2f79111afd818c1dc0916d824b0a1
I have the following code:
string key = "52320e181a481f5e19507a75b3cae4d74d5cfbc328f7f2b738e9fb06b2e05b55b632c1c3d331dcf3baacae8d3000594f839d770f2080910b52b7b8beb3458c08";
string payload = "1100002842850CHF91827364";
byte[] keyInBytes = Encoding.UTF8.GetBytes(key);
byte[] payloadInBytes = Encoding.UTF8.GetBytes(payload);
var md5 = new HMACMD5(keyInBytes);
byte[] hash = md5.ComputeHash(payloadInBytes);
var result = BitConverter.ToString(hash).Replace("-", string.Empty);
However, I am not getting the result. What am I doing wrong?
when hashing with key HMAC md5
var data = Encoding.UTF8.GetBytes(plaintext);
// key
var key = Encoding.UTF8.GetBytes(transactionKey);
// Create HMAC-MD5 Algorithm;
var hmac = new HMACMD5(key);
// Compute hash.
var hashBytes = hmac.ComputeHash(data);
// Convert to HEX string.
return System.BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
Instead of doing this:
byte[] keyInBytes = Encoding.UTF8.GetBytes(key);
you need to convert key from a hex string to array of bytes. Here you can find example:
How do you convert Byte Array to Hexadecimal String, and vice versa?

Resources