Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
jemacc
Starting Member
42 Posts |
Posted - 2006-10-18 : 16:37:37
|
Hi all,Sorry if I posted this twice but I could not find my original post.I am trying to encrypt and decrypted credit card information using the following script created by Greg Larsen. I have install the capicom.dll but I could not register it. I can call other com objects but I cannot with the capicom. if any off you can offer some assistance. Please let me know. Here is the script.Declare @rc intDeclare @returnval intDECLARE @object intDECLARE @Encrypted_CreditCard varchar(4000)DECLARE @Decrypted_CreditCard varchar(4000)Declare @Method_call varchar(4000)Declare @Secret_code varchar(1000)declare @src varchar(255) declare @desc varchar(255) -- Password for Encryptionset @secret_code = 'super secret code' set @Decrypted_CreditCard = '1234 5678 9012 3456' -- EncryptEXEC @rc = sp_OACreate 'CAPICOM.EncryptedData', @object OUTif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend EXEC @rc = sp_OASetProperty @Object, 'Algorithm.Name', 3 -- 3DESif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend EXEC @rc = sp_OASetProperty @Object, 'Algorithm.KeyLength', 3 -- 128 bit keyif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend set @method_call = 'SetSecret("' + @Secret_code + '")'EXEC @rc=sp_OAMethod @Object, @method_callif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend EXEC @rc=sp_OASetProperty @Object, 'Content',@Decrypted_CreditCardif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend EXEC @rc=sp_OAMethod @Object, 'Encrypt(0)', @Encrypted_CreditCard outif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend -- Print encrypted textprint 'Encrypted Credit Card Info = ' + @Encrypted_CreditCard -- DecryptEXEC @rc = sp_OACreate 'CAPICOM.EncryptedData', @object OUTif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend set @method_call = 'SetSecret("' + @Secret_code + '")'EXEC @rc=sp_OAMethod @Object, @method_callif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end set @Decrypted_CreditCard = 'garbage'set @method_call = 'Decrypt("' + @Encrypted_CreditCard + '")'EXEC @rc=sp_OAMethod @Object,@method_callif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend EXEC @rc=sp_OAGetProperty @Object, 'Content',@Decrypted_CreditCard outif @rc <> 0begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc returnend -- Print decrypted textprint ' 'print 'Decrypted Create Card Info = ' + @Decrypted_CreditCard -- Destroy objectexec @rc = sp_OADestroy @objectif @rc <> 0begin exec sp_OAGetErrorInfo @object returnendThanks in AdvanceJaime E. Maccou |
|
snSQL
Master Smack Fu Yak Hacker
1837 Posts |
Posted - 2006-10-18 : 17:50:02
|
The script is useless if you can't register the component. Here's a good article (maybe the one you already saw)http://www.dbazine.com/sql/sql-articles/larsen2And this info on installing and registering the component quote: How to Install CAPICOMIt is a fairly easy process to install CAPICOM. CAPICOM consists of a single dll, capicom.dll, that must be placed in your system32 directory, then registered. You can download the CAPICOM dll from the Microsoft Download Center.Once you have downloaded, and extracted the CAPICOM package, read the README.txt for an explanation of how to install CAPICOM. To call CAPICOM from TSQL, you will need to install CAPICOM on the SQL Server box that will be running the TSQL that calls CAPICOM.
If you can't register the component you probably don't have permissions to do so? |
|
|
jemacc
Starting Member
42 Posts |
Posted - 2006-10-19 : 12:57:04
|
okay I was able to register the dll. my problem is how to I encrypt the table with the credit card using the script.the table name is customer with the following columns CREATE TABLE [dbo].[customer] ( [SubscriptionID] [int] IDENTITY (1, 1) NOT NULL , [CustomerID] [int] NOT NULL , [NameOnCard] [varchar] (255) NOT NULL , [CardType] [varchar] (50) NOT NULL , [ExpirationDate] [datetime] NOT NULL , [AuthCode] [int] NOT NULL , [DateCreated] [datetime] NOT NULL , [DateModified] [datetime] NOT NULL , [PaymentCardNumber] [varchar] (100)NOT NULL ) ON [PRIMARY]GO |
|
|
snSQL
Master Smack Fu Yak Hacker
1837 Posts |
Posted - 2006-10-19 : 13:38:19
|
Before looking at implementing this, there are a couple of things to ask/consider.1. You said "my problem is how to I encrypt the table with the credit card using the script." - you don't really want to encrypt the whole table right, just the PaymentCardNumber column?2. What kind of app is going to use the data? If you do the encryption/decryption on the SQL Server then you are securing the data, but given that you will need to decrypt it on the way out, the decrypted data will be available to any application that can query the database, and the decrypted data will travel from the SQL Server to the app or web server - is that OK? If not you may be better off implementing the encryption/decryption directly in the application, so that you are always sending/receiving the already encrypted data to SQL Server and only decrypting in the app.3. The encryption is going to be based on a password or some other piece of secret data, where are you going to store that - if you put it in the stored proc or function that encrypts/decrypts data it's not very secure, otherwise your app could provide it with every query, but you'll have to ensure its secure then too.4. SQL Server 2005 implements a very nice solution to this where you can base the encryption/decryption on certificates - is 2005 an option because if so, then you're probably better off doing that.So, think about all these then we can look at whether you want to create functions based on CAPICOM to do the encryption and decryption. |
|
|
jemacc
Starting Member
42 Posts |
Posted - 2006-10-19 : 14:08:57
|
1. Just the PaymentCardNumber2. I will be encrypting on the server. The app will not be accessing that data; only when it writes to it.3. for now it will be on proc. when I get it working it will be called from somewhere else more secure.4. Yes, SQL 2005 took care of this but right now it is not a choice.Thanks for your quick responce. |
|
|
snSQL
Master Smack Fu Yak Hacker
1837 Posts |
Posted - 2006-10-19 : 15:21:22
|
OK then, here's what you need. First two functions that use the CAPICOM component to encrypt and decrypt a given varchar value using a given secret/password. Then two examples of using these functions, one just calls them with variables, the next one creates a temporary table and shows inserting encrypted data and then reading that data, either encrypted or decrypted.For anyone else reading this, you'll need to get the Microsoft CAPICOM component and install it on your SQL Server machine before this will work. Get it herehttp://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=860EE43A-A843-462F-ABB5-FF88EA5896F6All of this code provided as is, with no warranty, guarantee, or any other type of liability on my part!!If you encrypt data and lose the password - YOU CANNOT decrypt it, so don't ask how to do that!!--Create the crypto functions--Thanks to Greg Larsen for the original code that these functions are based on--see http://www.dbazine.com/sql/sql-articles/larsen2--USE AT YOUR OWN RISKCREATE ALTER FUNCTION dbo.CAPICOMEncrypt(@TextToEncrypt varchar(4000), @Secret varchar(1000))RETURNS varchar(4000)ASBEGIN DECLARE @EncryptedText varchar(4000) DECLARE @rc int DECLARE @object int DECLARE @Method_call varchar(4000) -- Encrypt EXEC @rc = sp_OACreate 'CAPICOM.EncryptedData', @object OUT if @rc <> 0 begin return NULL end EXEC @rc = sp_OASetProperty @Object, 'Algorithm.Name', 3 -- 3DES if @rc <> 0 begin return NULL end EXEC @rc = sp_OASetProperty @Object, 'Algorithm.KeyLength', 3 -- 128 bit key if @rc <> 0 begin return NULL end set @method_call = 'SetSecret("' + @Secret + '")' EXEC @rc=sp_OAMethod @Object, @method_call if @rc <> 0 begin return NULL end EXEC @rc=sp_OASetProperty @Object, 'Content',@TextToEncrypt if @rc <> 0 begin return NULL end EXEC @rc=sp_OAMethod @Object, 'Encrypt(0)', @EncryptedText out if @rc <> 0 begin return NULL end -- Destroy object exec @rc = sp_OADestroy @object return @EncryptedTextENDCREATE FUNCTION dbo.CAPICOMDecrypt(@TextToDecrypt varchar(4000), @Secret varchar(1000))RETURNS varchar(4000)ASBEGIN DECLARE @DecryptedText varchar(4000) DECLARE @rc int DECLARE @object int DECLARE @Method_call varchar(4000) -- Decrypt EXEC @rc = sp_OACreate 'CAPICOM.EncryptedData', @object OUT if @rc <> 0 begin return NULL end set @method_call = 'SetSecret("' + @Secret + '")' EXEC @rc=sp_OAMethod @Object, @method_call if @rc <> 0 begin return NULL end set @method_call = 'Decrypt("' + @TextToDecrypt + '")' EXEC @rc=sp_OAMethod @Object,@method_call if @rc <> 0 begin return NULL end EXEC @rc=sp_OAGetProperty @Object, 'Content',@DecryptedText out if @rc <> 0 begin return NULL end -- Destroy object exec @rc = sp_OADestroy @object return @DecryptedTextEND --Example of calling the crypto functionsDECLARE @secret_code varchar(1000)DECLARE @Decrypted_CreditCard varchar(4000)DECLARE @Encrypted_CreditCard varchar(4000)set @secret_code = 'li3j2 4liuj3 lighgh4 lijoil4j o43i uj43'set @Decrypted_CreditCard = '1234 5678 9012 3456' select @Encrypted_CreditCard = dbo.CAPICOMEncrypt(@Decrypted_CreditCard, @secret_code)select @Decrypted_CreditCard Originalselect @Encrypted_CreditCard Encryptedselect dbo.CAPICOMDecrypt(@Encrypted_CreditCard, @secret_code) Decrypted --Example of using the crypto functions on a table columncreate table #TestEncryption(EncryptedValue varchar(4000))insert #TestEncryptionselect dbo.CAPICOMEncrypt('1234 5678 9012 3456', 'my password') union allselect dbo.CAPICOMEncrypt('1234 5678 9012 3456', 'new password') union allselect dbo.CAPICOMEncrypt('1234 5678 9012 3456', 'your password') union allselect dbo.CAPICOMEncrypt('1234 5678 9012 3456', 'my password')select EncryptedValue from #TestEncryptionselect dbo.CAPICOMDecrypt(EncryptedValue, 'my password') DecryptedValue from #TestEncryptionselect dbo.CAPICOMDecrypt(EncryptedValue, 'new password') DecryptedValue from #TestEncryptionselect dbo.CAPICOMDecrypt(EncryptedValue, 'your password') DecryptedValue from #TestEncryption |
|
|
jemacc
Starting Member
42 Posts |
Posted - 2006-10-23 : 16:37:48
|
I taken your function and I able to get this working. The problem I am having is: when I encrypted the card number and run the store procedure again it inserts another encryption key next to the original one. How can I prevent this with the store procedure listed below. All I want to prevent is building a history of encryption keys. I have had help with it but I cannot take further. SET QUOTED_IDENTIFIER ON GOSET ANSI_NULLS ON GO/****** Object: Stored Procedure dbo.usp_PaymentCreditCardNumber Script Date: 10/20/2006 3:18:26 PM ******/ALTER proc usp_PaymentCreditCardNumberasDECLARE @OldCipherSecret NVARCHAR(100)DECLARE @NewCipherSecret NVARCHAR(100)DECLARE @PlainText NVARCHAR(20)DECLARE @CipherText NVARCHAR(1000)DECLARE @CustomerId INTDECLARE @CardNumber NVARCHAR(1000)DECLARE @HResult INTDECLARE @EncryptedData INTDECLARE @src varchar(255), @desc varchar(255)DECLARE @LoopIndex INT SET @OldCipherSecret = 'OldSecret'SET @NewCipherSecret = 'NewSecret'DECLARE @CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM INTSET @CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM = 0DECLARE @CAPICOM_ENCRYPTION_ALGORITHM_3DES INTSET @CAPICOM_ENCRYPTION_ALGORITHM_3DES = 3EXEC @HResult = sp_OACreate 'CAPICOM.EncryptedData', @EncryptedData OUTIF @HResult <> 0BEGIN EXEC sp_OAGetErrorInfo @EncryptedData, @src OUT, @desc OUT SELECT hr = convert(varbinary(4), @HResult), Source = @src, Description = @desc RETURNENDELSEBEGIN EXEC sp_OAMethod @EncryptedData, 'SetSecret', NULL, @OldCipherSecret DECLARE ToBeDecrypted CURSOR LOCAL FORWARD_ONLY -- The SQL will need tailoring to your own table. We only want numbers that have been encrypted, that's why the length test is there. FOR SELECT CustomerId, CardNumber FROM stsubscriptions_test WHERE DATALENGTH(CardNumber) > 100 FOR UPDATE OF CardNumber OPEN ToBeDecrypted FETCH NEXT FROM ToBeDecrypted INTO @CustomerId, @CardNumber WHILE @@FETCH_STATUS = 0 BEGIN EXEC sp_OAMethod @EncryptedData, 'Decrypt', NULL, @CardNumber EXEC sp_OAGetProperty @EncryptedData, 'Content', @CardNumber OUTPUT --changed from @plaintext PRINT CAST(@CustomerId AS NVARCHAR(10)) + ': ' + @CardNumber -- changed from @plaintext UPDATE stsubscriptions SET CardNumber = @CardNumber WHERE CURRENT OF ToBeDecrypted FETCH NEXT FROM ToBeDecrypted INTO @CustomerId, @CardNumber END CLOSE ToBeDecrypted DEALLOCATE ToBeDecrypted EXEC sp_OASetProperty @EncryptedData, 'Algorithm.Name', @CAPICOM_ENCRYPTION_ALGORITHM_3DES EXEC sp_OASetProperty @EncryptedData, 'Algorithm.KeyLength', @CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM EXEC sp_OAMethod @EncryptedData, 'SetSecret', NULL, @NewCipherSecret DECLARE ToBeEncrypted CURSOR LOCAL FORWARD_ONLY FOR SELECT CustomerId, CardNumber FROM stsubscriptions WHERE CardNumber IS NOT NULL AND DATALENGTH(CardNumber) > 1 FOR UPDATE OF CardNumber OPEN ToBeEncrypted FETCH NEXT FROM ToBeEncrypted INTO @CustomerId, @CardNumber WHILE @@FETCH_STATUS = 0 BEGIN EXEC sp_OASetProperty @EncryptedData, 'Content', @CardNumber EXEC sp_OAMethod @EncryptedData, 'Encrypt', @CipherText OUTPUT UPDATE stsubscriptions_test SET CardNumber = @CipherText WHERE CURRENT OF ToBeEncrypted FETCH NEXT FROM ToBeEncrypted INTO @CustomerId, @CardNumber END CLOSE ToBeEncrypted DEALLOCATE ToBeEncrypted EXEC sp_OADestroy @EncryptedDataENDGOSET QUOTED_IDENTIFIER OFF GOSET ANSI_NULLS ON GO I and still using the same table structure CREATE TABLE [dbo].[customer] ([SubscriptionID] [int] IDENTITY (1, 1) NOT NULL ,[CustomerID] [int] NOT NULL ,[NameOnCard] [varchar] (255) NOT NULL ,[CardType] [varchar] (50) NOT NULL ,[ExpirationDate] [datetime] NOT NULL ,[AuthCode] [int] NOT NULL ,[DateCreated] [datetime] NOT NULL ,[DateModified] [datetime] NOT NULL ,[PaymentCardNumber] [varchar] (100)NOT NULL ) ON [PRIMARY]GO |
|
|
snSQL
Master Smack Fu Yak Hacker
1837 Posts |
Posted - 2006-10-23 : 16:54:34
|
What do you want this to do? If you want to decrypt the current encrypted values and replace them with new encrypted ones, just run an UPDATE using the functions I already gave you - there is absolutely no need for a cursor. |
|
|
jemacc
Starting Member
42 Posts |
Posted - 2006-10-23 : 17:42:39
|
I will like to decrypt the current value and stored once. |
|
|
snSQL
Master Smack Fu Yak Hacker
1837 Posts |
Posted - 2006-10-23 : 18:04:17
|
Sorry, but I don't understand, "store once" - store where?Here's some guesses--update all customers to encrypt cc numbers using 'my password'UPDATE customerSET PaymentCardNumber = dbo.CAPICOMEncrypt(PaymentCardNumber, 'my password')WHERE len(PaymentCardNumber) < 20--update all customers to decrypt cc numbers using 'my password'UPDATE customerSET PaymentCardNumber = dbo.CAPICOMDecrypt(PaymentCardNumber, 'my password')WHERE len(PaymentCardNumber) < 20--update all customers to encrypt cc numbers using 'new password', that were encrypted using 'my password'UPDATE customerSET PaymentCardNumber = dbo.CAPICOMEncrypt(dbo.CAPICOMDecrypt(PaymentCardNumber, 'my password'), 'new password')WHERE len(PaymentCardNumber) < 20 |
|
|
jemacc
Starting Member
42 Posts |
Posted - 2006-10-23 : 18:47:45
|
sorry about that.I will like to update the card number to an encryption value when the data is insert in the table. Once the update occurs I do not want touch that record again. The card number will always be stored in the database encrypted.I will look at your recommendation. |
|
|
jemacc
Starting Member
42 Posts |
Posted - 2006-10-23 : 19:05:47
|
Thank you so much for your recommendation. Every thing works great. I really appreciate the time you have taken to look at this.The Only change I made was to the second update it was UPDATE stsubscriptionsSET PaymentCardNumber = dbo.CAPICOMDecrypt(PaymentCardNumber, 'NewSecret')WHERE len(PaymentCardNumber) < 20 and I changed it to UPDATE stsubscriptionsSET PaymentCardNumber = dbo.CAPICOMDecrypt(PaymentCardNumber, 'NewSecret')WHERE len(PaymentCardNumber) > 20 |
|
|
|
|
|
|
|