In [ ]:
from Crypto.PublicKey import RSA
import base64
from github_settings import SSH_KEY_PASSWORD
my_public_key = RSA.importKey(
open('/Users/raymondyee/.ssh/id_rsa.pub', 'r').read())
my_private_key = RSA.importKey(open('/Users/raymondyee/.ssh/id_rsa','r').read(),
passphrase=SSH_KEY_PASSWORD)
message = "abcdefgh"
In [ ]:
print (my_public_key.exportKey(format='PEM'))
In [ ]:
print (open("/Users/raymondyee/.ssh/id_rsa.pem").read())
How to match the
Base64.encode64
from travis.rb/repository.rb at dcc9f20535c811068c4ff9788ae9bd026a116351 · travis-ci/travis.rb This docs: Module: Base64 (Ruby 2_2_0):
Returns the Base64-encoded version of bin. This method complies with RFC 2045. Line feeds are added to every 60 encoded characters.
Class: OpenSSL::PKey::RSA (Ruby 2_2_4):
Encrypt string with the public key. padding defaults to PKCS1_PADDING. The encrypted string output can be decrypted using private_decrypt.
Also in the doc:
RSA is an asymmetric public key algorithm that has been formalized in RFC 3447.
Look for how to do so in Python.
possible values for padding (see source: Ruby MRI/test/openssl/test_pkey_rsa.rb):
OpenSSL::PKey::RSA::NO_PADDINGOpenSSL::PKey::RSA::PKCS1_PADDINGLooks like there is no standard library support in Ruby libs for
Also: don't know whether PKCS1_PADDING means:
In [ ]:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA
from Crypto import Random
import base64
def nopadding_encrypt(message, key):
ciphertext = key.encrypt(message, 0)[0]
return base64.b64encode(ciphertext)
def nopadding_decrypt(ciphertextb64, key):
ciphertext = base64.b64decode(ciphertextb64)
return key.decrypt(ciphertext)
def pkcs1v15_encrypt(message, key):
h = SHA.new(message)
cipher = PKCS1_v1_5.new(key)
ciphertext = cipher.encrypt(message+h.digest())
return base64.b64encode(ciphertext)
def pkcs1v15_decrypt (ciphertextb64, key):
dsize = SHA.digest_size
sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15
cipher = PKCS1_v1_5.new(key)
ciphertext = base64.b64decode(ciphertextb64)
message = cipher.decrypt(ciphertext, sentinel)
digest = SHA.new(message[:-dsize]).digest()
print ("len(message): {} sentinel: {} len(digest):{} dsize: {}".format(len(message), sentinel,
len(digest), dsize))
if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel
return message[:-dsize]
else:
raise Exception ('encryption was done incorrectly:{}'.format(message))
def pkcs1oaep_encrypt(message, key):
cipher = PKCS1_OAEP.new(key)
ciphertext = cipher.encrypt(message)
return base64.b64encode(ciphertext)
def pkcs1oaep_decrypt(ciphertextb64, key):
cipher = PKCS1_OAEP.new(key)
ciphertext = base64.b64decode(ciphertextb64)
return cipher.decrypt(ciphertext)
In [ ]:
enc_data = nopadding_encrypt(message, my_public_key)
print (enc_data,
nopadding_decrypt (enc_data, my_private_key)
)
In [ ]:
enc_data = pkcs1v15_encrypt(message, my_public_key)
print (enc_data, pkcs1v15_decrypt(enc_data,
my_private_key
))
In [ ]:
enc_data = pkcs1oaep_encrypt(message, my_public_key)
print (enc_data,
pkcs1oaep_decrypt( enc_data,
my_private_key
))
In [ ]:
### try decrypting output from Ruby with pkcs1v15
In [ ]:
ruby_output = """
Upw4QQcNptfvd6t00mVLZaLMd965DqiiNOYmRStkcr1eX/v3ETkTNIqkc8WG
ajrTYM20rYw3wfcMIjbCKXBSouTYqrJ4H4Uom3BbOI11Ykmf3Lf20QhB5r9K
YwDLol3bKSqbTTNXhPm2ALSjsX5tha4jkc4VooGAA6grMMcTmS9cGgCC0Gm5
oILJzzLb5WEEN2CiUk0JVvSvadYylDyuFou8iP6GVPpOrILDNHHZKb70irXb
E846PrDg8x83fL3+OoYAtfup3fR2ZH2qVXvs4JAQqRH9ECQtUkinJ4sukKYU
R/pULVPeWI/xgX0cQ3xxXg3V8m4IcqF1nTe8TkZ1RA==
""".strip()
assert base64.b64decode(ruby_output) == base64.b64decode(ruby_output.replace("\n",""))
pkcs1v15_decrypt(ruby_output, my_private_key)
In [ ]:
pkcs1oaep_decrypt(ruby_output, my_private_key)
In [ ]:
%%bash
echo -n 'abcdefgh' \
| openssl rsautl \
-encrypt \
-pubin -inkey ~/.ssh/id_rsa.pem \
> /Users/raymondyee/Downloads/cipher.txt
In [ ]:
pkcs1v15_decrypt(base64.b64encode(open("/Users/raymondyee/Downloads/cipher.txt", "rb").read()), my_private_key)
In [ ]:
%%bash
cat /Users/raymondyee/Downloads/test_message.txt \
| base64 -D \
| openssl rsautl \
-decrypt \
-inkey ~/.ssh/id_rsa
In [ ]:
pkcs1oaep_decrypt(base64.b64encode(open("/Users/raymondyee/Downloads/cipher.txt", "rb").read()), my_private_key)
In [ ]:
%%bash
# using openssl
echo -n 'abcdefgh' | openssl rsautl -encrypt -pubin -inkey /Users/raymondyee/.ssh/id_rsa.pem | base64
In [ ]:
openssl_output = """
yHkXsyDCj6eZJ7Ixf8vdXwOT7iCp9DHjVNcVmyMYR/fAsLzgLDeuNeS01hsMAVXtDiEJaMjxVaAqziRgeYB8Q36ZDGm9OUBkWahjQbvouXjS/YG5wLpW+PxnhYOIWS8La74dc50Kwqa5r6iqDJufBxJfD9g0eAngBTeIxIg1jq/r/ThNYcpb3qLVa4+h9sd4BocXxwvAwSjd0Wr1B4rogSUdxf11KU6K2tlQTjb/GHfOY7HjXaQH6jz8gRWJlNdDVaGSc+DCKiZfGrB62Ifuf94RBNjq0Y9T18PS+vVatcI2FJ8rSpV90cHYB3gTSLmBBwytW1SUt2rYR13Oi7aCUA==
""".strip()
pkcs1v15_decrypt(openssl_output, my_private_key)
In [ ]:
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"abc")
digest.update(b"123")
digest.finalize()
In [ ]:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
private_key
In [ ]:
from github_settings import SSH_KEY_PASSWORD
from cryptography.hazmat.primitives import serialization
with open("/Users/raymondyee/.ssh/id_rsa", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=SSH_KEY_PASSWORD,
backend=default_backend()
)
In [ ]:
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
public_key = private_key.public_key()
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
pem.splitlines()
In [ ]:
message = b"abcdefgh"
#OAEP
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
ciphertext
In [ ]:
message = b"abcdefgh"
#PKCS1v15
ciphertext = public_key.encrypt(
message,
padding.PKCS1v15()
)
ciphertext
In [ ]:
plaintext = private_key.decrypt(
ciphertext,
padding.PKCS1v15()
)
plaintext == message
In [ ]:
private_key.decrypt(
base64.b64decode(openssl_output),
padding.PKCS1v15()
)
In [ ]:
private_key.decrypt(
base64.b64decode(ruby_output),
padding.PKCS1v15()
)
Conclusion: use the cryptography lib