Skip to content

Instantly share code, notes, and snippets.

@ateska
Created April 11, 2019 06:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ateska/09e1c874494bba8e381ccd8d851b0df8 to your computer and use it in GitHub Desktop.
Save ateska/09e1c874494bba8e381ccd8d851b0df8 to your computer and use it in GitHub Desktop.
Python / cryptography.io decryption compatible with iOS ECIES encryption
import binascii
import cryptography.hazmat.backends
import cryptography.hazmat.primitives.asymmetric.ec
import cryptography.hazmat.primitives.hashes
import cryptography.hazmat.primitives.kdf.x963kdf
import cryptography.hazmat.primitives.ciphers.aead
import cryptography.hazmat.primitives.serialization
# Alice (with iOS) is sending encrypted message to Bob (Python)
#
# This is based on https://darthnull.org/security/2018/05/31/secure-enclave-ecies/
# It is a Proof-of-Concept that decrypts a ECEIS messages encrypted by iOS or macOS
# This piece is for SECP384R1 (be carefull, Secure Enclave can do only SECP256R1, which is only about changes in few parameters bellow)
#
# Swift code:
# var error : Unmanaged<CFError>?
# let request_cyphertext = SecKeyCreateEncryptedData(
# bob_public_key,
# SecKeyAlgorithm.eciesEncryptionCofactorX963SHA256AESGCM,
# request_plaintext as CFData,
# &error
# )
# Ciphertext
ct = bytes.fromhex('046b935b6ac8236fdb8717ec8bc4c54275303ad2a48a02f6a58351985d8ed89793bc8c98261eb9bea5010d2f3d6ffe1e244698cfa8a61899905274796b192707012cdbb1b0be64389088b9499f61b110331c69e81e947756d687921510ae616863b5e26da3865c38fc37cd5a070007a54d0cabda5364618a289dca3eca07b271cc210964f67e8274b377944381f68818f84cdf75cb00ed38a0d1422a3b884612a90dddd8335db4b5bcd6642818f2c3b291dc4497c1e60fa51c97aba1bec2eba1d2af6f9b6d5f20e0e180a35399446addbd3944c3e512ff79e083609ddf234d37802c3ac2e2417e3e559cb6a2751851cc7844e7cd0b1cabd9de06910798f09814336eea473e0e6bf708f17ec0fd3949975597877c79a62402dcb37bd1466bcff11cafe0ea296229c4bfd2643616efdc40de7ce6e7adf5f3f50be572')
# Load the private key of the target (bob)
bob_pem = b'''
-----BEGIN EC PRIVATE KEY-----
MIG... private key lives here
-----END EC PRIVATE KEY-----'''
bob_private = cryptography.hazmat.primitives.serialization.load_pem_private_key(
bob_pem,
password=None,
backend=cryptography.hazmat.backends.default_backend()
)
# Extract the public key of the sender (ephemeral, only for this message)
alice_pub_bytes = ct[:96+1]
alice_public = cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point(
cryptography.hazmat.primitives.asymmetric.ec.SECP384R1(),
alice_pub_bytes
)
#
# use ECDH to generate a shared key using Alice's public and Bob's private keys
#
shared_key = bob_private.exchange(
cryptography.hazmat.primitives.asymmetric.ec.ECDH(),
alice_public
)
# #
# # Use the ANSI x9.63 Key Derivation Function to derive the final
# # encryption key from the ECDH-built key.
# #
# # * Use the SHA-256 hash when deriving the key,
# # * Use Alice's (ephemeral) public key data as Shared Info, and
# # * Extract 16 bytes (enough for a 128-bit key
xkdf = cryptography.hazmat.primitives.kdf.x963kdf.X963KDF(
algorithm=cryptography.hazmat.primitives.hashes.SHA256(),
length=32,
sharedinfo=alice_pub_bytes,
backend=cryptography.hazmat.backends.default_backend()
)
key_enc = xkdf.derive(shared_key)
iv = binascii.a2b_hex('00000000000000000000000000000000')
# #
# # DECRYPT THE MESSAGE!
# #
cryptor = cryptography.hazmat.primitives.ciphers.aead.AESGCM(key_enc)
pt = cryptor.decrypt(iv, ct[96+1:], b"")
print(pt)
@EasyAndComplex
Copy link

HI Ateska,
Just a question, have you tried the code with swift?

@ateska
Copy link
Author

ateska commented Feb 8, 2024

Can confirm that for 100% but likely yes. @EasyAndComplex

@EasyAndComplex
Copy link

EasyAndComplex commented Feb 9, 2024

Thanks @ateska.
I have issue on this:

I get the publickey in order to encrypt in swift:

bob_pem = b'''

-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIFL3sLnioGcDvHWM/BPlNw96BOx1KKco2qsq4UwhQUosoAcGBSuBBAAK
oUQDQgAEXs1Fmq4QdPAbn3NycdEU+HOjc3kW9efbso2kI/vdDTWcSCMk310s53G3
tRClDBPPuuJAsKghbPfaTaUpmXFCNA==
-----END EC PRIVATE KEY-----
'''

bob_private = cryptography.hazmat.primitives.serialization.load_pem_private_key(
    bob_pem,
    password=None,
    backend=cryptography.hazmat.backends.default_backend()
)


# Extract Bob's public key from his private key
public_key = bob_private.public_key()


# Extracting public key bytes
public_key_bytes = public_key.public_bytes(
    encoding=cryptography.hazmat.primitives.serialization.Encoding.PEM,
    format=cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo
)

and in swift when ii try to encrypt since it is .pem it gives error:

 let publicKey = """
    -----BEGIN PUBLIC KEY-----
    MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEAs5xEIm001FFsRpXSRFEy57+swcr3nW9
    SP3ERlrT539LE/x2auTwUVTCkaFS6R5IBl2QIvEml+UXgBU0sDK3PqZsqHcQzvBz
    Z/lX7NehqphbVCQBr3nkhDwyq0tkrmyD
    -----END PUBLIC KEY-----
    """
    
    // Remove the header and footer
    let publicKeyString = publicKey.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----\n", with: "")
        .replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
        .replacingOccurrences(of: "\n", with: "")

    // Decode the base64 string
    if let publicKeyData = Data(base64Encoded: publicKeyString) {
        print("What is base 64: \(publicKeyData.base64EncodedString())")
         
    } else {
        
    }
    
    
   let query: [String: Any] = [
     kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
     kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
     kSecAttrKeySizeInBits as String: 2048
   ]
   
   var unmanagedError: Unmanaged<CFError>?
   
   guard let pubKeyRef = SecKeyCreateWithData(pubKeyData as CFData, query as CFDictionary, &unmanagedError) else {
       print(unmanagedError!.takeRetainedValue() as Error)
     throw unmanagedError!.takeRetainedValue() as Error
   }
   print("What is pubref: \(pubKeyRef)")
   return pubKeyRef
 } 

Any idea how to resolve this? do you have swift example class?

@EasyAndComplex
Copy link

I have tried : https://github.com/agens-no/EllipticCurveKeyPair/tree/master with this example: https://darthnull.org/secure-enclave-ecies/ at the end I get error: Error: underlying(message: "Could not decrypt.", error: Error Domain=NSOSStatusErrorDomain Code=-50 "ECIES: Failed to aes-gcm decrypt data (err -69)" (paramErr: error in user parameter list) UserInfo={NSDescription=ECIES: Failed to aes-gcm decrypt data (err -69), numberOfErrorsDeep=0, NSLocalizedRecoverySuggestion=See https://www.osstatus.com/search/results?platform=all&framework=all&search=-50})

@ateska
Copy link
Author

ateska commented Feb 16, 2024

Sorry, I don't have a way to test it now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment