Popular New Releases in Encryption
certbot
Certbot 1.26.0
unlock-music
Build 2022/01/09
client
v5.9.3
cryptomator
1.6.8
unlock-music
Build 2021/02/08
Popular Libraries in Encryption
by certbot python
28838 NOASSERTION
Certbot is EFF's tool to obtain certs from Let's Encrypt and (optionally) auto-enable HTTPS on your server. It can also act as a client for any other CA that uses the ACME protocol.
by signalapp java
22277 GPL-3.0
A private messenger for Android.
by unlock-music typescript
11299 MIT
Unlock encrypted music file in browser. 在浏览器中解锁加密的音乐文件。
by keybase go
8023 BSD-3-Clause
Keybase Go Library, Client, Service, OS X, iOS, Android, Electron
by signalapp java
7566 AGPL-3.0
Server supporting the Signal Private Messenger applications on Android, Desktop, and iOS
by cryptomator java
7273 GPL-3.0
Multi-platform transparent client-side encryption of your files in the cloud
by ix64 javascript
7224 MIT
Unlock encrypted music file in browser. 在浏览器中解锁加密的音乐文件。
by upspin go
5836 NOASSERTION
Upspin: A framework for naming everyone's everything.
by diafygi python
4526 MIT
A tiny script to issue and renew TLS certs from Let's Encrypt
Trending New libraries in Encryption
by google c++
2178 Apache-2.0
Libraries and tools to perform fully homomorphic encryption operations on an encrypted data set.
by jesseduffield go
2145 MIT
Split your file into encrypted fragments so that you don't need to remember a passcode
by ddz go
869
Decrypt WhatsApp encrypted media files
by privacyguides css
683 CC0-1.0
Protect your data against global mass surveillance programs.
by andrewchambers rust
622 MIT
Easy and efficient encrypted backups.
by small-tech javascript
450 AGPL-3.0
Develop, test, and deploy your secure static or dynamic personal web site with zero configuration.
by zama-ai rust
405 NOASSERTION
Concrete Operates oN Ciphertexts Rapidly by Extending TfhE
by mafintosh javascript
404 MIT
A 1-1 end-to-end encrypted internet pipe powered by Hyperswarm
by SocketDev javascript
356 MIT
Streaming encryption for Wormhole.app, based on Encrypted Content-Encoding for HTTP (RFC 8188)
Top Authors in Encryption
1
41 Libraries
691
2
13 Libraries
1740
3
9 Libraries
1164
4
9 Libraries
3430
5
8 Libraries
54
6
8 Libraries
1182
7
8 Libraries
2811
8
7 Libraries
3074
9
6 Libraries
61
10
6 Libraries
176
1
41 Libraries
691
2
13 Libraries
1740
3
9 Libraries
1164
4
9 Libraries
3430
5
8 Libraries
54
6
8 Libraries
1182
7
8 Libraries
2811
8
7 Libraries
3074
9
6 Libraries
61
10
6 Libraries
176
Trending Kits in Encryption
Java Encryption Libraries enable password encryption, digital signatures, secure random number generation, message authentication, and 2FA.
Encryption, decryption, and key generation are the three most crucial aspects of Java cryptography. Key-based data security can be enabled in two ways, using symmetric or asymmetric encryption algorithms, considering how secure the code needs to be. Moreover, developers can easily enable security functions directly into the code with the set of APIs available in the Java Cryptography Architecture (JCA). The JCA is the core of java encryption and decryption, hashing, secure random, and various other java cryptographic functions.
Check out the below list to find more trending Java encryption libraries for your applications:
tink
- Offers various cryptographic functions like encryption, digital signatures, and more.
- Provides an easy-to-use interface, simplifying the implementation of robust security measures.
- Follows best practices, minimizing the chance of security vulnerabilities in cryptographic operations.
bc-java
- Provides various encryption, signatures, and hashing algorithms.
- Offers flexible options for cryptographic operations to suit various protocols.
- Seamlessly integrates into Java applications for strong security features.
jasypt
- Supports many encryption methods for tailored security.
- Seamlessly integrates encryption features into Java codebases.
- Allows easy setup of encryption configurations for different use cases.
cryptomator
- Encrypts files before uploading them to the cloud, keeping data private.
- Can easily access encrypted files and work with your data as usual.
- Enables secure file storage and access from different environments.
Aegis
- Offers authenticated encryption schemes, ensuring both data confidentiality and integrity.
- Provides a user-friendly and straightforward API for implementing cryptographic operations.
- Is lightweight and easy to carry, so it works well in limited environments or small systems.
mockserver
- Facilitates creating mock servers for testing and simulating HTTP/HTTPS interactions.
- Setting precise expectations for requests and responses helps thoroughly test API interactions.
- Can save API requests to reuse in tests for accuracy and reproducibility.
hawk
- Offers a strong MAC algorithm for verifying the integrity and authenticity of messages.
- Utilizes an authorization header to transmit authentication information, enhancing security securely.
- Works across various platforms and languages, allowing integration into different applications and systems.
GDA-android-reversing-Tool
- Can learn about Android apps by analyzing them using reverse engineering.
- Helps analyze and break down the code of Android apps for inspection.
- The graphical interface makes it easy to use the reverse engineering features.
wycheproof
- Enables testing cryptographic algorithms and libraries for known security vulnerabilities and weaknesses.
- Have many cryptography test cases to ensure it works well in different situations.
- Helps confirm if cryptographic implementations work well on different platforms and libraries.
bt
- Can share files, reducing the need for central servers and speeding up downloads.
- To speed up downloads, it uses a method called "swarming." This method collects small pieces from many sources simultaneously.
- The protocol will download from other sources if a source is unavailable. This ensures that downloads are uninterrupted and strong.
Peergos
- Provides strong file encryption, ensuring data privacy and security from unauthorized access.
- Users gain control over their data. They can securely share files and manage access permissions.
- It uses a network not centered in one place to save and find files. This makes it so we don't have to rely on one main server, which helps ensure the data is always there and strong.
i2p.i2p
- Let users browse websites and send messages without showing their IP addresses.
- Uses powerful encryption to keep data safe and secure when it's sent.
- The routing mechanism is not centralized. This makes it difficult for others to track online activities.
secure-preferences
- We use encryption to protect private information from people who shouldn't see it.
- It works with Android's SharedPreferences API. This means you can easily use secure data storage without changing much code.
- The app protects sensitive information, reducing the risk of data breaches or leaks. It enhances user privacy.
AndroidWM
- Can add personalized watermarks to images, improving branding and ownership recognition.
- Can choose where the watermark goes, how big it is, how see-through it is, and what it looks like.
- Can process many images together, which makes it simpler to add watermarks to them.
Cipher.so
- Can easily use native code for cryptography in Android apps.
- Optimized cryptographic algorithms for efficient and secure data encryption and decryption.
- Supports various encryption and decryption methods, enabling customization based on specific security requirements.
conscrypt
- Uses many different ways to keep data safe when encrypted or sent.
- Offers up-to-date TLS and SSL protocol versions for secure network communication.
- Ensures compatibility with older Android versions, allowing applications to maintain security across devices.
react-native-sensitive-info
- Can securely store sensitive information like passwords or tokens.
- Compatible with both Android and iOS, ensuring consistent security practices across different platforms.
- Utilizes encryption mechanisms to protect sensitive data from unauthorized access.
android-storage
- Simplifies data storage and retrieval tasks in Android apps, promoting efficient data handling.
- Offers the option to encrypt files stored on the device, enhancing data security.
- Can focus on how things work instead of how things are stored.
whorlwind
- Offer tools to protect data when stored and transferred, ensuring it stays safe.
- Supports various encryption algorithms for different security needs.
- Designed for use across various platforms, promoting consistent security practices.
encrypt
- Enables encryption and decryption operations within Android applications.
- Supports many encryption algorithms, offering flexibility in choosing the appropriate method.
- Simplifies the process of implementing encryption-related functionalities.
java-aes-crypto
- Offers AES encryption and decryption capabilities, a widely used symmetric encryption algorithm.
- Provides mechanisms for secure key generation and management within Java applications.
- Supports cryptographic modes that ensure both data confidentiality and integrity.
Android-Goldfinger
- Facilitates fingerprint-based authentication and access control in Android apps.
- Enhances user security by integrating biometric authentication.
- Offers a user-friendly interface for integrating fingerprint-related functionalities.
AESCrypt-Android
- Implements AES encryption and decryption for protecting sensitive data in Android applications.
- Provides straightforward methods for incorporating AES cryptography into your code.
- Enables users to store and transmit sensitive information securely.
Secured-Preference-Store
- Enhances SharedPreferences with encryption, safeguarding sensitive user preferences.
- Offers a seamless way to integrate secure preference storage without extensive code modifications.
- Prevents unauthorized access to preference data by implementing encryption mechanisms.
EncryptedPreferences
- Integrates secure storage mechanisms for sensitive preferences in Android apps.
- Implements encryption to prevent data exposure or tampering.
- Provides an API for easily incorporating encrypted preference storage in Android projects.
FAQ
What are Java encryption Libraries, and what basic encryption capabilities do they provide?
Java encryption libraries are tools used to improve data security in Java applications. They help implement cryptographic techniques. They offer:
- AES (Advanced Encryption Standard): Symmetric encryption for secure data transmission.
- RSA (Rivest–Shamir–Adleman): Asymmetric encryption for secure key exchange and digital signatures.
- Hashing Algorithms: Generate secure hash codes to verify data integrity.
- Digital Signatures: Authenticate data origin and verify integrity.
- Key Management: Generate, store, and handle encryption keys.
- SSL/TLS: Implement secure communication over networks.
- PGP (Pretty Good Privacy): Encrypt and decrypt data for privacy.
How can password encryption be achieved using Java libraries?
In Java, you can encrypt passwords using JCA or third-party libraries. Hashing algorithms, such as bcrypt and SHA-256, convert passwords into irreversible codes. To keep user credentials safe, adding salt and storing them securely is important. This helps to prevent attacks and maintain confidentiality.
Are digital signatures supported by any of the Java encryption libraries?
Yes, digital signatures are supported by various Java encryption libraries. Java Cryptography Architecture (JCA) libraries enable the creation and verification of digital signatures. They use algorithms like RSA for asymmetric encryption. Digital signatures are important in Java applications for secure communication and authentication. They ensure data is authentic, integral, and cannot be denied. Bouncy Castle and other Java libraries can help with digital signatures and cryptography.
What is an encryption key, and how is it used to encrypt and decrypt data securely?
An encryption key is a special code that turns normal data into secret code and back again. It decides how data is changed so only authorized people with the right key can see it. Strong key management is essential to maintain data security and prevent unauthorized access.
Encryption keys are crucial for secure communication. Data is kept safe from unauthorized access. This happens when it's being transmitted or stored.
Can you create a Message Authentication Code using a popular Java encryption library?
Developers can use algorithms, such as HMAC from JCA, to implement MAC for security. The sender creates a code that receivers can check using a secret key. This process ensures data is correct and information is secure when sent.
Is there an easy way to generate cipher text from plain text using a library written in Java?
Java has libraries like JCA that help turn plain text into secret code. Developers can change plain text into cipher text. They do this by choosing an encryption algorithm, such as AES, and using a secret key. They can do this through straightforward method calls. Java applications can securely transmit and store data while keeping it confidential. Developers can easily add strong encryption using these libraries without needing complex coding.
Trending Discussions on Encryption
How to use sized traits in structs?
Crypto-js encryption and Python decryption using HKDF key
Reading encrypted private key in PKCS#8 format through bouncycastle, Java failing in docker container
iOS CryptoSwift AES Encryption to Python Decryption works - but not the inverse
Use string value for argument typed as Literal
How do I calculate a key check value for AES-128-CBC?
Convert Node crypto aes-256-cbc to CryptoJS
Problem Updating to .Net 6 - Encrypting String
convert base-64 spki string into public key
Data Encryption static encrypt
QUESTION
How to use sized traits in structs?
Asked 2022-Apr-03 at 21:27I'm trying to use the AES crate, which offers three algorithms: AES128, AES192 and AES256. I'm trying to create a struct that can create the correct algorithm by detecting the key size, and save it to later use.
I see they all implement the BlockEncrypt (I only need encryption) trait, but when I try to make a field in the struct with this type, even when supplying the size, i get an "the trait BlockEncrypt
cannot be made into an object. the trait cannot be made into an object because it requires Self: Sized
" error.
1pub struct MyStruct<'a, T: Sized> {
2 ciph: Box< dyn BlockEncrypt<BlockSize = T>>,
3}
4
ANSWER
Answered 2022-Apr-03 at 19:42As @cdhowie mentioned, you can't create a trait object from a trait with a Sized
bound. Instead, you can create an enum:
1pub struct MyStruct<'a, T: Sized> {
2 ciph: Box< dyn BlockEncrypt<BlockSize = T>>,
3}
4enum MyAlgorithm {
5 AES128(AES128),
6 AES192(AES192),
7 AES256(AES256),
8}
9
QUESTION
Crypto-js encryption and Python decryption using HKDF key
Asked 2022-Mar-28 at 11:29Based on the example provided here on how to establish a shared secret and derived key between JS (Crypto-JS) and Python, I can end up with the same shared secret and derived key on both ends.
However, when I try to encrypt as below, I cannot find a way to properly decrypt from Python. My understanding is that probably I am messing with the padding or salts and hashes.
1 const payload = "hello"
2 var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
3
4 var test = CryptoJS.AES.encrypt(
5 payload,
6 derived_key,
7 {iv: iv, mode: CryptoJS.mode.CBC}
8 ).toString();
9
10 console.log(test)
11
Output "y+In4kriw0qy4lji6/x14g=="
Python (one of the attempts):
1 const payload = "hello"
2 var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
3
4 var test = CryptoJS.AES.encrypt(
5 payload,
6 derived_key,
7 {iv: iv, mode: CryptoJS.mode.CBC}
8 ).toString();
9
10 console.log(test)
11from Crypto.Cipher import AES
12from Crypto.Util.Padding import pad,unpad
13
14iv = "1020304050607080"
15
16test_enc = "y+In4kriw0qy4lji6/x14g=="
17enc = base64.b64decode(test_enc)
18
19cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
20
21print(base64.b64decode(cipher.decrypt(enc)))
22
23print(unpad(cipher.decrypt(enc),16))
24
Any guidance here would be greatly appreciated as I am stuck for quite some time.
(I have encryption working using a password, but struggling with HKDF).
EDIT:
Here is the full Python code:
1 const payload = "hello"
2 var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
3
4 var test = CryptoJS.AES.encrypt(
5 payload,
6 derived_key,
7 {iv: iv, mode: CryptoJS.mode.CBC}
8 ).toString();
9
10 console.log(test)
11from Crypto.Cipher import AES
12from Crypto.Util.Padding import pad,unpad
13
14iv = "1020304050607080"
15
16test_enc = "y+In4kriw0qy4lji6/x14g=="
17enc = base64.b64decode(test_enc)
18
19cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
20
21print(base64.b64decode(cipher.decrypt(enc)))
22
23print(unpad(cipher.decrypt(enc),16))
24from cryptography.hazmat.primitives.asymmetric import ec
25from cryptography.hazmat.primitives.kdf.hkdf import HKDF
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28import base64
29
30
31from Crypto.Cipher import AES
32from Crypto.Util.Padding import pad,unpad
33
34
35def deriveKey():
36
37 server_pkcs8 = b'''-----BEGIN PRIVATE KEY-----
38MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBReGpDVmoVTzxNbJx6
39aL4L9z1EdB91eonAmAw7mKDocLfCJITXZPUAmM46c6AipTmhZANiAAR3t96P0ZhU
40jtW3rHkHpeGu4e+YT+ufMiMeanE/w8p+d9aCslvIbZyBBzeZ/266yqTUUoiYDzqv
41Hb5q8rz7vEgr3DG4XfHYpCqfE2nttQGK3emHKGnvY239AteZkdwMpcs=
42-----END PRIVATE KEY-----'''
43
44 client_x509 = b'''-----BEGIN PUBLIC KEY-----
45MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEm0xeyy3nVnYpOpx/CV/FnlNEdWUZaqtB
46AGf7flKxXEjmlSUjseYzCd566sLpNg56Gw6hcFx+rWTLGR4eDRWfmwlXhyUasuEg
47mb0BQf8XJLBdvadb9eFx2CP1yjBsiy8e
48-----END PUBLIC KEY-----'''
49
50 client_public_key = serialization.load_pem_public_key(client_x509)
51 server_private_key = serialization.load_pem_private_key(server_pkcs8, password=None)
52 shared_secret = server_private_key.exchange(ec.ECDH(), client_public_key)
53 print('Shared secret: ' + base64.b64encode(shared_secret).decode('utf8')) # Shared secret: xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
54
55 salt_bytes = "12345678".encode('utf-8')
56 info_bytes = "abc".encode('utf-8')
57
58 derived_key = HKDF(
59 algorithm=hashes.SHA256(),
60 length=32,
61 salt=salt_bytes,
62 info=info_bytes,
63 ).derive(shared_secret)
64 print('Derived key: ' + base64.b64encode(derived_key).decode('utf8'))
65 return derived_key
66
67derived_key = deriveKey()
68iv = "1020304050607080"
69
70test_enc = "y+In4kriw0qy4lji6/x14g=="
71enc = base64.b64decode(test_enc)
72
73cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
74
75print(base64.b64decode(cipher.decrypt(enc)))
76
77print(unpad(cipher.decrypt(enc),16))
78
ANSWER
Answered 2022-Mar-28 at 11:29The issue is that the key is not passed correctly in the CryptoJS code.
The posted Python code generates LefjQ2pEXmiy/nNZvEJ43i8hJuaAnzbA1Cbn1hOuAgA=
as Base64-encoded key. This must be imported in the CryptoJS code using the Base64 encoder:
1 const payload = "hello"
2 var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
3
4 var test = CryptoJS.AES.encrypt(
5 payload,
6 derived_key,
7 {iv: iv, mode: CryptoJS.mode.CBC}
8 ).toString();
9
10 console.log(test)
11from Crypto.Cipher import AES
12from Crypto.Util.Padding import pad,unpad
13
14iv = "1020304050607080"
15
16test_enc = "y+In4kriw0qy4lji6/x14g=="
17enc = base64.b64decode(test_enc)
18
19cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
20
21print(base64.b64decode(cipher.decrypt(enc)))
22
23print(unpad(cipher.decrypt(enc),16))
24from cryptography.hazmat.primitives.asymmetric import ec
25from cryptography.hazmat.primitives.kdf.hkdf import HKDF
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28import base64
29
30
31from Crypto.Cipher import AES
32from Crypto.Util.Padding import pad,unpad
33
34
35def deriveKey():
36
37 server_pkcs8 = b'''-----BEGIN PRIVATE KEY-----
38MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBReGpDVmoVTzxNbJx6
39aL4L9z1EdB91eonAmAw7mKDocLfCJITXZPUAmM46c6AipTmhZANiAAR3t96P0ZhU
40jtW3rHkHpeGu4e+YT+ufMiMeanE/w8p+d9aCslvIbZyBBzeZ/266yqTUUoiYDzqv
41Hb5q8rz7vEgr3DG4XfHYpCqfE2nttQGK3emHKGnvY239AteZkdwMpcs=
42-----END PRIVATE KEY-----'''
43
44 client_x509 = b'''-----BEGIN PUBLIC KEY-----
45MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEm0xeyy3nVnYpOpx/CV/FnlNEdWUZaqtB
46AGf7flKxXEjmlSUjseYzCd566sLpNg56Gw6hcFx+rWTLGR4eDRWfmwlXhyUasuEg
47mb0BQf8XJLBdvadb9eFx2CP1yjBsiy8e
48-----END PUBLIC KEY-----'''
49
50 client_public_key = serialization.load_pem_public_key(client_x509)
51 server_private_key = serialization.load_pem_private_key(server_pkcs8, password=None)
52 shared_secret = server_private_key.exchange(ec.ECDH(), client_public_key)
53 print('Shared secret: ' + base64.b64encode(shared_secret).decode('utf8')) # Shared secret: xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
54
55 salt_bytes = "12345678".encode('utf-8')
56 info_bytes = "abc".encode('utf-8')
57
58 derived_key = HKDF(
59 algorithm=hashes.SHA256(),
60 length=32,
61 salt=salt_bytes,
62 info=info_bytes,
63 ).derive(shared_secret)
64 print('Derived key: ' + base64.b64encode(derived_key).decode('utf8'))
65 return derived_key
66
67derived_key = deriveKey()
68iv = "1020304050607080"
69
70test_enc = "y+In4kriw0qy4lji6/x14g=="
71enc = base64.b64decode(test_enc)
72
73cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
74
75print(base64.b64decode(cipher.decrypt(enc)))
76
77print(unpad(cipher.decrypt(enc),16))
78const payload = "hello"
79var derived_key = CryptoJS.enc.Base64.parse("LefjQ2pEXmiy/nNZvEJ43i8hJuaAnzbA1Cbn1hOuAgA=")
80var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
81var test = CryptoJS.AES.encrypt(payload, derived_key, {iv: iv, mode: CryptoJS.mode.CBC}).toString();
82document.getElementById("ct").innerHTML = test; // bLdmGA+HLLyFEVtBEuCzVg==
1 const payload = "hello"
2 var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
3
4 var test = CryptoJS.AES.encrypt(
5 payload,
6 derived_key,
7 {iv: iv, mode: CryptoJS.mode.CBC}
8 ).toString();
9
10 console.log(test)
11from Crypto.Cipher import AES
12from Crypto.Util.Padding import pad,unpad
13
14iv = "1020304050607080"
15
16test_enc = "y+In4kriw0qy4lji6/x14g=="
17enc = base64.b64decode(test_enc)
18
19cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
20
21print(base64.b64decode(cipher.decrypt(enc)))
22
23print(unpad(cipher.decrypt(enc),16))
24from cryptography.hazmat.primitives.asymmetric import ec
25from cryptography.hazmat.primitives.kdf.hkdf import HKDF
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28import base64
29
30
31from Crypto.Cipher import AES
32from Crypto.Util.Padding import pad,unpad
33
34
35def deriveKey():
36
37 server_pkcs8 = b'''-----BEGIN PRIVATE KEY-----
38MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBReGpDVmoVTzxNbJx6
39aL4L9z1EdB91eonAmAw7mKDocLfCJITXZPUAmM46c6AipTmhZANiAAR3t96P0ZhU
40jtW3rHkHpeGu4e+YT+ufMiMeanE/w8p+d9aCslvIbZyBBzeZ/266yqTUUoiYDzqv
41Hb5q8rz7vEgr3DG4XfHYpCqfE2nttQGK3emHKGnvY239AteZkdwMpcs=
42-----END PRIVATE KEY-----'''
43
44 client_x509 = b'''-----BEGIN PUBLIC KEY-----
45MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEm0xeyy3nVnYpOpx/CV/FnlNEdWUZaqtB
46AGf7flKxXEjmlSUjseYzCd566sLpNg56Gw6hcFx+rWTLGR4eDRWfmwlXhyUasuEg
47mb0BQf8XJLBdvadb9eFx2CP1yjBsiy8e
48-----END PUBLIC KEY-----'''
49
50 client_public_key = serialization.load_pem_public_key(client_x509)
51 server_private_key = serialization.load_pem_private_key(server_pkcs8, password=None)
52 shared_secret = server_private_key.exchange(ec.ECDH(), client_public_key)
53 print('Shared secret: ' + base64.b64encode(shared_secret).decode('utf8')) # Shared secret: xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
54
55 salt_bytes = "12345678".encode('utf-8')
56 info_bytes = "abc".encode('utf-8')
57
58 derived_key = HKDF(
59 algorithm=hashes.SHA256(),
60 length=32,
61 salt=salt_bytes,
62 info=info_bytes,
63 ).derive(shared_secret)
64 print('Derived key: ' + base64.b64encode(derived_key).decode('utf8'))
65 return derived_key
66
67derived_key = deriveKey()
68iv = "1020304050607080"
69
70test_enc = "y+In4kriw0qy4lji6/x14g=="
71enc = base64.b64decode(test_enc)
72
73cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
74
75print(base64.b64decode(cipher.decrypt(enc)))
76
77print(unpad(cipher.decrypt(enc),16))
78const payload = "hello"
79var derived_key = CryptoJS.enc.Base64.parse("LefjQ2pEXmiy/nNZvEJ43i8hJuaAnzbA1Cbn1hOuAgA=")
80var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
81var test = CryptoJS.AES.encrypt(payload, derived_key, {iv: iv, mode: CryptoJS.mode.CBC}).toString();
82document.getElementById("ct").innerHTML = test; // bLdmGA+HLLyFEVtBEuCzVg==<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
83<p style="font-family:'Courier New', monospace;" id="ct"></p>
The hereby generated ciphertext bLdmGA+HLLyFEVtBEuCzVg==
can be decrypted with the Python code:
1 const payload = "hello"
2 var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
3
4 var test = CryptoJS.AES.encrypt(
5 payload,
6 derived_key,
7 {iv: iv, mode: CryptoJS.mode.CBC}
8 ).toString();
9
10 console.log(test)
11from Crypto.Cipher import AES
12from Crypto.Util.Padding import pad,unpad
13
14iv = "1020304050607080"
15
16test_enc = "y+In4kriw0qy4lji6/x14g=="
17enc = base64.b64decode(test_enc)
18
19cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
20
21print(base64.b64decode(cipher.decrypt(enc)))
22
23print(unpad(cipher.decrypt(enc),16))
24from cryptography.hazmat.primitives.asymmetric import ec
25from cryptography.hazmat.primitives.kdf.hkdf import HKDF
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28import base64
29
30
31from Crypto.Cipher import AES
32from Crypto.Util.Padding import pad,unpad
33
34
35def deriveKey():
36
37 server_pkcs8 = b'''-----BEGIN PRIVATE KEY-----
38MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBReGpDVmoVTzxNbJx6
39aL4L9z1EdB91eonAmAw7mKDocLfCJITXZPUAmM46c6AipTmhZANiAAR3t96P0ZhU
40jtW3rHkHpeGu4e+YT+ufMiMeanE/w8p+d9aCslvIbZyBBzeZ/266yqTUUoiYDzqv
41Hb5q8rz7vEgr3DG4XfHYpCqfE2nttQGK3emHKGnvY239AteZkdwMpcs=
42-----END PRIVATE KEY-----'''
43
44 client_x509 = b'''-----BEGIN PUBLIC KEY-----
45MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEm0xeyy3nVnYpOpx/CV/FnlNEdWUZaqtB
46AGf7flKxXEjmlSUjseYzCd566sLpNg56Gw6hcFx+rWTLGR4eDRWfmwlXhyUasuEg
47mb0BQf8XJLBdvadb9eFx2CP1yjBsiy8e
48-----END PUBLIC KEY-----'''
49
50 client_public_key = serialization.load_pem_public_key(client_x509)
51 server_private_key = serialization.load_pem_private_key(server_pkcs8, password=None)
52 shared_secret = server_private_key.exchange(ec.ECDH(), client_public_key)
53 print('Shared secret: ' + base64.b64encode(shared_secret).decode('utf8')) # Shared secret: xbU6oDHMTYj3O71liM5KEJof3/0P4HlHJ28k7qtdqU/36llCizIlOWXtj8v+IngF
54
55 salt_bytes = "12345678".encode('utf-8')
56 info_bytes = "abc".encode('utf-8')
57
58 derived_key = HKDF(
59 algorithm=hashes.SHA256(),
60 length=32,
61 salt=salt_bytes,
62 info=info_bytes,
63 ).derive(shared_secret)
64 print('Derived key: ' + base64.b64encode(derived_key).decode('utf8'))
65 return derived_key
66
67derived_key = deriveKey()
68iv = "1020304050607080"
69
70test_enc = "y+In4kriw0qy4lji6/x14g=="
71enc = base64.b64decode(test_enc)
72
73cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
74
75print(base64.b64decode(cipher.decrypt(enc)))
76
77print(unpad(cipher.decrypt(enc),16))
78const payload = "hello"
79var derived_key = CryptoJS.enc.Base64.parse("LefjQ2pEXmiy/nNZvEJ43i8hJuaAnzbA1Cbn1hOuAgA=")
80var iv = CryptoJS.enc.Utf8.parse("1020304050607080");
81var test = CryptoJS.AES.encrypt(payload, derived_key, {iv: iv, mode: CryptoJS.mode.CBC}).toString();
82document.getElementById("ct").innerHTML = test; // bLdmGA+HLLyFEVtBEuCzVg==<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
83<p style="font-family:'Courier New', monospace;" id="ct"></p>from Crypto.Cipher import AES
84from Crypto.Util.Padding import unpad
85import base64
86
87test_enc = "bLdmGA+HLLyFEVtBEuCzVg=="
88enc = base64.b64decode(test_enc)
89derived_key = base64.b64decode("LefjQ2pEXmiy/nNZvEJ43i8hJuaAnzbA1Cbn1hOuAgA=")
90iv = "1020304050607080"
91cipher = AES.new(derived_key, AES.MODE_CBC, iv.encode('utf-8'))
92print(unpad(cipher.decrypt(enc),16)) # b'hello'
93
Note that for security reasons, a static IV should not be used so that key/IV pairs are not repeated.
QUESTION
Reading encrypted private key in PKCS#8 format through bouncycastle, Java failing in docker container
Asked 2022-Jan-31 at 01:18I am trying to read a PKCS#8 private key which looks like following:
key.k8 --> (Sample key. Passphrase - 123456):
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31
Following code is being used to parse the private key:
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31 InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
32 logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
33 PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
34 Object pemObject = pemParser.readObject();
35 if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
36 // Handle the case where the private key is encrypted.
37 PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
38 InputDecryptorProvider pkcs8Prov =
39 new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
40 privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
41}
42
43
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31 InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
32 logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
33 PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
34 Object pemObject = pemParser.readObject();
35 if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
36 // Handle the case where the private key is encrypted.
37 PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
38 InputDecryptorProvider pkcs8Prov =
39 new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
40 privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
41}
42
43InputStream resourceAsStream = null;
44 if ("local".equals(privateKeyMode)) {
45 resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
46 } else {
47 File keyFile = new File(privateKeyPath);
48 logger.info(
49 "Key file found in {} mode. FileName : {}, Exists : {}",
50 privateKeyMode,
51 keyFile.getName(),
52 keyFile.exists());
53 try {
54 resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
55 } catch (FileNotFoundException e) {
56 e.printStackTrace();
57 }
58
When I am running this code through intelliJ on windows, the code works fine but when I run it through docker container I am getting following exception:
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31 InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
32 logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
33 PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
34 Object pemObject = pemParser.readObject();
35 if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
36 // Handle the case where the private key is encrypted.
37 PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
38 InputDecryptorProvider pkcs8Prov =
39 new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
40 privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
41}
42
43InputStream resourceAsStream = null;
44 if ("local".equals(privateKeyMode)) {
45 resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
46 } else {
47 File keyFile = new File(privateKeyPath);
48 logger.info(
49 "Key file found in {} mode. FileName : {}, Exists : {}",
50 privateKeyMode,
51 keyFile.getName(),
52 keyFile.exists());
53 try {
54 resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
55 } catch (FileNotFoundException e) {
56 e.printStackTrace();
57 }
58org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream
59snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0]
60snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na]
61snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
62
Following is Dockerfile used:
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31 InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
32 logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
33 PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
34 Object pemObject = pemParser.readObject();
35 if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
36 // Handle the case where the private key is encrypted.
37 PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
38 InputDecryptorProvider pkcs8Prov =
39 new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
40 privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
41}
42
43InputStream resourceAsStream = null;
44 if ("local".equals(privateKeyMode)) {
45 resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
46 } else {
47 File keyFile = new File(privateKeyPath);
48 logger.info(
49 "Key file found in {} mode. FileName : {}, Exists : {}",
50 privateKeyMode,
51 keyFile.getName(),
52 keyFile.exists());
53 try {
54 resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
55 } catch (FileNotFoundException e) {
56 e.printStackTrace();
57 }
58org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream
59snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0]
60snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na]
61snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
62FROM adoptopenjdk/openjdk11-openj9:latest
63COPY build/libs/snowflake-report-sync-*.jar snowflake-report-sync.jar
64RUN mkdir /encryption-keys
65COPY encryption-keys/ /encryption-keys/ #keys are picked from docker filesystem when running in container
66EXPOSE 8080
67CMD java -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar snowflake-report-sync.jar
68
Options tried:
- Ensured that key file is being read while running in container. Logger "InputStreamExists --> {}" gives number of bytes
- Ran dos2unix on key.k8 just to make sure there are no Window's "^M" characters which be could be causing issue as container is linux one : FROM adoptopenjdk/openjdk11-openj9:latest
Not sure what I am doing wrong but any help or pointers would be appreciated.
ANSWER
Answered 2022-Jan-30 at 12:33Edit:
On second thought, when creating the JceOpenSSLPKCS8DecryptorProviderBuilder
, you're not explicitly specifying the provider:
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31 InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
32 logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
33 PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
34 Object pemObject = pemParser.readObject();
35 if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
36 // Handle the case where the private key is encrypted.
37 PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
38 InputDecryptorProvider pkcs8Prov =
39 new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
40 privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
41}
42
43InputStream resourceAsStream = null;
44 if ("local".equals(privateKeyMode)) {
45 resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
46 } else {
47 File keyFile = new File(privateKeyPath);
48 logger.info(
49 "Key file found in {} mode. FileName : {}, Exists : {}",
50 privateKeyMode,
51 keyFile.getName(),
52 keyFile.exists());
53 try {
54 resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
55 } catch (FileNotFoundException e) {
56 e.printStackTrace();
57 }
58org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream
59snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0]
60snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na]
61snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
62FROM adoptopenjdk/openjdk11-openj9:latest
63COPY build/libs/snowflake-report-sync-*.jar snowflake-report-sync.jar
64RUN mkdir /encryption-keys
65COPY encryption-keys/ /encryption-keys/ #keys are picked from docker filesystem when running in container
66EXPOSE 8080
67CMD java -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar snowflake-report-sync.jar
68new JceOpenSSLPKCS8DecryptorProviderBuilder()
69 .setProvider(BouncyCastleProvider.PROVIDER_NAME) // add this line
70 .build(passphrase.toCharArray());
71
It seems OpenJ9 uses a different provider/algo selection mechanism and selects the SunJCE
's AESCipher
class as CipherSpi by default, while Hotspot selects BouncyCastleProvider
's AES
class.
Explicitly specifying the provider should work in all cases.
Alternatively, when adding the BouncyCastleProvider
you could insert it at the first preferred position (i.e. Security.insertProviderAt(new BouncyCastleProvider(), 1)
instead of Security.addProvider(new BouncyCastleProvider())
) so that it gets selected.
(It's still unclear to me why the provider selection mechanism differs between the different JVMs.)
Original post:
I've managed to reproduce the issue and at this point I'd say it's an incompatibility issue with the OpenJ9 JVM.
Starting from a Hotspot base image instead, e.g.
1-----BEGIN ENCRYPTED PRIVATE KEY-----
2MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
3MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
40IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
5mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
64pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
7s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
8uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
9zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
10iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
11tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
12b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
135m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
140YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
15Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
16PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
17UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
18LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
19vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
20D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
21h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
22NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
23SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
24jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
25q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
267TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
27PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
28h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
296A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
30-----END ENCRYPTED PRIVATE KEY-----
31 InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
32 logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
33 PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
34 Object pemObject = pemParser.readObject();
35 if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
36 // Handle the case where the private key is encrypted.
37 PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
38 InputDecryptorProvider pkcs8Prov =
39 new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
40 privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
41}
42
43InputStream resourceAsStream = null;
44 if ("local".equals(privateKeyMode)) {
45 resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
46 } else {
47 File keyFile = new File(privateKeyPath);
48 logger.info(
49 "Key file found in {} mode. FileName : {}, Exists : {}",
50 privateKeyMode,
51 keyFile.getName(),
52 keyFile.exists());
53 try {
54 resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
55 } catch (FileNotFoundException e) {
56 e.printStackTrace();
57 }
58org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream
59snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0]
60snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na]
61snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
62FROM adoptopenjdk/openjdk11-openj9:latest
63COPY build/libs/snowflake-report-sync-*.jar snowflake-report-sync.jar
64RUN mkdir /encryption-keys
65COPY encryption-keys/ /encryption-keys/ #keys are picked from docker filesystem when running in container
66EXPOSE 8080
67CMD java -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar snowflake-report-sync.jar
68new JceOpenSSLPKCS8DecryptorProviderBuilder()
69 .setProvider(BouncyCastleProvider.PROVIDER_NAME) // add this line
70 .build(passphrase.toCharArray());
71FROM adoptopenjdk:11-jre-hotspot
72
makes the code work.
(Not yet entirely sure whether the fault lies with the Docker image itself, the OpenJ9 JVM or BouncyCastle)
QUESTION
iOS CryptoSwift AES Encryption to Python Decryption works - but not the inverse
Asked 2022-Jan-28 at 10:30I am using CryptoSwift 1.4.1, iOS 15.2, PyCryptodome 3.12.0, and XCode 13.2.1 to encrypt small string messages that I send to a Raspberry Pi Linux Device over BLE. It works when iOS encrypts the message and sends it to the Raspberry Pi. The Pi can successfully decrypt it. Now I want to do the inverse, encrypt a message on the Pi and have the iOS App read and decrypt it. This, however is not working and the decrypted value is the not the message I encrypted on the Pi.
Working iOS encryption:
1func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
2 let data = stringToEncrypt.data(using: String.Encoding.utf8)
3 let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
4 return encrypted.toHexString()
5}
6
7let ivString = "4198816658388141"
8let keyString = "9004786896524916"
9
10let key = [UInt8](keyString.utf8)
11let iv = [UInt8](ivString.utf8)
12
13let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
14
Working Raspberry Pi decryption in Python:
1func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
2 let data = stringToEncrypt.data(using: String.Encoding.utf8)
3 let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
4 return encrypted.toHexString()
5}
6
7let ivString = "4198816658388141"
8let keyString = "9004786896524916"
9
10let key = [UInt8](keyString.utf8)
11let iv = [UInt8](ivString.utf8)
12
13let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
14KEY = b'9004786896524916'
15IV = b'4198816658388141'
16MODE = AES.MODE_CFB
17
18def decrypt(key, iv, encrypted_text):
19 logger.info(f"Encrypted: {encrypted_text}")
20 aes = AES.new(key, MODE, iv, segment_size=128)
21 encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
22 decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
23 logger.info(f"Decrypted: {decrypted_text}")
24 return decrypted_text
25
I tried to encrypt a message on the Pi with the following code:
1func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
2 let data = stringToEncrypt.data(using: String.Encoding.utf8)
3 let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
4 return encrypted.toHexString()
5}
6
7let ivString = "4198816658388141"
8let keyString = "9004786896524916"
9
10let key = [UInt8](keyString.utf8)
11let iv = [UInt8](ivString.utf8)
12
13let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
14KEY = b'9004786896524916'
15IV = b'4198816658388141'
16MODE = AES.MODE_CFB
17
18def decrypt(key, iv, encrypted_text):
19 logger.info(f"Encrypted: {encrypted_text}")
20 aes = AES.new(key, MODE, iv, segment_size=128)
21 encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
22 decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
23 logger.info(f"Decrypted: {decrypted_text}")
24 return decrypted_text
25KEY = b'9004786896524916'
26IV = b'4198816658388141'
27MODE = AES.MODE_CFB
28
29def encrypt(key, decrypted_text):
30 # Create cipher object and encrypt the data
31 logger.info(f"Decrypted: {decrypted_text}")
32 cipher = AES.new(key, MODE, segment_size=128) # Create a AES cipher object with the key using the mode CBC
33 #encrypted_text = cipher.encrypt(pad(decrypted_text, AES.block_size)) # Pad the input data and then encrypt
34 encrypted_text = cipher.encrypt(decrypted_text) # Pad the input data and then encrypt
35 logger.info(f"Encrypted: {encrypted_text}")
36 return encrypted_text
37 ...
38 encrypt(KEY, returnString('utf-8'))
39
However, the iOS App fails to decrypt it properly with this method:
1func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
2 let data = stringToEncrypt.data(using: String.Encoding.utf8)
3 let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
4 return encrypted.toHexString()
5}
6
7let ivString = "4198816658388141"
8let keyString = "9004786896524916"
9
10let key = [UInt8](keyString.utf8)
11let iv = [UInt8](ivString.utf8)
12
13let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
14KEY = b'9004786896524916'
15IV = b'4198816658388141'
16MODE = AES.MODE_CFB
17
18def decrypt(key, iv, encrypted_text):
19 logger.info(f"Encrypted: {encrypted_text}")
20 aes = AES.new(key, MODE, iv, segment_size=128)
21 encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
22 decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
23 logger.info(f"Decrypted: {decrypted_text}")
24 return decrypted_text
25KEY = b'9004786896524916'
26IV = b'4198816658388141'
27MODE = AES.MODE_CFB
28
29def encrypt(key, decrypted_text):
30 # Create cipher object and encrypt the data
31 logger.info(f"Decrypted: {decrypted_text}")
32 cipher = AES.new(key, MODE, segment_size=128) # Create a AES cipher object with the key using the mode CBC
33 #encrypted_text = cipher.encrypt(pad(decrypted_text, AES.block_size)) # Pad the input data and then encrypt
34 encrypted_text = cipher.encrypt(decrypted_text) # Pad the input data and then encrypt
35 logger.info(f"Encrypted: {encrypted_text}")
36 return encrypted_text
37 ...
38 encrypt(KEY, returnString('utf-8'))
39func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
40 let data = stringToDecrypt.data(using: String.Encoding.utf8)
41 let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt((data?.bytes)!)
42 return decrypted.toHexString()
43}
44let ivString = "4198816658388141"
45let keyString = "9004786896524916"
46
47let key = [UInt8](keyString.utf8)
48let iv = [UInt8](ivString.utf8)
49var message = try! aesDecrypt(stringToDecrypt: charString, key: key, iv: iv)
50
How can I get decryption to work properly in the iOS App when a message is encrypted on the Pi? Thanks.
ANSWER
Answered 2022-Jan-28 at 10:30In the encrypt()
method the IV is not considered. As in aesEncrypt()
, the IV must be passed and used when creating the AES object.
Furthermore there are bugs in the encoding: The plaintext must be UTF8 encoded and the ciphertext must be hex encoded:
1func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
2 let data = stringToEncrypt.data(using: String.Encoding.utf8)
3 let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
4 return encrypted.toHexString()
5}
6
7let ivString = "4198816658388141"
8let keyString = "9004786896524916"
9
10let key = [UInt8](keyString.utf8)
11let iv = [UInt8](ivString.utf8)
12
13let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
14KEY = b'9004786896524916'
15IV = b'4198816658388141'
16MODE = AES.MODE_CFB
17
18def decrypt(key, iv, encrypted_text):
19 logger.info(f"Encrypted: {encrypted_text}")
20 aes = AES.new(key, MODE, iv, segment_size=128)
21 encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
22 decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
23 logger.info(f"Decrypted: {decrypted_text}")
24 return decrypted_text
25KEY = b'9004786896524916'
26IV = b'4198816658388141'
27MODE = AES.MODE_CFB
28
29def encrypt(key, decrypted_text):
30 # Create cipher object and encrypt the data
31 logger.info(f"Decrypted: {decrypted_text}")
32 cipher = AES.new(key, MODE, segment_size=128) # Create a AES cipher object with the key using the mode CBC
33 #encrypted_text = cipher.encrypt(pad(decrypted_text, AES.block_size)) # Pad the input data and then encrypt
34 encrypted_text = cipher.encrypt(decrypted_text) # Pad the input data and then encrypt
35 logger.info(f"Encrypted: {encrypted_text}")
36 return encrypted_text
37 ...
38 encrypt(KEY, returnString('utf-8'))
39func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
40 let data = stringToDecrypt.data(using: String.Encoding.utf8)
41 let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt((data?.bytes)!)
42 return decrypted.toHexString()
43}
44let ivString = "4198816658388141"
45let keyString = "9004786896524916"
46
47let key = [UInt8](keyString.utf8)
48let iv = [UInt8](ivString.utf8)
49var message = try! aesDecrypt(stringToDecrypt: charString, key: key, iv: iv)
50from Crypto.Cipher import AES
51import binascii
52
53def encrypt(key, iv, plaintext):
54 cipher = AES.new(key, MODE, iv, segment_size=128)
55 plaintext_bytes = plaintext.encode("utf-8")
56 ciphertext = cipher.encrypt(plaintext_bytes)
57 ciphertext_hex = binascii.b2a_hex(ciphertext)
58 return ciphertext_hex
59
This function is the counterpart to decrypt()
, i.e. encrypt()
can be used to generate a ciphertext which can be decrypted with decrypt()
(or aesDecrypt()
).
In the iOS code there are two bugs, both concerning the encoding: The ciphertext must not be UTF8 encoded, but hex decoded. And the decrypted data must not be hex encoded, but UTF-8 decoded.
A possible fix is:
1func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
2 let data = stringToEncrypt.data(using: String.Encoding.utf8)
3 let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
4 return encrypted.toHexString()
5}
6
7let ivString = "4198816658388141"
8let keyString = "9004786896524916"
9
10let key = [UInt8](keyString.utf8)
11let iv = [UInt8](ivString.utf8)
12
13let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
14KEY = b'9004786896524916'
15IV = b'4198816658388141'
16MODE = AES.MODE_CFB
17
18def decrypt(key, iv, encrypted_text):
19 logger.info(f"Encrypted: {encrypted_text}")
20 aes = AES.new(key, MODE, iv, segment_size=128)
21 encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
22 decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
23 logger.info(f"Decrypted: {decrypted_text}")
24 return decrypted_text
25KEY = b'9004786896524916'
26IV = b'4198816658388141'
27MODE = AES.MODE_CFB
28
29def encrypt(key, decrypted_text):
30 # Create cipher object and encrypt the data
31 logger.info(f"Decrypted: {decrypted_text}")
32 cipher = AES.new(key, MODE, segment_size=128) # Create a AES cipher object with the key using the mode CBC
33 #encrypted_text = cipher.encrypt(pad(decrypted_text, AES.block_size)) # Pad the input data and then encrypt
34 encrypted_text = cipher.encrypt(decrypted_text) # Pad the input data and then encrypt
35 logger.info(f"Encrypted: {encrypted_text}")
36 return encrypted_text
37 ...
38 encrypt(KEY, returnString('utf-8'))
39func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
40 let data = stringToDecrypt.data(using: String.Encoding.utf8)
41 let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt((data?.bytes)!)
42 return decrypted.toHexString()
43}
44let ivString = "4198816658388141"
45let keyString = "9004786896524916"
46
47let key = [UInt8](keyString.utf8)
48let iv = [UInt8](ivString.utf8)
49var message = try! aesDecrypt(stringToDecrypt: charString, key: key, iv: iv)
50from Crypto.Cipher import AES
51import binascii
52
53def encrypt(key, iv, plaintext):
54 cipher = AES.new(key, MODE, iv, segment_size=128)
55 plaintext_bytes = plaintext.encode("utf-8")
56 ciphertext = cipher.encrypt(plaintext_bytes)
57 ciphertext_hex = binascii.b2a_hex(ciphertext)
58 return ciphertext_hex
59func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
60 let data = Array<UInt8>(hex: stringToDecrypt)
61 let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt(data)
62 return String(bytes: decrypted, encoding: .utf8)!
63}
64
This function is the counterpart to aesEncrypt()
, i.e. aesDecrypt()
can be used to decrypt a ciphertext generated with aesEncrypt()
(or encrypt()
).
Regarding security: A static IV is insecure. Instead, the IV should be randomly generated for each encryption. Since the (non-secret IV) is needed for decryption, it is passed along with the ciphertext (typically concatenated).
QUESTION
Use string value for argument typed as Literal
Asked 2022-Jan-26 at 17:45I use kms.decrypt() method from boto3 package. For typing support I use the boto3-stubs package.
The decrypt method has attribute EncryptionAlgorithm
, which is typed as
1EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"]
2
I parse the encryption algorithm via regular expression from input string so in my case the EncryptionAlgorithm value is str
, not a Literal. Mypy complaint for it.
I do not want to disable type check for this line and the only solution I was found is the helper method which convert the str value to literal in this way:
1EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"]
2import boto3
3from mypy_boto3_kms.literals import EncryptionAlgorithmSpecType
4
5def getEncryptionAlgorithmLiteral(algorithm: str) -> EncryptionAlgorithmSpecType:
6 result: EncryptionAlgorithmSpecType
7 if algorithm == "RSAES_OAEP_SHA_1":
8 result = "RSAES_OAEP_SHA_1"
9 elif algorithm == "RSAES_OAEP_SHA_256":
10 result = "RSAES_OAEP_SHA_256"
11 elif algorithm == "SYMMETRIC_DEFAULT":
12 result = "SYMMETRIC_DEFAULT"
13 else:
14 raise Exception(f"Unexpected algorithm '{algorithm}'. It must be one of {EncryptionAlgorithmSpecType}")
15 return result
16
17def main(binaryEncData: bytes, keyId: str, algorithm: str):
18 kms = boto3.client('kms')
19 kmsResult = kms.decrypt(CiphertextBlob=binaryEncData,
20 KeyId=keyId,
21 EncryptionAlgorithm=getEncryptionAlgorithmLiteral(algorithm))
22
23
I wonder if there is some better way how to achieve the conversion in getEncryptionAlgorithmLiteral()
method so I do not need to type all these values twice. Ideally I would like to use values directly from EncryptionAlgorithmSpecType
type instead of typing them again to my code.
ANSWER
Answered 2021-Nov-14 at 17:00You can use typing.get_args
to get the arguments passed in to typing.Literal
. In this case, you'll need to combine it with typing.cast
so you can signal to "mypy" that the string value that the function returns is an acceptable Literal
value.
1EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"]
2import boto3
3from mypy_boto3_kms.literals import EncryptionAlgorithmSpecType
4
5def getEncryptionAlgorithmLiteral(algorithm: str) -> EncryptionAlgorithmSpecType:
6 result: EncryptionAlgorithmSpecType
7 if algorithm == "RSAES_OAEP_SHA_1":
8 result = "RSAES_OAEP_SHA_1"
9 elif algorithm == "RSAES_OAEP_SHA_256":
10 result = "RSAES_OAEP_SHA_256"
11 elif algorithm == "SYMMETRIC_DEFAULT":
12 result = "SYMMETRIC_DEFAULT"
13 else:
14 raise Exception(f"Unexpected algorithm '{algorithm}'. It must be one of {EncryptionAlgorithmSpecType}")
15 return result
16
17def main(binaryEncData: bytes, keyId: str, algorithm: str):
18 kms = boto3.client('kms')
19 kmsResult = kms.decrypt(CiphertextBlob=binaryEncData,
20 KeyId=keyId,
21 EncryptionAlgorithm=getEncryptionAlgorithmLiteral(algorithm))
22
23from typing import cast
24# Import below from `typing` in Python 3.8+
25from typing_extensions import Literal, get_args
26
27
28# noinspection SpellCheckingInspection
29EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1",
30 "RSAES_OAEP_SHA_256",
31 "SYMMETRIC_DEFAULT"]
32
33_valid_algorithms = get_args(EncryptionAlgorithmSpecType)
34print(_valid_algorithms)
35
36
37def get_encryption_algorithm_literal(
38 algorithm: str) -> EncryptionAlgorithmSpecType:
39
40 if algorithm not in _valid_algorithms:
41 valid_values = str(list(_valid_algorithms)).replace("'", "")
42 raise Exception(f"Unexpected algorithm '{algorithm}'. "
43 f"It must be one of {valid_values}")
44
45 # cast string to literal, so static type checkers such as 'mypy'
46 # don't complain.
47 return cast(EncryptionAlgorithmSpecType, algorithm)
48
49
50def main():
51 # noinspection SpellCheckingInspection
52 string = 'RSAES_OAEP_SHA_256'
53
54 my_algorithm = get_encryption_algorithm_literal(string)
55 print(type(my_algorithm), my_algorithm)
56
57
58if __name__ == '__main__':
59 main()
60
Output:
1EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"]
2import boto3
3from mypy_boto3_kms.literals import EncryptionAlgorithmSpecType
4
5def getEncryptionAlgorithmLiteral(algorithm: str) -> EncryptionAlgorithmSpecType:
6 result: EncryptionAlgorithmSpecType
7 if algorithm == "RSAES_OAEP_SHA_1":
8 result = "RSAES_OAEP_SHA_1"
9 elif algorithm == "RSAES_OAEP_SHA_256":
10 result = "RSAES_OAEP_SHA_256"
11 elif algorithm == "SYMMETRIC_DEFAULT":
12 result = "SYMMETRIC_DEFAULT"
13 else:
14 raise Exception(f"Unexpected algorithm '{algorithm}'. It must be one of {EncryptionAlgorithmSpecType}")
15 return result
16
17def main(binaryEncData: bytes, keyId: str, algorithm: str):
18 kms = boto3.client('kms')
19 kmsResult = kms.decrypt(CiphertextBlob=binaryEncData,
20 KeyId=keyId,
21 EncryptionAlgorithm=getEncryptionAlgorithmLiteral(algorithm))
22
23from typing import cast
24# Import below from `typing` in Python 3.8+
25from typing_extensions import Literal, get_args
26
27
28# noinspection SpellCheckingInspection
29EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1",
30 "RSAES_OAEP_SHA_256",
31 "SYMMETRIC_DEFAULT"]
32
33_valid_algorithms = get_args(EncryptionAlgorithmSpecType)
34print(_valid_algorithms)
35
36
37def get_encryption_algorithm_literal(
38 algorithm: str) -> EncryptionAlgorithmSpecType:
39
40 if algorithm not in _valid_algorithms:
41 valid_values = str(list(_valid_algorithms)).replace("'", "")
42 raise Exception(f"Unexpected algorithm '{algorithm}'. "
43 f"It must be one of {valid_values}")
44
45 # cast string to literal, so static type checkers such as 'mypy'
46 # don't complain.
47 return cast(EncryptionAlgorithmSpecType, algorithm)
48
49
50def main():
51 # noinspection SpellCheckingInspection
52 string = 'RSAES_OAEP_SHA_256'
53
54 my_algorithm = get_encryption_algorithm_literal(string)
55 print(type(my_algorithm), my_algorithm)
56
57
58if __name__ == '__main__':
59 main()
60('RSAES_OAEP_SHA_1', 'RSAES_OAEP_SHA_256', 'SYMMETRIC_DEFAULT')
61<class 'str'> RSAES_OAEP_SHA_256
62
Result for an invalid input like 'RSAES_OAEP_SHA_2567'
:
1EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256", "SYMMETRIC_DEFAULT"]
2import boto3
3from mypy_boto3_kms.literals import EncryptionAlgorithmSpecType
4
5def getEncryptionAlgorithmLiteral(algorithm: str) -> EncryptionAlgorithmSpecType:
6 result: EncryptionAlgorithmSpecType
7 if algorithm == "RSAES_OAEP_SHA_1":
8 result = "RSAES_OAEP_SHA_1"
9 elif algorithm == "RSAES_OAEP_SHA_256":
10 result = "RSAES_OAEP_SHA_256"
11 elif algorithm == "SYMMETRIC_DEFAULT":
12 result = "SYMMETRIC_DEFAULT"
13 else:
14 raise Exception(f"Unexpected algorithm '{algorithm}'. It must be one of {EncryptionAlgorithmSpecType}")
15 return result
16
17def main(binaryEncData: bytes, keyId: str, algorithm: str):
18 kms = boto3.client('kms')
19 kmsResult = kms.decrypt(CiphertextBlob=binaryEncData,
20 KeyId=keyId,
21 EncryptionAlgorithm=getEncryptionAlgorithmLiteral(algorithm))
22
23from typing import cast
24# Import below from `typing` in Python 3.8+
25from typing_extensions import Literal, get_args
26
27
28# noinspection SpellCheckingInspection
29EncryptionAlgorithmSpecType = Literal["RSAES_OAEP_SHA_1",
30 "RSAES_OAEP_SHA_256",
31 "SYMMETRIC_DEFAULT"]
32
33_valid_algorithms = get_args(EncryptionAlgorithmSpecType)
34print(_valid_algorithms)
35
36
37def get_encryption_algorithm_literal(
38 algorithm: str) -> EncryptionAlgorithmSpecType:
39
40 if algorithm not in _valid_algorithms:
41 valid_values = str(list(_valid_algorithms)).replace("'", "")
42 raise Exception(f"Unexpected algorithm '{algorithm}'. "
43 f"It must be one of {valid_values}")
44
45 # cast string to literal, so static type checkers such as 'mypy'
46 # don't complain.
47 return cast(EncryptionAlgorithmSpecType, algorithm)
48
49
50def main():
51 # noinspection SpellCheckingInspection
52 string = 'RSAES_OAEP_SHA_256'
53
54 my_algorithm = get_encryption_algorithm_literal(string)
55 print(type(my_algorithm), my_algorithm)
56
57
58if __name__ == '__main__':
59 main()
60('RSAES_OAEP_SHA_1', 'RSAES_OAEP_SHA_256', 'SYMMETRIC_DEFAULT')
61<class 'str'> RSAES_OAEP_SHA_256
62Traceback (most recent call last):
63 ...
64 raise Exception(...)
65Exception: Unexpected algorithm 'RSAES_OAEP_SHA_2567'. It must be one of [RSAES_OAEP_SHA_1, RSAES_OAEP_SHA_256, SYMMETRIC_DEFAULT]
66
QUESTION
How do I calculate a key check value for AES-128-CBC?
Asked 2022-Jan-13 at 16:47I'm trying to implement a function in Java to calculate the key check value for a 128 bit AES encryption key. The AES128CBCEncryptor class is implementing AES/128/CBC with ISO 9797-1 M2 padding.
The only information I can find on the key check value algorithm for AES says "the KCV for an AES key is computed by encrypting 16 bytes, each with value '01'.". It does not specify how the IV should be constructed.
Here is what I have thus far, but it's not generating the expected result:
1 public String computeAesCheckValue(String key) throws InvalidKeyException,
2 IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException,
3 NoSuchAlgorithmException, NoSuchPaddingException, IOException {
4 AES128CBCEncryptor encryptor = new AES128CBCEncryptor(key);
5
6 byte[] cleartext = new byte[16];
7 byte[] iv = new byte[16];
8 for (int i = 0; i < 16; i++) {
9 cleartext[i] = (byte) 0x01;
10 iv[i] = (byte) 0x00;
11 }
12 String kcv = encryptor.encrypt(new String(cleartext, "utf-8"), Hex.encodeHexString(iv));
13
14 return (kcv != null && kcv.length() >= 6)
15 ? Hex.encodeHexString(kcv.getBytes()).substring(0, 6)
16 : null;
17 }
18
What am I missing?
ANSWER
Answered 2022-Jan-13 at 16:47For a Key Check Value (KCV) one generally uses single block encryption, without any mode such as ECB or CBC. As only a constant value of 16 bytes is used, there is no need for padding either.
If you just have a CBC class that performs ISO 9797-1 M2 padding then you could encrypt the static value of 01010101010101010101010101010101
(hex encoding of 16 bytes), using an all-zero IV and taking the first 16 bytes from the result (removing 16 bytes of ciphertext at the end that is just encryption of the mandatory padding).
As you can see in the image below, because the IV is all zero, the XOR with the plaintext leaves the input intact, basically making the first ciphertext identical to direct encryption with the block cipher.
By WhiteTimberwolf (SVG version) - PNG version, Public Domain, https://commons.wikimedia.org/w/index.php?curid=26434096
However, as you are using Java, it makes more sense to use a Cipher
object using algorithm "AES/ECB/NoPadding"
and use that to encrypt the value of 01010101010101010101010101010101
directly. ECB doesn't take an IV, so that problem is avoided. Also, no padding needs to be considered when "NoPadding"
is specified.
If you need fewer bytes: those are usually taken from the left (lowest index) of the result.
Beware that these kinds of KCV's are somewhat dangerous as they show the ciphertext of one particular plaintext block. In the worst instances, this could lead to an adversary decrypting one ciphertext block, or for an authenticated scheme to lose its integrity/authentication properties.
Commonly KCV's are over an all-zero plaintext block. Using an all one-valued block makes the chance that this happens smaller, but that chance is still significant.
QUESTION
Convert Node crypto aes-256-cbc to CryptoJS
Asked 2022-Jan-10 at 21:43How to convert the following Node's built-in crypto module encryption to CryptoJS?
1const crypto = require('crypto');
2
3const pass = 'some,password:)with>spec(chars*'
4const cipher1 = crypto.createCipher('aes-256-cbc', pass)
5const c1 = cipher1.update(input, 'utf8', 'hex') + cipher1.final('hex')
6
I tried something like this, but the results are not the same:
1const crypto = require('crypto');
2
3const pass = 'some,password:)with>spec(chars*'
4const cipher1 = crypto.createCipher('aes-256-cbc', pass)
5const c1 = cipher1.update(input, 'utf8', 'hex') + cipher1.final('hex')
6const CryptoJS = require('crypto-js');
7
8const pass = 'some,password:)with>spec(chars*'
9const cipher2 = CryptoJS.AES.encrypt(input, pass, {
10 mode: CryptoJS.mode.CBC,
11});
12const c2 = cipher2.ciphertext.toString(CryptoJS.enc.Hex);
13
I need this to use as a Postman prerequest script as it does not support Node's crypto
, but crypto-js
.
ANSWER
Answered 2022-Jan-10 at 21:43Both codes use the OpenSSL proprietary key derivation function EVP_BytesToKey()
with an iteration count of 1 and MD5 as digest.
NodeJS does not use a salt, while CryptoJS applies a random salt. For this reason, the NodeJS result is unchanged for each encryption, while the CryptoJS result always changes (assuming the same plaintext and passphrase).
Thus, to get the result of the NodeJS code with the CryptoJS code, you must not use a salt. However, by default, a salt is always applied. This can only be circumvented by explicitly determining key and IV with the key derivation function EvpKDF
and then using both in the encryption:
1const crypto = require('crypto');
2
3const pass = 'some,password:)with>spec(chars*'
4const cipher1 = crypto.createCipher('aes-256-cbc', pass)
5const c1 = cipher1.update(input, 'utf8', 'hex') + cipher1.final('hex')
6const CryptoJS = require('crypto-js');
7
8const pass = 'some,password:)with>spec(chars*'
9const cipher2 = CryptoJS.AES.encrypt(input, pass, {
10 mode: CryptoJS.mode.CBC,
11});
12const c2 = cipher2.ciphertext.toString(CryptoJS.enc.Hex);
13var input = "The quick brown fox jumps over the lazy dog";
14var pass = 'some,password:)with>spec(chars*'
15
16var keySize = 32/4;
17var ivSize = 16/4;
18var kdf = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize, hasher: CryptoJS.algo.MD5 }).compute(pass, ''); // no salt!
19var key = CryptoJS.lib.WordArray.create(kdf.words.slice(0, keySize), keySize * 4);
20var iv = CryptoJS.lib.WordArray.create(kdf.words.slice(keySize), ivSize * 4);
21var ciphertextCP = CryptoJS.AES.encrypt(input, key, {iv: iv}); // default: CBC, PKCS#7 padding
22var ciphertext = ciphertextCP.ciphertext.toString(CryptoJS.enc.Hex);
23document.getElementById("ct").innerHTML = ciphertext; // d98cf2d285bf0c1d796226190bf54d9c5540300ee1c6f35618f8bb3564b5053920ec958d31b41bbe4e4880e23543d709
1const crypto = require('crypto');
2
3const pass = 'some,password:)with>spec(chars*'
4const cipher1 = crypto.createCipher('aes-256-cbc', pass)
5const c1 = cipher1.update(input, 'utf8', 'hex') + cipher1.final('hex')
6const CryptoJS = require('crypto-js');
7
8const pass = 'some,password:)with>spec(chars*'
9const cipher2 = CryptoJS.AES.encrypt(input, pass, {
10 mode: CryptoJS.mode.CBC,
11});
12const c2 = cipher2.ciphertext.toString(CryptoJS.enc.Hex);
13var input = "The quick brown fox jumps over the lazy dog";
14var pass = 'some,password:)with>spec(chars*'
15
16var keySize = 32/4;
17var ivSize = 16/4;
18var kdf = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize, hasher: CryptoJS.algo.MD5 }).compute(pass, ''); // no salt!
19var key = CryptoJS.lib.WordArray.create(kdf.words.slice(0, keySize), keySize * 4);
20var iv = CryptoJS.lib.WordArray.create(kdf.words.slice(keySize), ivSize * 4);
21var ciphertextCP = CryptoJS.AES.encrypt(input, key, {iv: iv}); // default: CBC, PKCS#7 padding
22var ciphertext = ciphertextCP.ciphertext.toString(CryptoJS.enc.Hex);
23document.getElementById("ct").innerHTML = ciphertext; // d98cf2d285bf0c1d796226190bf54d9c5540300ee1c6f35618f8bb3564b5053920ec958d31b41bbe4e4880e23543d709<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
24<p style="font-family:'Courier New', monospace;" id="ct"></p>
This CryptoJS code produces the same ciphertext for the same plaintext and passphrase as the NodeJS code.
Note that the key derivation with EVP_BytesToKey()
and the chosen parameters is deprecated and considered insecure today. This is true for NodeJS to a greater extent than for CryptoJS, due to the lack of a salt.
It is more secure to avoid the built-in key derivation function and specify the key directly.
To do this, use createCipheriv()
in NodeJS and pass the key as WordArray
in the CryptoJS code. This way, a random IV must be explicitly generated for each encryption.
Optionally, a reliable key derivation function like PBKDF2 can be used, which is supported by both libraries.
QUESTION
Problem Updating to .Net 6 - Encrypting String
Asked 2021-Dec-20 at 23:09I'm using a string Encryption/Decryption class similar to the one provided here as a solution.
This worked well for me in .Net 5.
Now I wanted to update my project to .Net 6.
When using .Net 6, the decrypted string does get cut off a certain point depending on the length of the input string.
▶️ To make it easy to debug/reproduce my issue, I created a public repro Repository here.
- The encryption code is on purpose in a Standard 2.0 Project.
- Referencing this project are both a .Net 6 as well as a .Net 5 Console project.
Both are calling the encryption methods with the exact same input of "12345678901234567890"
with the path phrase of "nzv86ri4H2qYHqc&m6rL"
.
.Net 5 output: "12345678901234567890"
.Net 6 output: "1234567890123456"
The difference in length is 4
.
I also looked at the breaking changes for .Net 6, but could not find something which guided me to a solution.
I'm glad for any suggestions regarding my issue, thanks!
Encryption Class
1public static class StringCipher
2{
3 // This constant is used to determine the keysize of the encryption algorithm in bits.
4 // We divide this by 8 within the code below to get the equivalent number of bytes.
5 private const int Keysize = 128;
6
7 // This constant determines the number of iterations for the password bytes generation function.
8 private const int DerivationIterations = 1000;
9
10 public static string Encrypt(string plainText, string passPhrase)
11 {
12 // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
13 // so that the same Salt and IV values can be used when decrypting.
14 var saltStringBytes = Generate128BitsOfRandomEntropy();
15 var ivStringBytes = Generate128BitsOfRandomEntropy();
16 var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
17 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
18 {
19 var keyBytes = password.GetBytes(Keysize / 8);
20 using (var symmetricKey = Aes.Create())
21 {
22 symmetricKey.BlockSize = 128;
23 symmetricKey.Mode = CipherMode.CBC;
24 symmetricKey.Padding = PaddingMode.PKCS7;
25 using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
26 {
27 using (var memoryStream = new MemoryStream())
28 {
29 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
30 {
31 cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
32 cryptoStream.FlushFinalBlock();
33 // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
34 var cipherTextBytes = saltStringBytes;
35 cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
36 cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
37 memoryStream.Close();
38 cryptoStream.Close();
39 return Convert.ToBase64String(cipherTextBytes);
40 }
41 }
42 }
43 }
44 }
45 }
46
47 public static string Decrypt(string cipherText, string passPhrase)
48 {
49 // Get the complete stream of bytes that represent:
50 // [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
51 var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
52 // Get the saltbytes by extracting the first 16 bytes from the supplied cipherText bytes.
53 var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
54 // Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
55 var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
56 // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
57 var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
58
59 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
60 {
61 var keyBytes = password.GetBytes(Keysize / 8);
62 using (var symmetricKey = Aes.Create())
63 {
64 symmetricKey.BlockSize = 128;
65 symmetricKey.Mode = CipherMode.CBC;
66 symmetricKey.Padding = PaddingMode.PKCS7;
67 using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
68 {
69 using (var memoryStream = new MemoryStream(cipherTextBytes))
70 {
71 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
72 {
73 var plainTextBytes = new byte[cipherTextBytes.Length];
74 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
75 memoryStream.Close();
76 cryptoStream.Close();
77 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
78 }
79 }
80 }
81 }
82 }
83 }
84
85 private static byte[] Generate128BitsOfRandomEntropy()
86 {
87 var randomBytes = new byte[16]; // 16 Bytes will give us 128 bits.
88 using (var rngCsp = RandomNumberGenerator.Create())
89 {
90 // Fill the array with cryptographically secure random bytes.
91 rngCsp.GetBytes(randomBytes);
92 }
93 return randomBytes;
94 }
95}
96
Calling code
1public static class StringCipher
2{
3 // This constant is used to determine the keysize of the encryption algorithm in bits.
4 // We divide this by 8 within the code below to get the equivalent number of bytes.
5 private const int Keysize = 128;
6
7 // This constant determines the number of iterations for the password bytes generation function.
8 private const int DerivationIterations = 1000;
9
10 public static string Encrypt(string plainText, string passPhrase)
11 {
12 // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
13 // so that the same Salt and IV values can be used when decrypting.
14 var saltStringBytes = Generate128BitsOfRandomEntropy();
15 var ivStringBytes = Generate128BitsOfRandomEntropy();
16 var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
17 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
18 {
19 var keyBytes = password.GetBytes(Keysize / 8);
20 using (var symmetricKey = Aes.Create())
21 {
22 symmetricKey.BlockSize = 128;
23 symmetricKey.Mode = CipherMode.CBC;
24 symmetricKey.Padding = PaddingMode.PKCS7;
25 using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
26 {
27 using (var memoryStream = new MemoryStream())
28 {
29 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
30 {
31 cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
32 cryptoStream.FlushFinalBlock();
33 // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
34 var cipherTextBytes = saltStringBytes;
35 cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
36 cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
37 memoryStream.Close();
38 cryptoStream.Close();
39 return Convert.ToBase64String(cipherTextBytes);
40 }
41 }
42 }
43 }
44 }
45 }
46
47 public static string Decrypt(string cipherText, string passPhrase)
48 {
49 // Get the complete stream of bytes that represent:
50 // [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
51 var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
52 // Get the saltbytes by extracting the first 16 bytes from the supplied cipherText bytes.
53 var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
54 // Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
55 var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
56 // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
57 var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
58
59 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
60 {
61 var keyBytes = password.GetBytes(Keysize / 8);
62 using (var symmetricKey = Aes.Create())
63 {
64 symmetricKey.BlockSize = 128;
65 symmetricKey.Mode = CipherMode.CBC;
66 symmetricKey.Padding = PaddingMode.PKCS7;
67 using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
68 {
69 using (var memoryStream = new MemoryStream(cipherTextBytes))
70 {
71 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
72 {
73 var plainTextBytes = new byte[cipherTextBytes.Length];
74 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
75 memoryStream.Close();
76 cryptoStream.Close();
77 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
78 }
79 }
80 }
81 }
82 }
83 }
84
85 private static byte[] Generate128BitsOfRandomEntropy()
86 {
87 var randomBytes = new byte[16]; // 16 Bytes will give us 128 bits.
88 using (var rngCsp = RandomNumberGenerator.Create())
89 {
90 // Fill the array with cryptographically secure random bytes.
91 rngCsp.GetBytes(randomBytes);
92 }
93 return randomBytes;
94 }
95}
96var input = "12345678901234567890";
97var inputLength = input.Length;
98var inputBytes = Encoding.UTF8.GetBytes(input);
99
100var encrypted = StringCipher.Encrypt(input, "nzv86ri4H2qYHqc&m6rL");
101
102var output = StringCipher.Decrypt(encrypted, "nzv86ri4H2qYHqc&m6rL");
103var outputLength = output.Length;
104var outputBytes = Encoding.UTF8.GetBytes(output);
105
106var lengthDiff = inputLength - outputLength;
107
ANSWER
Answered 2021-Nov-10 at 10:25The reason is this breaking change:
DeflateStream, GZipStream, and CryptoStream diverged from typical Stream.Read and Stream.ReadAsync behavior in two ways:
They didn't complete the read operation until either the buffer passed to the read operation was completely filled or the end of the stream was reached.
And the new behaviour is:
Starting in .NET 6, when Stream.Read or Stream.ReadAsync is called on one of the affected stream types with a buffer of length N, the operation completes when:
At least one byte has been read from the stream, or The underlying stream they wrap returns 0 from a call to its read, indicating no more data is available.
In your case you are affected because of this code in Decrypt
method:
1public static class StringCipher
2{
3 // This constant is used to determine the keysize of the encryption algorithm in bits.
4 // We divide this by 8 within the code below to get the equivalent number of bytes.
5 private const int Keysize = 128;
6
7 // This constant determines the number of iterations for the password bytes generation function.
8 private const int DerivationIterations = 1000;
9
10 public static string Encrypt(string plainText, string passPhrase)
11 {
12 // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
13 // so that the same Salt and IV values can be used when decrypting.
14 var saltStringBytes = Generate128BitsOfRandomEntropy();
15 var ivStringBytes = Generate128BitsOfRandomEntropy();
16 var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
17 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
18 {
19 var keyBytes = password.GetBytes(Keysize / 8);
20 using (var symmetricKey = Aes.Create())
21 {
22 symmetricKey.BlockSize = 128;
23 symmetricKey.Mode = CipherMode.CBC;
24 symmetricKey.Padding = PaddingMode.PKCS7;
25 using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
26 {
27 using (var memoryStream = new MemoryStream())
28 {
29 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
30 {
31 cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
32 cryptoStream.FlushFinalBlock();
33 // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
34 var cipherTextBytes = saltStringBytes;
35 cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
36 cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
37 memoryStream.Close();
38 cryptoStream.Close();
39 return Convert.ToBase64String(cipherTextBytes);
40 }
41 }
42 }
43 }
44 }
45 }
46
47 public static string Decrypt(string cipherText, string passPhrase)
48 {
49 // Get the complete stream of bytes that represent:
50 // [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
51 var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
52 // Get the saltbytes by extracting the first 16 bytes from the supplied cipherText bytes.
53 var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
54 // Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
55 var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
56 // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
57 var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
58
59 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
60 {
61 var keyBytes = password.GetBytes(Keysize / 8);
62 using (var symmetricKey = Aes.Create())
63 {
64 symmetricKey.BlockSize = 128;
65 symmetricKey.Mode = CipherMode.CBC;
66 symmetricKey.Padding = PaddingMode.PKCS7;
67 using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
68 {
69 using (var memoryStream = new MemoryStream(cipherTextBytes))
70 {
71 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
72 {
73 var plainTextBytes = new byte[cipherTextBytes.Length];
74 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
75 memoryStream.Close();
76 cryptoStream.Close();
77 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
78 }
79 }
80 }
81 }
82 }
83 }
84
85 private static byte[] Generate128BitsOfRandomEntropy()
86 {
87 var randomBytes = new byte[16]; // 16 Bytes will give us 128 bits.
88 using (var rngCsp = RandomNumberGenerator.Create())
89 {
90 // Fill the array with cryptographically secure random bytes.
91 rngCsp.GetBytes(randomBytes);
92 }
93 return randomBytes;
94 }
95}
96var input = "12345678901234567890";
97var inputLength = input.Length;
98var inputBytes = Encoding.UTF8.GetBytes(input);
99
100var encrypted = StringCipher.Encrypt(input, "nzv86ri4H2qYHqc&m6rL");
101
102var output = StringCipher.Decrypt(encrypted, "nzv86ri4H2qYHqc&m6rL");
103var outputLength = output.Length;
104var outputBytes = Encoding.UTF8.GetBytes(output);
105
106var lengthDiff = inputLength - outputLength;
107using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
108{
109 var plainTextBytes = new byte[cipherTextBytes.Length];
110 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
111 memoryStream.Close();
112 cryptoStream.Close();
113 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
114}
115
You do not check how much bytes Read
actually read and whether it read them all. You could get away with this in previous versions of .NET because as mentioned CryptoStream
behaviour was different from other streams, and because your buffer length is enough to hold all data. However, this is no longer the case and you need to check it as you would do for other streams. Or even better - just use CopyTo
:
1public static class StringCipher
2{
3 // This constant is used to determine the keysize of the encryption algorithm in bits.
4 // We divide this by 8 within the code below to get the equivalent number of bytes.
5 private const int Keysize = 128;
6
7 // This constant determines the number of iterations for the password bytes generation function.
8 private const int DerivationIterations = 1000;
9
10 public static string Encrypt(string plainText, string passPhrase)
11 {
12 // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
13 // so that the same Salt and IV values can be used when decrypting.
14 var saltStringBytes = Generate128BitsOfRandomEntropy();
15 var ivStringBytes = Generate128BitsOfRandomEntropy();
16 var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
17 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
18 {
19 var keyBytes = password.GetBytes(Keysize / 8);
20 using (var symmetricKey = Aes.Create())
21 {
22 symmetricKey.BlockSize = 128;
23 symmetricKey.Mode = CipherMode.CBC;
24 symmetricKey.Padding = PaddingMode.PKCS7;
25 using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
26 {
27 using (var memoryStream = new MemoryStream())
28 {
29 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
30 {
31 cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
32 cryptoStream.FlushFinalBlock();
33 // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
34 var cipherTextBytes = saltStringBytes;
35 cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
36 cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
37 memoryStream.Close();
38 cryptoStream.Close();
39 return Convert.ToBase64String(cipherTextBytes);
40 }
41 }
42 }
43 }
44 }
45 }
46
47 public static string Decrypt(string cipherText, string passPhrase)
48 {
49 // Get the complete stream of bytes that represent:
50 // [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
51 var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
52 // Get the saltbytes by extracting the first 16 bytes from the supplied cipherText bytes.
53 var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
54 // Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
55 var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
56 // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
57 var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
58
59 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
60 {
61 var keyBytes = password.GetBytes(Keysize / 8);
62 using (var symmetricKey = Aes.Create())
63 {
64 symmetricKey.BlockSize = 128;
65 symmetricKey.Mode = CipherMode.CBC;
66 symmetricKey.Padding = PaddingMode.PKCS7;
67 using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
68 {
69 using (var memoryStream = new MemoryStream(cipherTextBytes))
70 {
71 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
72 {
73 var plainTextBytes = new byte[cipherTextBytes.Length];
74 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
75 memoryStream.Close();
76 cryptoStream.Close();
77 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
78 }
79 }
80 }
81 }
82 }
83 }
84
85 private static byte[] Generate128BitsOfRandomEntropy()
86 {
87 var randomBytes = new byte[16]; // 16 Bytes will give us 128 bits.
88 using (var rngCsp = RandomNumberGenerator.Create())
89 {
90 // Fill the array with cryptographically secure random bytes.
91 rngCsp.GetBytes(randomBytes);
92 }
93 return randomBytes;
94 }
95}
96var input = "12345678901234567890";
97var inputLength = input.Length;
98var inputBytes = Encoding.UTF8.GetBytes(input);
99
100var encrypted = StringCipher.Encrypt(input, "nzv86ri4H2qYHqc&m6rL");
101
102var output = StringCipher.Decrypt(encrypted, "nzv86ri4H2qYHqc&m6rL");
103var outputLength = output.Length;
104var outputBytes = Encoding.UTF8.GetBytes(output);
105
106var lengthDiff = inputLength - outputLength;
107using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
108{
109 var plainTextBytes = new byte[cipherTextBytes.Length];
110 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
111 memoryStream.Close();
112 cryptoStream.Close();
113 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
114}
115using (var plainTextStream = new MemoryStream())
116{
117 cryptoStream.CopyTo(plainTextStream);
118 var plainTextBytes = plainTextStream.ToArray();
119 return Encoding.UTF8.GetString(plainTextBytes, 0, plainTextBytes.Length);
120}
121
Or even better as another answer suggests, since you decrypt UTF8 text:
1public static class StringCipher
2{
3 // This constant is used to determine the keysize of the encryption algorithm in bits.
4 // We divide this by 8 within the code below to get the equivalent number of bytes.
5 private const int Keysize = 128;
6
7 // This constant determines the number of iterations for the password bytes generation function.
8 private const int DerivationIterations = 1000;
9
10 public static string Encrypt(string plainText, string passPhrase)
11 {
12 // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
13 // so that the same Salt and IV values can be used when decrypting.
14 var saltStringBytes = Generate128BitsOfRandomEntropy();
15 var ivStringBytes = Generate128BitsOfRandomEntropy();
16 var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
17 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
18 {
19 var keyBytes = password.GetBytes(Keysize / 8);
20 using (var symmetricKey = Aes.Create())
21 {
22 symmetricKey.BlockSize = 128;
23 symmetricKey.Mode = CipherMode.CBC;
24 symmetricKey.Padding = PaddingMode.PKCS7;
25 using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
26 {
27 using (var memoryStream = new MemoryStream())
28 {
29 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
30 {
31 cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
32 cryptoStream.FlushFinalBlock();
33 // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
34 var cipherTextBytes = saltStringBytes;
35 cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
36 cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
37 memoryStream.Close();
38 cryptoStream.Close();
39 return Convert.ToBase64String(cipherTextBytes);
40 }
41 }
42 }
43 }
44 }
45 }
46
47 public static string Decrypt(string cipherText, string passPhrase)
48 {
49 // Get the complete stream of bytes that represent:
50 // [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
51 var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
52 // Get the saltbytes by extracting the first 16 bytes from the supplied cipherText bytes.
53 var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
54 // Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
55 var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
56 // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
57 var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
58
59 using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
60 {
61 var keyBytes = password.GetBytes(Keysize / 8);
62 using (var symmetricKey = Aes.Create())
63 {
64 symmetricKey.BlockSize = 128;
65 symmetricKey.Mode = CipherMode.CBC;
66 symmetricKey.Padding = PaddingMode.PKCS7;
67 using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
68 {
69 using (var memoryStream = new MemoryStream(cipherTextBytes))
70 {
71 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
72 {
73 var plainTextBytes = new byte[cipherTextBytes.Length];
74 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
75 memoryStream.Close();
76 cryptoStream.Close();
77 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
78 }
79 }
80 }
81 }
82 }
83 }
84
85 private static byte[] Generate128BitsOfRandomEntropy()
86 {
87 var randomBytes = new byte[16]; // 16 Bytes will give us 128 bits.
88 using (var rngCsp = RandomNumberGenerator.Create())
89 {
90 // Fill the array with cryptographically secure random bytes.
91 rngCsp.GetBytes(randomBytes);
92 }
93 return randomBytes;
94 }
95}
96var input = "12345678901234567890";
97var inputLength = input.Length;
98var inputBytes = Encoding.UTF8.GetBytes(input);
99
100var encrypted = StringCipher.Encrypt(input, "nzv86ri4H2qYHqc&m6rL");
101
102var output = StringCipher.Decrypt(encrypted, "nzv86ri4H2qYHqc&m6rL");
103var outputLength = output.Length;
104var outputBytes = Encoding.UTF8.GetBytes(output);
105
106var lengthDiff = inputLength - outputLength;
107using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
108{
109 var plainTextBytes = new byte[cipherTextBytes.Length];
110 var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
111 memoryStream.Close();
112 cryptoStream.Close();
113 return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
114}
115using (var plainTextStream = new MemoryStream())
116{
117 cryptoStream.CopyTo(plainTextStream);
118 var plainTextBytes = plainTextStream.ToArray();
119 return Encoding.UTF8.GetString(plainTextBytes, 0, plainTextBytes.Length);
120}
121using (var plainTextReader = new StreamReader(cryptoStream))
122{
123 return plainTextReader.ReadToEnd();
124}
125
QUESTION
convert base-64 spki string into public key
Asked 2021-Dec-17 at 18:59I'm trying to find a python equivalent of this js function:
1/**
2* Generating the shared secret with the merchant private key and the ephemeral public key(part of the payment token data)
3* using Elliptic Curve Diffie-Hellman (id-ecDH 1.3.132.1.12).
4* As the Apple Pay certificate is issued using prime256v1 encryption, create elliptic curve key instances using the package - https://www.npmjs.com/package/ec-key
5*/
6sharedSecret (privatePem) {
7 const prv = new ECKey(privatePem, 'pem') // Create a new ECkey instance from PEM formatted string
8 const publicEc = new ECKey(this.ephemeralPublicKey, 'spki') // Create a new ECKey instance from a base-64 spki string
9 return prv.computeSecret(publicEc).toString('hex') // Compute secret using private key for provided ephemeral public key
10 }
11
public key i try to convert: (should be a base-64 spki string?)
1/**
2* Generating the shared secret with the merchant private key and the ephemeral public key(part of the payment token data)
3* using Elliptic Curve Diffie-Hellman (id-ecDH 1.3.132.1.12).
4* As the Apple Pay certificate is issued using prime256v1 encryption, create elliptic curve key instances using the package - https://www.npmjs.com/package/ec-key
5*/
6sharedSecret (privatePem) {
7 const prv = new ECKey(privatePem, 'pem') // Create a new ECkey instance from PEM formatted string
8 const publicEc = new ECKey(this.ephemeralPublicKey, 'spki') // Create a new ECKey instance from a base-64 spki string
9 return prv.computeSecret(publicEc).toString('hex') // Compute secret using private key for provided ephemeral public key
10 }
11MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYtpZKqPDqavs4KzNnMoxWdIThKe/ErKMI/l34Y9/xVkt4DU4BrCaQnGLlRGx+Pn/WHPkQg3BYoRH4xUWswNhEA==
12
What i manage to do:
1/**
2* Generating the shared secret with the merchant private key and the ephemeral public key(part of the payment token data)
3* using Elliptic Curve Diffie-Hellman (id-ecDH 1.3.132.1.12).
4* As the Apple Pay certificate is issued using prime256v1 encryption, create elliptic curve key instances using the package - https://www.npmjs.com/package/ec-key
5*/
6sharedSecret (privatePem) {
7 const prv = new ECKey(privatePem, 'pem') // Create a new ECkey instance from PEM formatted string
8 const publicEc = new ECKey(this.ephemeralPublicKey, 'spki') // Create a new ECKey instance from a base-64 spki string
9 return prv.computeSecret(publicEc).toString('hex') // Compute secret using private key for provided ephemeral public key
10 }
11MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYtpZKqPDqavs4KzNnMoxWdIThKe/ErKMI/l34Y9/xVkt4DU4BrCaQnGLlRGx+Pn/WHPkQg3BYoRH4xUWswNhEA==
12from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, EllipticCurvePublicKey, ECDH
13from cryptography.hazmat.primitives.serialization import load_pem_private_key
14
15def __compute_shared_secret(ephemeral_public_key: str) -> bytes:
16 curve = SECP256R1()
17 key = base64.b64decode(ephemeral_public_key)
18 public_key = EllipticCurvePublicKey.from_encoded_point(curve, key) # problem here
19 server_private_key = load_pem_private_key(<private_key>, password=None)
20 shared_secret = server_private_key.exchange(ECDH(), public_key)
21 return shared_secret
22
1/**
2* Generating the shared secret with the merchant private key and the ephemeral public key(part of the payment token data)
3* using Elliptic Curve Diffie-Hellman (id-ecDH 1.3.132.1.12).
4* As the Apple Pay certificate is issued using prime256v1 encryption, create elliptic curve key instances using the package - https://www.npmjs.com/package/ec-key
5*/
6sharedSecret (privatePem) {
7 const prv = new ECKey(privatePem, 'pem') // Create a new ECkey instance from PEM formatted string
8 const publicEc = new ECKey(this.ephemeralPublicKey, 'spki') // Create a new ECKey instance from a base-64 spki string
9 return prv.computeSecret(publicEc).toString('hex') // Compute secret using private key for provided ephemeral public key
10 }
11MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYtpZKqPDqavs4KzNnMoxWdIThKe/ErKMI/l34Y9/xVkt4DU4BrCaQnGLlRGx+Pn/WHPkQg3BYoRH4xUWswNhEA==
12from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, EllipticCurvePublicKey, ECDH
13from cryptography.hazmat.primitives.serialization import load_pem_private_key
14
15def __compute_shared_secret(ephemeral_public_key: str) -> bytes:
16 curve = SECP256R1()
17 key = base64.b64decode(ephemeral_public_key)
18 public_key = EllipticCurvePublicKey.from_encoded_point(curve, key) # problem here
19 server_private_key = load_pem_private_key(<private_key>, password=None)
20 shared_secret = server_private_key.exchange(ECDH(), public_key)
21 return shared_secret
22ValueError: Unsupported elliptic curve point type
23
From what i understand i need to convert the public key to something before using it in EllipticCurvePublicKey, but i can't figure what type of conversion i should do.
ANSWER
Answered 2021-Dec-17 at 18:59According to the documentation of the JavaScript library the line
1/**
2* Generating the shared secret with the merchant private key and the ephemeral public key(part of the payment token data)
3* using Elliptic Curve Diffie-Hellman (id-ecDH 1.3.132.1.12).
4* As the Apple Pay certificate is issued using prime256v1 encryption, create elliptic curve key instances using the package - https://www.npmjs.com/package/ec-key
5*/
6sharedSecret (privatePem) {
7 const prv = new ECKey(privatePem, 'pem') // Create a new ECkey instance from PEM formatted string
8 const publicEc = new ECKey(this.ephemeralPublicKey, 'spki') // Create a new ECKey instance from a base-64 spki string
9 return prv.computeSecret(publicEc).toString('hex') // Compute secret using private key for provided ephemeral public key
10 }
11MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYtpZKqPDqavs4KzNnMoxWdIThKe/ErKMI/l34Y9/xVkt4DU4BrCaQnGLlRGx+Pn/WHPkQg3BYoRH4xUWswNhEA==
12from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, EllipticCurvePublicKey, ECDH
13from cryptography.hazmat.primitives.serialization import load_pem_private_key
14
15def __compute_shared_secret(ephemeral_public_key: str) -> bytes:
16 curve = SECP256R1()
17 key = base64.b64decode(ephemeral_public_key)
18 public_key = EllipticCurvePublicKey.from_encoded_point(curve, key) # problem here
19 server_private_key = load_pem_private_key(<private_key>, password=None)
20 shared_secret = server_private_key.exchange(ECDH(), public_key)
21 return shared_secret
22ValueError: Unsupported elliptic curve point type
23const publicEc = new ECKey(this.ephemeralPublicKey, 'spki')
24
imports a Base64 encoded X.509/SPKI DER key.
In Python, this can be done with load_der_public_key()
of the Cryptography library as follows:
1/**
2* Generating the shared secret with the merchant private key and the ephemeral public key(part of the payment token data)
3* using Elliptic Curve Diffie-Hellman (id-ecDH 1.3.132.1.12).
4* As the Apple Pay certificate is issued using prime256v1 encryption, create elliptic curve key instances using the package - https://www.npmjs.com/package/ec-key
5*/
6sharedSecret (privatePem) {
7 const prv = new ECKey(privatePem, 'pem') // Create a new ECkey instance from PEM formatted string
8 const publicEc = new ECKey(this.ephemeralPublicKey, 'spki') // Create a new ECKey instance from a base-64 spki string
9 return prv.computeSecret(publicEc).toString('hex') // Compute secret using private key for provided ephemeral public key
10 }
11MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYtpZKqPDqavs4KzNnMoxWdIThKe/ErKMI/l34Y9/xVkt4DU4BrCaQnGLlRGx+Pn/WHPkQg3BYoRH4xUWswNhEA==
12from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1, EllipticCurvePublicKey, ECDH
13from cryptography.hazmat.primitives.serialization import load_pem_private_key
14
15def __compute_shared_secret(ephemeral_public_key: str) -> bytes:
16 curve = SECP256R1()
17 key = base64.b64decode(ephemeral_public_key)
18 public_key = EllipticCurvePublicKey.from_encoded_point(curve, key) # problem here
19 server_private_key = load_pem_private_key(<private_key>, password=None)
20 shared_secret = server_private_key.exchange(ECDH(), public_key)
21 return shared_secret
22ValueError: Unsupported elliptic curve point type
23const publicEc = new ECKey(this.ephemeralPublicKey, 'spki')
24from cryptography.hazmat.primitives.serialization import load_der_public_key
25import base64
26...
27public_key = load_der_public_key(base64.b64decode(ephemeral_public_key))
28
Here, ephemeral_public_key
is the Base64 encoded X.509/SPKI DER key.
With this change of the Python code the shared secret can be determined.
QUESTION
Data Encryption static encrypt
Asked 2021-Dec-13 at 08:04My hexidigit is changing on day by day basis. How can I change it back to static
Code
1from Crypto.Cipher import AES
2import pandas as pd
3import mysql.connector
4
5myconn = mysql.connector.connect(host="######", user="##", password="######", database="#######")
6query = """SELECT * from table """
7df = pd.read_sql(query, myconn) #getting hexidigit back from the SQL server after dumping the ecrypted data into the database
8
9def resize_length(string):
10 #resizes the String to a size divisible by 16 (needed for this Cipher)
11 return string.rjust((len(string) // 16 + 1) * 16)
12
13def encrypt(url, cipher):
14 # Converts the string to bytes and encodes them with your Cipher
15 cipherstring = cipher.encrypt(resize_length(url).encode())
16 cipherstring = "".join("{:02x}".format(c) for c in cipherstring)
17 return cipherstring
18
19def decrypt(text, cipher):
20 # Converts the string to bytes and decodes them with your Cipher
21 text = bytes.fromhex(text)
22 original_url = cipher.decrypt(text).decode().lstrip()
23 return original_url
24
25# It is important to use 2 ciphers with the same information, else the system breaks
26# Define the Cipher with your data (Encryption Key and IV)
27cipher1 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
28cipher2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
29message = df['values'][4]
30eypt = encrypt(message, cipher1)
31print(decrypt(eypt, cipher2))
32
I'm able to decrypt the string after calling from database but on the next day the encrypted string changes which fails my code. How can I freeze this? Keeping a constant string everyday?
ANSWER
Answered 2021-Dec-13 at 08:04I got the solution by encrypting the key using bytes() Use the byte method to store the key in secured config file or database and encrypt the byte string to get the key. After that use any cipher method with suitable algorithm to encrypt the data and mask it.
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in Encryption
Tutorials and Learning Resources are not available at this moment for Encryption