des-ecb Encryption in elixir/erlang - erlang

How do i pass a 24 byte key to elixir/erlang block_encrypt des-ecb cipher.
As a follow up to my previous question How to set a 24 byte length key to elixir/erlang block_encrypt/4 function using des_ede3 as mode of encryption that i was able to get working, Am trying to pass a 24byte key to the key field in elixir/erlang block_encrypt method.
Below is what i have so far.
# this failed
key = "Fget63htyu3nvu28nuineiru34"
<<key_1::binary-8, key_2::binary-8, key_3::binary-8>> = key
cipher = :crypto.block_encrypt(:des_ecb, {key_1, key_2, key_3}, pad(data, 8))
How do i pass the 24 byte length key as an 8 byte key thats required by the des_ecb cipher.

Related

How to access bytes in public key generated by SecKeyCreateRandomKey()?

I am trying to send encrypted messages using AES-GCM between an iOS app and an ESP microcontroller. But before I do that, I need to perform a key exchange between the two devices so that they both have a shared secret. So I am looking into iOS methods for generating private/public key pairs and there are several. However there is one problem, the keys generated by iOS aren't readily compatible with anything outside of iOS (as far as I understand) which means I have to jump in and make some modifications to the keys. I noticed the keys that are generated are always abdc1234 where abcd never changes and 1234 changes every time a key is generated. So I am assuming that abcd is just something iOS uses and 1234 is the actual key. At least, that's what happens in Android. So to test my hypothesis, I'm trying to get the raw bytes of the public key that was generated in iOS so I can cut off the abcd and send the actual key 1234 to the ESP. The problem is I can't find how to access the bytes that the key contains. Here's what I tried so far...
let tag = "".data(using: .utf8)!
let attributes: [String: Any] = [
kSecAttrType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag
]
]
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)
let publicKey = SecKeyCopyPublicKey(privateKey!)
print("\(publicKey!)")
var address = Unmanaged.passUnretained(publicKey!).toOpaque()
do{
withUnsafeBytes(of: &address) { bytes in
for byte in bytes{
print(byte)
}
}
}
So the first print statement outputs the following
<SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 256, bits, y: ..., x: ..., addr: 0x...>
Which so far so good, the key that I want is on the curve that I want and the key is the correct length and such.
But now the next print outputs the following
144
70
215
9
1
0
0
0
That's it. Clearly, the last 8 things to be printed are not the key, it's too short. So yeah, how do I extract the x and y value of the public key. I can see it printed so there must be a way to access it but yeah I have searched everywhere and no dice. My theory that I can "chop" off the "iOS" part of the generated key might not even be correct but the thing is I can't even test it without being able to send the bytes to the ESP. I hope there is an easier way to achieve the key exchange between iOS app and ESP but for now, this is the only way I know how. Oh yeah, I send the key bytes over bluetooth, I was able to connect the iOS app to the ESP via bluetooth and that's how I'm trying to make the key exchange. I know bluetooth is techncially encrypted but I just want to do the key exchange and then encrypt the bluetooth messages further by using AES-GCM. So please. If you know of a way to access the key bytes, please share!
UPDATE:
I use this code to generate key pair for ECDH key exchange:
let attributes: [String: Any] = [
kSecAttrType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecPrivateKeysAttrs as String: [
kSecAttrIsPermanent as String: true
]
]
var error: Unmanaged<CFError>?
privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)!
publicKey = SecKeyCopyPublicKey(privateKey!)!
let pubKeyExternRep = SecKeyCopyExternalRepresentation(publicKey!, &error)
print("\(publicKeyExternRep!)")
Which outputs the following:
{length = 65, bytes = 0x048820d8 0482e62f 7abac673 02d8a68e ... 6e0117684
ff455540 }
I am trying to get everything after the 0x04 in the bytes section to be in a character array so that I can send it over bluetooth in a sequence of packets. So it is imperative that I obtain everything after the 0x04, all 128 characters, and have it in a byte array. In the end, if I print the contents of the byte array, it should just say 8820d80482e62f ... 6e0117684ff455540.
I have tried the following:
//^^^ previous code block that generates the key pair ^^^
let length = CFDataGetLength(pubKeyExternRep!)
let range = CFRange.init(location: 0, length: length)
let uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity:length)
CFDataGetBytes(pubKeyExternRep!, range, uint8Pointer)
print("\(uint8Pointer.pointee)")
This outputs the following:
4
Which seems promising since it matches the first 4 of the key, the 0x04 but then I move up the pointer by switching location: 5 and it prints a random two digit number that doesn't match with anything useful, i.e. 68 or something like that.
I also tried this:
^^^ previous code block that generates the key pair ^^^
let keyData = pubKeyExternRep as Data?
let dataString = keyData?.base64EncodedString()
var byteArray: [UInt8] = []
byteArray = Array(dataString!.utf8)
print("\(byteArray)")
Now this gets me extremely close to what I need, it's a byte array and I can perform operations on it and concatenate stuff and such, if I print it outputs this:
[66, 79, 76, ..., 119, 81, 61]
The problem is not only do the members of the array not match any of the 128 bytes in the pubKeyExternRep but its also shorter than the 128 bytes I need. It's 64 bytes. This is actually something I been noticing for both methods I tried (the CFDataGetBytes method and the String to Array method), whatever it is I get, it's never 128 bytes, it's always 64.
I just need all 128 bytes after the 0x04 when I print(publicKeyExternRep!)
UPDATE 2:
Found solution, it's not the one that's marked but that did technically answer the question. Will post solution after work!
Just use SecKeyCopyExternalRepresentation(_:_:). Encoded format is not as what is commonly referred to as X9.63 by the way, it is a flat uncompressed public key point without the parameters of the named curve.

How to set a 24 byte length key to elixir/erlang block_encrypt/4 function using des_ede3 as mode of encryption

Am trying to send data to an external api that expects encrypted data using 3DES encryption but am having issues understanding how to pass my api key as the key field to erlangs des_ede3 cipher.
According to erlangs cipher docs des_ede3 expects 3 keys that are all 8 bytes in length. How can i pass my 24 byte api key as the key to elixir/erlang :cryptoblock_encrypt/4 function
*** how can i pass key to block_encrypt/4 ***
key = "123456789012345678901234"
data = "hello world! The world is yours"
block_size = 8
cipher = :crypto.block_encrypt(:des_ede3, [key, key, key], iv, pad(data, block_size))
How do i pass my 24 byte api key as the key to erlangs block_encrypt/4 in order for me to pass data to the external api.
Thanks
Use binary pattern matching:
<<k1 :: binary-size(8),
k2 :: binary-size(8),
k3 :: binary-size(8)>> = "123456789012345678901234"
#⇒ "123456789012345678901234"
{k1, k2, k3}
#⇒ {"12345678", "90123456", "78901234"}

SecKeyRawSign SHA256withRSA: how to?

I'm trying to use SecKeyRawSign on swift to digitally sign a String using SHA256withRSA. I can properly generate the RSA keys, but I'm not sure about what data to send to this function.
My goal is to use PKCS1 v1.5 format, which should generate the same signature as long as the private key and content to be signed are the same, i.e., there's no random component in the algorithm.
Also, I (think I) know that the algorith that I should first calculate the SHA256 hash of the message, then I should add a ASN.1 prefix describing the algorithm. And finally I should add the PKCS1 padding (0x00 0x01 0xff .. 0xff 0x00) to complete a 128-byte sequence for a 1024-bit key.
I tried passing the following combinations of data and padding to the function:
* message with PKCS1HSA256 padding
* sha256(message) with PKCS1HSA256 padding
* algorithm identifier + sha256(message) with PKCS1 padding
* pkcs1 padding + algorithm identifier + sha256(message) with raw padding
In each case the function returns no error, but each time I call the function with the same key and data, a different signature is generated.
Knowing that the algorithm has no random component, shouldn't I be getting the same signature every time?
So can somebody help me by letting me know what should be passed into each parameter to accomplish my goal? How data param should be constructed?
Thanks.

iOS SecItemCopyMatching RSA public key format?

I'm trying to extract a 1024-bit RSA public key from an already generated key pair (two SecKeyRefs), in order to send it over the wire. All I need is a plain (modulus, exponent) pair, which should take up exactly 131 bytes (128 for the modulus and 3 for the exponent).
However, when I fetch the key info as a NSData object, I get 140 bits instead of 131. Here's an example result:
<30818902 818100d7 514f320d eacf48e1 eb64d8f9 4d212f77 10dd3b48 ba38c5a6
ed6ba693 35bb97f5 a53163eb b403727b 91c34fc8 cba51239 3ab04f97 dab37736
0377cdc3 417f68eb 9e351239 47c1f98f f4274e05 0d5ce1e9 e2071d1b 69a7cac4
4e258765 6c249077 dba22ae6 fc55f0cf 834f260a 14ac2e9f 070d17aa 1edd8db1
0cd7fd4c c2f0d302 03010001>
After retrying the key generation a couple of times and comparing the resulting NSData objects, the bytes that remain the same for all keys are the first 7:
<30818902 818100>
The last three bytes look like the exponent (65537, a common value). There are also two bytes between the "modulus" and the exponent:
<0203>
Can someone with more crypto experience help me identify what encoding is this? DER? How do I properly decode the modulus and exponent?
I tried manually stripping out the modulus and exponent using
NSData* modulus = [keyBits subdataWithRange:(NSRange){ 7, 128 }];
NSData* exponent = [keyBits subdataWithRange:(NSRange){ 7 + 128 + 2, 3 }];
but I get errors when trying to decrypt data which the remote host encoded using that "key".
EDIT:
Here's a gist of the solution I ended up using to unpack the RSA blob: https://gist.github.com/vl4dimir/6079882
Assuming you want the solution to work under iOS, please have a look at this thread. The post confirms that the encoding is DER and shows how to extract the exponent and modulus from the NSData object you started with.
There is another solution that won't work on iOS, but will work on Desktop systems (including MacOS X) that have OpenSSL installed in this thread. Even if you are looking for the iOS-only solution you can still use this to verify your code is working correctly.

Generating an RSA Key Pair with Erlang?

Erlang has a crypto function which generates public private keys (documentation copied below). However the documentation seems vague and I can't find any example code that describes how to generate the shared prime number or the generator. Can someone post an example that generates a public/private key pair? Thanks in advance for any help!
dh_generate_key(DHParams) -> {PublicKey,PrivateKey}
dh_generate_key(PrivateKey, DHParams) -> {PublicKey,PrivateKey}
Types:
DHParameters = [P, G]
P, G = Mpint
Where P is the shared prime number and G is the shared generator.
PublicKey, PrivateKey = Mpint()
Generates a Diffie-Hellman PublicKey and PrivateKey (if not given).
You don't generate the shared prime number or the generator for Diffie-Hellman. See:
http://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange
The parameters P and G are agreed to ahead of time by both sides. Using the notation of the Wikipedia article, crypto:dh_generate_key is used for steps 2 & 3 to generate a/A & b/B, and then crypto:dh_compute_key is used for steps 4 & 5 to compute the shared secret s.
For RSA, I don't know of a standard library function that generates a public/private key pair. Generating primes is a fairly involved algorithm from what I remember; I would strongly recommend you not try to code it yourself. Diffie-Hellman key pairs are not suitable for use with RSA; they are different algorithms intended for different purposes.
Generally you don't need to generate these at runtime since you can reuse the key pair. You can use any number of other sources to actually generate it. (Maybe ssh-keygen would work? And there's always OpenSSL.) To use the key pair you've created, you'd use the crypto:rsa_ public/private _ encrypt/decrypt functions.
See cutkey (https://github.com/yrashk/cutkey)
"cutkey is an Erlang app for generating RSA keys. It is implemented as
a port driver that calls OpenSSL's RSA_generate_key on a thread from
the async pool."
os:command("openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048").
You can use the crypto:generate_key/2 function to create RSA public and private keys:
For a 2048 length
{Pub, Priv} = crypto:generate_key(rsa, {2048,65537}).
Or for a 1024 length
{Pub, Priv} = crypto:generate_key(rsa, {1024,65537}).
See: https://erlang.org/doc/apps/crypto/crypto.pdf (page 37)
generate_key(Type, Params) -> {PublicKey, PrivKeyOut}
Where
Type = rsa
Params = rsa_params() =
{ModulusSizeInBits :: integer(),
PublicExponent :: key_integer()}

Resources