openssl command line to cipher RC4, not expected result, don't understand - encryption

this is probably a stupid question, but I cannot figure it out.
Currently, I am using this website: http://www.fyneworks.com/encryption/rc4-encryption/ to cipher rc4 for a proof of concept. For instance, I am entering 'a' as a cleartext, 'a' as a password and I get '71' as a ciphertext (this is the ascii representation of the 'q').
I wanted to do the same from the command line, using openssl:
> echo a | openssl rc4 -nosalt -out /tmp/uuu
enter rc4 encryption password:
Verifying - enter rc4 encryption password:
> cat /tmp/uuu | xxd
0000000: 5896 X.
So we are getting '5896' instead of '71' and this is what I don't understand. If someone could explain to me, I'd be grateful.
Thank you !

Thanks to a friend, we figured out what was wrong. He told me to print the key
echo -ne "a" | openssl rc4 -pass pass:a -e -nopad -nosalt -p
key=0CC175B9C0F1B6A831C399E269772661
We see that there is some padding added, with the 0x61 we entered at the end. It turns out openssl generates a key from the pass.
Instead, if we enter directly the key with the -K option:
echo -ne "a" | openssl rc4 -K 61 -e -nopad -nosalt -p
key=61000000000000000000000000000000
We see that there is a padding with '0's. ACtually, it doesn't want us to use a too small key (since for rc4 the key must be at least 40bits long). Now, let's try with a 128b key:
echo -ne "foobar" | openssl rc4 -K "6162636465666768696A6B6C6D6E6F70" -e -nopad -nosalt | xxd
0000000: caaf 2cbf d334 ..,..4
The result is the same as the one on the webpage :)

Work-in-progress
Here's an interesting pattern for you. Using '0' as the encryption key we get some strong trends between the plaintext and the ciphertext. See below.
What interests me about the difference between the two implementations is that fyne increases monotonically while OpenSSL is a bit of a stair-step. I'll take another look at it later - I'm marking this a community wiki since I don't consider this an answer yet but I figured the analysis might help.
fyne:
0(0) = B8
0(1) = B9
0(2) = BA
0(3) = BB
0(4) = BC
0(5) = BD
0(6) = BE
0(7) = BF
0(8) = B0
0(9) = B1
OpenSSL:
0(0) = 72
0(1) = 73
0(2) = 70
0(3) = 71
0(4) = 76
0(5) = 77
0(6) = 74
0(7) = 75
0(8) = 7A
0(9) = 7B
Commands Used
cat -n N > /tmp/test #Where n is a number
openssl rc4 -e -nosalt -in /tmp/test -out /tmp/uuu
cat /tmp/uuu |xxd

Related

Verify EU GreenPass with openSSL

I just received my Covid Green Pass. I've started to decode it, here are the fields I get:
header: a20448349a42b0c2d0728e0126
payload: a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f624954626369782630314954303544314444
signature: 6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a
All fields are hexadecimals in this example. The payload is a CBOR structure, it can be further decoded to get your data.
Verifying the GreenPass
What I would like to do now, is to verify the signature using the Unix tool openssl.
I figured out that the green pass signature is created with Elliptic Curve Digital Signature Algorithm (ECDSA), using the P–256 parameters, in combination with the SHA–256 hash algorithm.
With openssl, I should be able to verify this greenpass:
$ openssl dgst -sha256 -verify public_key_it -signature my_signature my_data
I need three parameters: public_key_it, my_signature and my_data.
public_key_it is a file containing the public key capable of checking the green pass signature. It is available online, for Italy it is:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnL9+WnIp9fvbcocZSGUFlSw9ffW/jbMONzcvm1X4c+pXOPEs7C4/83+PxS8Swea2hgm/tKt4PI0z8wgnIehojw==
-----END PUBLIC KEY-----
my_signature is a file containing the signature part of the green pass.
I get it with:
echo "6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a" | xxd -r -p > my_signature
The my_data part is more mysterious.
It seems that it should be a Sig_structure, as specified in https://datatracker.ietf.org/doc/html/rfc8152#section-4.4.
Anyway, I tried to compose it:
jSignature1MH4Br&#Y7d]a;bIT9avbdnbmamORG-100031184bvpj1119349007bdtj2021-07-14bcobITbcix&01IT05D1DDD951474B1C93D161A4F4663B8E#3bmplEU/1/20/1507bisvMinistero della Salutebsdbtgi840539006cnamcfntfDUPONTbfnfDUPONTcgntxCORENTIN<NICOLAS<MARIE<FRANCOISbgnx"CORENTIN, NICOLAS, MARIE, FRANCOIScvere1.0.0cdobj1978-11-17
Some characters are not printable, so here it is again in hexadecimals:
846a5369676e6174757265314da20448349a42b0c2d0728e012640590137a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f62495462636978263031495430354431444444393531343734423143393344313631413446343636334238452333626d706c45552f312f32302f31353037626973764d696e69737465726f2064656c6c612053616c7574656273640162746769383430353339303036636e616da463666e74664455504f4e5462666e664455504f4e5463676e74781f434f52454e54494e3c4e49434f4c41533c4d415249453c4652414e434f495362676e7822434f52454e54494e2c204e49434f4c41532c204d415249452c204652414e434f49536376657265312e302e3063646f626a313937382d31312d3137
Well, if I try the openssl command above, I get:
$ openssl dgst -sha256 -verify public_key_it -signature my_signature my_data
Error Verifying Data
140529059103168:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91:
140529059103168:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:../crypto/asn1/tasn_dec.c:1137:
140529059103168:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:309:Type=ECDSA_SIG
Any hint? Am I even on the right track??
Thanks
EDIT: I now solved the problem. I wrote about all the details in a blog post: http://www.corentindupont.info/blog/posts/Programming/2021-08-13-GreenPass.html
With the help of #MichaelFehr, I managed to solve this problem!
Signature conversion
The GreenPass has a signature in "raw" (P1363) format.
However, openssl only accepts DER format. So we need to convert it.
Here is my signature:
6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc782cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a
It is 64 bytes long. It is composed of two integers, R and S.
R is the first half, while S is the second half.
R = 6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc78
S = 2cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a
According to DER encoding, I need to add some more bytes:
30 -- fixed value for composed structure
44 -- size of everything that follows
02 -- fixed value for integer
20 -- size of the R integer
6f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc78 -- R
02 -- fixed value for integer
20 -- size of the S integer
2cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a -- S
If I assemble it, I can obtain my DER signature:
echo -n "304402206f422bd436e216177de025d3d31681a27bead6115f480630754db6f1498bbc7802202cdc975f4c4d79af77dbe02c31de6af4ba94d7fe11510a5ca6121cb0bf10890a" | xxd -r -p > my_signature.der
Data conversion
The data part needs to be composed, too.
According to the COSE spec, I need to build a "Sig_structure" from the green pass data. This Sig_structure is used both for creating the signature, and verifying it.
Here is the "Sig_structure" completed:
846a5369676e6174757265314d -- "Signature1" in hexadecimals
a20448349a42b0c2d0728e0126 -- My header (see original post above)
40590137 -- some separator... not sure
a4041a645d8180061a61053b9501624954390103a101a4617681aa62646e01626d616d4f52472d3130303033313138346276706a313131393334393030376264746a323032312d30372d313462636f62495462636978263031495430354431444444393531343734423143393344313631413446343636334238452333626d706c45552f312f32302f31353037626973764d696e69737465726f2064656c6c612053616c7574656273640162746769383430353339303036636e616da463666e74664455504f4e5462666e664455504f4e5463676e74781f434f52454e54494e3c4e49434f4c41533c4d415249453c4652414e434f495362676e7822434f52454e54494e2c204e49434f4c41532c204d415249452c204652414e434f49536376657265312e302e3063646f626a313937382d31312d3137 -- my payload (see above)
We can now create my_data:
echo -n "846a536967..." | xxd -r -p > my_data.bin
It now works!!
$ openssl dgst -sha256 -verify public_key_it -signature my_signature.der my_data
Verified OK

SHA256 Hash doesn't match the one listed on Bitcoin Wiki

I am trying to create a bitcoin address by following the steps shown here. However, I am getting a different hash then the one shown in step 2.
Calculating the SHA256 hash on:
0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
Gives me the output:
a9ce83de3a0ff3516b7c50cdd787e9f69f152f227d93c9512774231e7132e925
The problem is according to the Bitcoin wiki I should get the following hash:
0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98
Can someone explain why I am not getting the same hash as the wiki?
You are treating 0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352 as an ascii string, whereas you should be treating it as a hex representation of 32 bytes.
If you use it as a string, you get:
echo -n "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" | openssl sha256
(stdin)= a9ce83de3a0ff3516b7c50cdd787e9f69f152f227d93c9512774231e7132e925
If you treat it as bytes, you get the right result:
echo -n "0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" | xxd -p -r | openssl sha256
(stdin)= 0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98

Why does password generated from "openssl passwd -1" has different length than md5sum?

Say password is 000000
cmd> openssl passwd -1 000000
$1$noyU0rJi$iZ7EgOhutl2aJItaBcF5v.
cmd> echo -n '000000noyU0rJi' | md5sum #cmd might be incorrect
1be6132fd5be99229741e0b88700fe95 -
md5sum hash should have 32 characters, but the hash from openssl is only 22 characters (iZ7EgOhutl2aJItaBcF5v). Why is that?
Edit: I got some downvote, would be helpful if you could explain why..
At least part of the difference you are seeing is that the output of the openssl tool is in the base64 format associated with the Unix crypt function [ https://en.wikipedia.org/wiki/Crypt_(C) ], whereas the output of the md5 function is in hexadecimal (base16).
If you look carefully, you can see that the output of md5sum only has the digits 0-9 and the lowercase letters a-f. The output of the openssl command has numbers and what appears to be the full alphabet, including upper and lowercase letters.
When you encode information more densely (base64), the length will naturally be shorter.

Decrypt TS file using OpenSSL (m3u8/EXT-X-KEY/EXT-X-MEDIA-SEQUENCE)

(Sorry in advance - my english is very bad)
I encrypted a couple of *.ts files in the past. Usually, there is a *.m3u8 with the necessary information, a key-file and the *.ts chunks.
Example:
File sources:
https://support.jwplayer.com/customer/portal/articles/1430261-aes-content-protection
M3U8:
#EXTM3U
#EXT-X-VERSION:1
## Created with Unified Streaming Platform(version=1.6.7)
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:11
#EXT-X-KEY:METHOD=AES-128,URI="oceans.key"
#EXTINF:11, no desc
oceans_aes-audio=65000-video=236000-1.ts
...
What I do next is, download the key file "oceans.key" that is specified in #EXT-X-KEY and create a hexdump of the content:
cat oceans.key | hexdump -e '16/1 "%02x" "\n"'
f571bfecfd1ab9adb05ce6fa030efd81
With the sequence number converted to HEX and left-padding 0 to fill up the '16 octet', I get the initial vector and execute this statement to decrypt the *.ts file:
openssl aes-128-cbc -d -in oceans_aes-audio\=65000-video\=236000-1.ts -out decrypted.ts -K f571bfecfd1ab9adb05ce6fa030efd81 -iv 00000000000000000000000000000001
It works like a charm. To make a long story short, I've some trouble get these files decrypted:
https://www.sendspace.com/filegroup/ajezM9HbgI3OI%2BY9%2BvUdJNnxYyXqGXX6K6jsNcrzYNc
The file named 'security' is the key file. When I hex-dump its content it is 17 octets instead of 16. Run the openssl command I get the following output:
hex string is too long
invalid hex key value
I compared the content of the file with some other files from this host and recognized that the last character is always the same (0x5e / ^). So, I removed it and tried again - my guess was that it is some kind of escape sequence / line-ending. No luck so far. The result is:
bad decrypt
140050579783384:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
Here the complete command:
openssl aes-128-cbc -d -in media_1496546273.ts -out media_1496546273.decrypt.ts -K aaf36c79be1fad3977a4e8b19e48f038 -iv 00000000000000000000000000008E97
I thought about padding, nopadding, different cipher, ... No result so far. Chrome did play the files in flowplayer without any issues.
I would appreciate any help and hint to get on with this.
BR

golang rsa decrypt no padding?

Golang rsa does not have NO_PADDING?
But openssl is ok.
For encrypted data docking and other language, the encrypted data with Golang cannot decrypt normally, but the use of PHP and Openssl can be normal, later found like Golang does not support NO_PADDING decryption, seems to only PKCS1.
Openssl increase the parameter - raw can normal decryption.The private key is above, a cipher and decrypted correct value.
Can someone help me to look at how to solve?
$ cat private.pem
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBANJS/xu+NtmDqobnhCdLjWk46aYbBk/mQrLcozAIbQLFG2mgkrxf
B5+CgtISKpKfmRfCO2NhceK+YedaMMBUxn8CAQMCQQCMN1S9KXnmV8cEmlgaMl5G
JfEZZ1mKmYHMkxd1WvNXLNuke9ntKwti8zG1lAFcOVHnm/uYsNdua+lvvQlEgBUL
AiEA/c8ezGaNUFwEAltwTEFtFItT5PyOXlWIdPAZ7j160lkCIQDUI8f/chEmLxG1
5kPcRtyJsQRdAcnQZ5QOz6S0nBnUlwIhAKk0vzLvCOA9WAGSSt2A82MHjUNTCZQ5
BaNKu/Qo/Iw7AiEAjW0v/6FgxB9hI+7X6C89sSCtk1aGiu+4Cd/DIxK74w8CIB4q
rA1k247JrqKTGlqSHVr1Ta+h3BPbwFKCi5CiDOjV
-----END RSA PRIVATE KEY-----
$ xxd data.txt
00000000: 6d4b 5dab 6d64 45e1 e4cb 0ea8 20df b724 mK].mdE..... ..$
00000010: cfe5 db3e 75c4 e80e 2337 4f08 1b36 87b4 ...>u...#7O..6..
00000020: 7550 47d4 ed60 576a a160 2d01 3cf7 4c50 uPG..`Wj.`-.<.LP
00000030: 7e44 6432 1f9d cfe2 2e9f 4f89 f815 ae01 ~Dd2......O.....
$ base64 -i data.txt
bUtdq21kReHkyw6oIN+3JM/l2z51xOgOIzdPCBs2h7R1UEfU7WBXaqFgLQE890xQfkRkMh+dz+Iun0+J+BWuAQ==
$ cat data.txt | openssl rsautl -decrypt -inkey private.pem -raw
qYnYKT2mxuXR5XB615gOenqxOnIUjWs7
Decrypting a ciphertext block using rsa with no padding is a single modulo exponent operation.
c := new(big.Int).SetBytes(cipherText)
plainText := c.Exp(c, privateKey.D, privateKey.N).Bytes()
A full example using your input data is here: https://play.golang.org/p/CgLYgLR61t
If you want a full version of the decryption function, with side-channel blinding and using precomputed CRT values for faster performance, you can copy the decrypt function from the crypto/rsa/rsa.go source.
If you have the choice, you should not be using rsa in this manner. There is a good discussion on the Crypto StackExchange site explaining the details and drawbacks of using this method.
Not actually answer the question, but I put this here for someone who are looking for encrypting a plain text using rsa with no padding.
var publicKey *rsa.PublicKey
// ...
// ...
c := new(big.Int).SetBytes([]byte(text))
encryptedBytes := c.Exp(c, big.NewInt(int64(publicKey.E)), publicKey.N).Bytes()
encryptedBase64 := base64.StdEncoding.EncodeToString(encryptedBytes)

Resources