I am trying to encrypt one of my sensitive columns in a SQL Server table.
I tried AES256 encryption with this script, and it works perfect.
But I don't want to create Certificates, or Symmetric Keys on my SQL Server as it may be a security problem later.
How can I encrypt the data with a single password or key in my query ?
Another problem with this method is, I can use only a single master password for
my encryption.
CREATE MASTER KEY ENCRYPTION
BY PASSWORD = '$Passw0rd'
GO
CREATE CERTIFICATE AESEncryptTestCert
WITH SUBJECT = 'AESEncrypt'
GO
CREATE SYMMETRIC KEY AESEncrypt
WITH ALGORITHM = AES_256 ENCRYPTION -- TRIPLE_DES ENCRYPTION
BY CERTIFICATE AESEncryptTestCert;
OPEN SYMMETRIC KEY AESEncrypt DECRYPTION
BY CERTIFICATE AESEncryptTestCert
SELECT ENCRYPTBYKEY(KEY_GUID('AESEncrypt'),'The text to be encrypted');
You can use EncryptByPassPhrase and DecryptByPassPhrase, for example:
DECLARE #CypherText varbinary(8000)
DECLARE #ClearText varchar(128) = 'Text to encrypt'
SET #CypherText = EncryptByPassPhrase ('MyP#ssword123', #ClearText)
DECLARE #DecryptedText varchar(128)
SET #DecryptedText = DecryptByPassPhrase('MyP#ssword123', #CypherText)
SELECT #CypherText AS CypherText, #DecryptedText As DecryptedText
EDIT:
The above code produces the following output
+----------------------------------------------------------------------------+-----------------+
| CypherText | DecryptedText |
+----------------------------------------------------------------------------+-----------------+
| 0x01000000F1D813F399246484FDA8D7C7D22BFBCF748D3F6033D4E9980FCDC58A387A1A93 | Text to encrypt |
+----------------------------------------------------------------------------+-----------------+
Related
I'm using IdentiyServer4 to generate tokens, I'm using the AddDeveloperSigningCredential() method to generate my RSA key with a KeyId.
But, in production, I'm using AddSigningCredential(CreateSigningCredential()), to generate a key like this :
private SigningCredentials CreateSigningCredential()
{
var signinkey = new RsaSecurityKey(RSA.Create());
signinkey.KeyId = "abcdefghijklmnopqrstuvwxyz";//How to generate KeyId ??
var credentials = new SigningCredentials(signinkey,
SecurityAlgorithms.RsaSha256);
return credentials;
}
How can I generate a KeyId? Can I set it to any arbitrary value?
You don't need to set the keyId and also creating the RSA key youself in code, sounds like bad practice. Then you can just as well use the AddDeveloperSigningCredential method.
You can actually look at the source for that method here to see how they do it in code:
https://github.com/DuendeSoftware/IdentityServer/blob/main/src/IdentityServer/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs
But, in production you should generate the key externally and pass it in to IdentityServer, so the key is the same across redeployment/restarts. Otherwise previously issued tokens will not be valid anymore.
You can for example store the key in Azure Key Vault, or using some other configuration/secret system. Or in a database or as a file somewhere.
If you want to create one manually, using OpenSSL, then you can write
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes256 -out rsa-private-key.pem
I am trying to understand the usage of SCP DEK in store data command.
As per GP Card spec 2.2.1- "The data encryption key (DEK) for decrypting sensitive data, e.g. secret or private keys. This key is a double length DES key and is used as a static key."
I requirement to encrypt the Store data APDU data. Now I have 3 questions
Is indeed SCP DEK used to encrypt EMV AUKs (Application Unique Keys) present in one of these store data commands?
If statement #1 is correct the which key is used to encrypt data field in the APDU?
Is the an indicator in commands prior to store data which says that data field in store data command would be Encrypted or NOT?
I would be able to set store data CLA, INS, P1 and P2 as per GP card 2.2.1 and Amendment D spec.
Asking this question here since crypto.stackexchange does not have global platform and cryptography tags
Any help is appreciated
Nevermind, I found answer
Yes
S-ENC Secure Channel Protocol '03' – Public Release v1.1.1
section 6.2.6 APDU Command C-MAC and C-DECRYPTION Generation and
Verification
External Authenticate command P1 as per 7.1.2.1 Reference Control Parameter P1 – Security Level - (Encrypted value =03 - C-DECRYPTION and C-MAC/ Clear value = 01 - C-MAC)
I need to register companies on my site for an electronic procurement system. Up to now these were local companies I could meet physically and give credentials to, but now they can be companies based anywhere in the world.
The solution is to have an online registration process whereby they submit a third party certificate. So say Verisign says they are 'Company X' so I register them as Company X and issue them credentials.
How can I implement this on my site? Do I simply give them a field in the registration form where they upload their certificate file? Do I then manually check these certificates in my back office? How does one check this manually? Is there a way to automate this process?
Once they have an account, should I simply request the credentials I issue them with to log in, or can all future logins request the same certificate file? In these a particular format for certificates I can request or should I allow a number of common formats that different certificate vendors provide?
Thanks in advance.
Being able to provide a certificate does unfortunately not prove anything. A certificate is completely public, and anyone can get a hold of the SSL certificate for any website. The certificate contains a public key. Proving ownership of the corresponding private key is what's required.
This is possible to do, but it requires that your users are technical enough to know how to run scripts and/or OpenSSL terminal commands so that they can sign something with their private key. Having the users upload their private key is of course a big no-no, as it means you can now act as the user, and that would require an enormous amount of trust in you to discard the private key after you've verified it.
From a technical perspective, you can do the verification by creating some kind of challenge, for example a random string, and have the user encrypt this string with their private key. If you decrypt this string with the public key in the certificate, and get the original string back, then you know that they have possession of the corresponding private key.
Here's a self-contained Ruby script that demonstrates this, with comments indicating which part of it is run on your side, and which part is run on their side.
require "openssl"
## This happens on the client side. They generate a private key and a certificate.
## This particular certificate is not signed by a CA - it is assumed that a CA
## signature check is already done elsewhere on the user cert.
user_keypair = OpenSSL::PKey::RSA.new(2048)
user_cert = OpenSSL::X509::Certificate.new
user_cert.not_before = Time.now
user_cert.subject = OpenSSL::X509::Name.new([
["C", "NO"],
["ST", "Oslo"],
["L", "Oslo"],
["CN", "August Lilleaas"]
])
user_cert.issuer = user_cert.subject
user_cert.not_after = Time.now + 1000000000 # 40 or so years
user_cert.public_key = user_keypair.public_key
user_cert.sign(user_keypair, OpenSSL::Digest::SHA256.new)
File.open("/tmp/user-cert.crt", "w+") do |f|
f.write user_cert.to_pem
end
## This happens on your side - generate a random phrase, and agree on a digest algorithm
random_phrase = "A small brown fox"
digest = OpenSSL::Digest::SHA256.new
## The client signs (encrypts a cheksum) the random phrase
signature = user_keypair.sign(digest, random_phrase)
## On your side, verify the signature using the user's certificate.
your_user_cert = OpenSSL::X509::Certificate.new(File.new("/tmp/user-cert.crt"))
puts your_user_cert.public_key.verify(digest, signature, random_phrase + "altered")
# => falase
puts your_user_cert.public_key.verify(digest, signature, random_phrase)
# => true
## On your side - attempting to verify with another public key/keypair fails
malicious_keypair = OpenSSL::PKey::RSA.new(2048)
puts malicious_keypair.public_key.verify(digest, signature, random_phrase)
Note that this script does not take into account the CA verification step - you also obviously want to verify that the user's certificate is verified by a CA, such as Verisign that you mentioned, because anyone can issue a certificate and hold a private key for foo.com - it's the CA signature of the certificate that provides authenticity guarantees.
I am using Django for an application capturing some sensitive data, and I need those data to be encrypted in the database. I have to use a database encryption.
So to save my fields, I use:
query = """
OPEN SYMMETRIC KEY MyKey
DECRYPTION BY CERTIFICATE MyCertificate
UPDATE mytable
SET name = ENCRYPTBYKEY(KEY_GUID('MyKey'), %s)
WHERE id = %s
CLOSE SYMMETRIC KEY MyKey
"""
args = ["Test Name", data.id]
cursor = connection.cursor()
cursor.execute(query, args)
transaction.commit_unless_managed()
The field is saved in database but, when I uncrypt the data saved in base, I get 0x540065007300740020004E0061006D006500 where I should get 0x54657374204E616D65.
Do someone know why there are some 0x00 bytes inserted in my string?
I have tried to get the query string using connection.queries[-1] and run it directly in the database, and the data is clean when I uncrypt it.
Apparently, SQL Server is implicitly doing some kind of string conversion.
I solved my problem by casting the data as a varchar before encryption:
query = """
OPEN SYMMETRIC KEY MyKey
DECRYPTION BY CERTIFICATE MyCertificate
UPDATE mytable
SET name = ENCRYPTBYKEY(KEY_GUID('MyKey'), CAST(%s AS VARCHAR(1023)))
WHERE id = %s
CLOSE SYMMETRIC KEY MyKey
"""
args = ["Test Name", data.id]
cursor = connection.cursor()
cursor.execute(query, args)
transaction.commit_unless_managed()
I am trying to encrypt database columns using a certificate and a symmetric key.
I successfully created the certificate and symmetric key using the following:
CREATE CERTIFICATE MyCertificate
ENCRYPTION BY PASSWORD = 'password'
WITH SUBJECT = 'Public Access Data'
GO
CREATE SYMMETRIC KEY MySSNKey
WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE MyCertificate
I tried encrypting and decrypting some data using the following:
DECLARE #Text VARCHAR(100)
SET #Text = 'Some Text'
DECLARE #EncryptedText VARBINARY(128)
-- Open the symmetric key with which to encrypt the data.
OPEN SYMMETRIC KEY MySSNKey
DECRYPTION BY CERTIFICATE MyCertificate;
SELECT #EncryptedText = EncryptByKey(Key_GUID('MySSNKey'), #Text)
SELECT CONVERT(VARCHAR(100), DecryptByKey(#EncryptedText)) AS DecryptedText
When I do so, I get the following error message:
The certificate has a private key that is protected by a user defined
password. That password needs to be provided to enable the use of the
private key.
Ultimately, what I am trying to do is write a stored procedure that will take some unencrypted data as input, encrypt it, then store it as encrypted varbinary. Then I'd like to write a 2nd stored procedure that will do the opposite - i.e., decrypt the encrypted varbinary and convert it back to a human-readable data type. I would rather not have to specify the password directly in the stored procedure. Is there any way to do that? What am I doing wrong in my code above?
Thanks.
You just need to use:
OPEN SYMMETRIC KEY MySSNKey
DECRYPTION BY CERTIFICATE MyCertificate WITH PASSWORD = 'password';
You nead use MASTER KEY
Example:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MasterPassword';
CREATE CERTIFICATE MyCertificate WITH SUBJECT = 'Public Access Data';
CREATE SYMMETRIC KEY MySSNKey WITH ALGORITHM = AES_256 ENCRYPTION BY CERTIFICATE MyCertificate;
OPEN SYMMETRIC KEY MySSNKey DECRYPTION BY CERTIFICATE MyCertificate;
SELECT Customer_id, Credit_card_number_encrypt AS 'Encrypted Credit Card Number',
CONVERT(varchar, DecryptByKey(Credit_card_number_encrypt)) AS 'Decrypted Credit Card Number'
FROM dbo.Customer_data;
CLOSE SYMMETRIC KEY MySSNKey ;