Reputation: 622
JWTs have 3 parts:
Is it possible to encrypt the payload? Following is my token's payload:
{
"iss": "joe",
"exp": "1300819380",
"data": {
"id": "12",
"userName": "PH",
"qntRed": "7",
"qntGrad": {
"1": "800",
"2": "858",
"3": "950",
"4": "745",
"5": "981"
}
}
If "qntGrad" contains sensitive data. Can I encrypt it using the secret key? Will it still be a valid JWT?
Upvotes: 23
Views: 29248
Reputation: 11
other very simple and effective method for encrypting payload using hashing and xor encoding and mix with timestamp
be helpful it..
import jwt
import base64
from datetime import datetime
import hashlib
# Get the current timestamp in seconds
def get_current_unix_timestamp():
return str(int(datetime.now().timestamp()))
# Convert the current Unix timestamp to a human-readable format
def get_human_readable_timestamp(timestamp):
current_datetime = datetime.fromtimestamp(int(timestamp))
return current_datetime.strftime("%Y-%m-%d %H:%M:%S")
# Encode the user ID with the timestamp using XOR operation
def encode_userid_with_timestamp(userid, current_unix_timestamp, secret_key):
# Hash the timestamp and trim to 32 characters
hashed_timestamp = hashlib.sha256((current_unix_timestamp + secret_key.decode()).encode()).hexdigest()[:32]
# Combine the hashed timestamp with the user ID
data = userid + "|" + hashed_timestamp
data_bytes = data.encode()
# Perform XOR operation
repeated_key = secret_key * ((len(data_bytes) // len(secret_key)) + 1)
repeated_key = repeated_key[:len(data_bytes)]
encoded_data_bytes = bytes([a ^ b for a, b in zip(data_bytes, repeated_key)])
# Encode the result in Base64 and return
encoded_data = base64.b64encode(encoded_data_bytes).decode()
return encoded_data
# Decode the XOR-encoded data
def decode_userid_timestamp(encoded_data, key):
# Decode from Base64
encoded_data_bytes = base64.b64decode(encoded_data.encode())
# Perform XOR operation
repeated_key = key * ((len(encoded_data_bytes) // len(key)) + 1)
repeated_key = repeated_key[:len(encoded_data_bytes)]
decoded_data_bytes = bytes([a ^ b for a, b in zip(encoded_data_bytes, repeated_key)])
# Separate the user ID and the hashed timestamp
decoded_data = decoded_data_bytes.decode()
userid, hashed_timestamp = decoded_data.split("|")
# Return the hashed timestamp
return userid, hashed_timestamp
def main():
userid = "23243232"
xor_secret_key = b'generally_user_salt_or_hash_or_random_uuid_this_value_must_be_in_dbms'
jwt_secret_key = 'yes_your_service_jwt_secret_key'
current_unix_timesstamp = get_current_unix_timestamp()
human_readable_timestamp = get_human_readable_timestamp(current_unix_timesstamp)
encoded_userid_timestamp = encode_userid_with_timestamp(userid, current_unix_timesstamp, xor_secret_key)
decoded_userid, hashed_timestamp = decode_userid_timestamp(encoded_userid_timestamp, xor_secret_key)
jwt_token = jwt.encode({'timestamp': human_readable_timestamp, 'userid': encoded_userid_timestamp}, jwt_secret_key, algorithm='HS256')
decoded_token = jwt.decode(jwt_token, jwt_secret_key, algorithms=['HS256'])
print("")
print("- Current Unix Timestamp:", current_unix_timesstamp)
print("- Current Unix Timestamp to Human Readable:", human_readable_timestamp)
print("")
print("- userid:", userid)
print("- XOR Symmetric key:", xor_secret_key)
print("- JWT Secret key:", jwt_secret_key)
print("")
print("- Encoded UserID and Timestamp:", encoded_userid_timestamp)
print("- Decoded UserID and Hashed Timestamp:", decoded_userid + "|" + hashed_timestamp)
print("")
print("- JWT Token:", jwt_token)
print("- Decoded JWT:", decoded_token)
if __name__ == "__main__":
main()
https://github.com/password123456/some-tweak-to-hide-jwt-payload-values
Upvotes: 0
Reputation: 16775
In fact there is not only signed JWT, but several technologies described by RFCs:
In your case, read the RFC7516 (JWE). These JWE have 5 parts:
Depending on your platform, you may find a library that will help you to create such encrypted JWT. Concerning PHP
, I am writing a library that is already able to load and create these jose.
Upvotes: 27
Reputation: 757
Not encrypting the token means that other external services can read and validate that the token is in fact authentic without having access to your private key. (They would only need the public key)
Upvotes: -3
Reputation: 337
Below is a very simple and effective method for encrypting using AES. Note you will need to get your own key (link included in comments).
Note that when you encrypt, it will set an IV for each encryption call. You will need this to decrypt.
public class CustomEncryption
{
public static string Encrypt256(string text, byte[] AesKey256, out byte[] iv)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Key = aesKey256();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
iv = aes.IV;
byte[] src = Encoding.Unicode.GetBytes(text);
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
return Convert.ToBase64String(dest);
}
}
public static string Decrypt256(string text, byte[] AesKey256, byte[] iv)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = iv;
aes.Key = aesKey256();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
byte[] src = System.Convert.FromBase64String(text);
using (ICryptoTransform decrypt = aes.CreateDecryptor())
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
return Encoding.Unicode.GetString(dest);
}
}
private static byte[] aesKey256()
{
//you will need to get your own aesKey
//for testing you can generate one from
//https://asecuritysite.com/encryption/keygen
return new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5 };
}
}
}
Upvotes: -3