|
Subject:
|
Credit Card Encryption
|
|
Posted By:
|
jemacc
|
Post Date:
|
10/18/2006 6:45:58 PM
|
Hi all 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 int Declare @returnval int DECLARE @object int DECLARE @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 Encryption set @secret_code = 'super secret code' set @Decrypted_CreditCard = '1234 5678 9012 3456' -- Encrypt EXEC @rc = sp_OACreate 'CAPICOM.EncryptedData', @object OUT if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end EXEC @rc = sp_OASetProperty @Object, 'Algorithm.Name', 3 -- 3DES if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end EXEC @rc = sp_OASetProperty @Object, 'Algorithm.KeyLength', 3 -- 128 bit key if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end set @method_call = 'SetSecret("' + @Secret_code + '")' EXEC @rc=sp_OAMethod @Object, @method_call if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end EXEC @rc=sp_OASetProperty @Object, 'Content',@Decrypted_CreditCard if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end EXEC @rc=sp_OAMethod @Object, 'Encrypt(0)', @Encrypted_CreditCard out if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end -- Print encrypted text print 'Encrypted Credit Card Info = ' + @Encrypted_CreditCard -- Decrypt EXEC @rc = sp_OACreate 'CAPICOM.EncryptedData', @object OUT if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end set @method_call = 'SetSecret("' + @Secret_code + '")' EXEC @rc=sp_OAMethod @Object, @method_call if @rc <> 0 begin 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_call if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end EXEC @rc=sp_OAGetProperty @Object, 'Content',@Decrypted_CreditCard out if @rc <> 0 begin exec sp_oageterrorinfo @object, @src out, @desc out select hr=convert(varbinary(4),@rc), source=@src, description=@desc return end -- Print decrypted text print ' ' print 'Decrypted Create Card Info = ' + @Decrypted_CreditCard -- Destroy object exec @rc = sp_OADestroy @object if @rc <> 0 begin exec sp_OAGetErrorInfo @object return end
Thanks in Advance
Jaime E. Maccou
Jaime E. Maccou
|
|
Reply By:
|
SQLScott
|
Reply Date:
|
10/18/2006 7:29:02 PM
|
Jamie,
How did you try and register the dll? What error did you get when attempting to register it?
Scott Klein Author - Professional SQL Server 2005 XML http://www.wrox.com/WileyCDA/WroxTitle/productCd-0764597922.html
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/18/2006 8:25:31 PM
|
I was finally able to register it but. I still get and error " Invalid String"
Jaime E. Maccou
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/18/2006 8:55:23 PM
|
Hi All,
I was able to figure it out. I made a mistake in registering the .dll Here is the site with all instructions. http://www.dbazine.com/sql/sql-articles/larsen2
Thanks to Greg Larsen; it works like a charm!
Jaime E. Maccou
|
|
Reply By:
|
joefawcett
|
Reply Date:
|
10/19/2006 2:46:14 AM
|
Be careful of the following scenario which might hit you... If you encrypt the data and then have to change the CAPICOM secret you have two main options, either keep a history of old secrets and when trying to decrypt use all in order until one finally gives a legitimate credit card number, or decrypt and re-encrypt all the numbers as you make the change so that there is only one secret in play at any one time. I wrote the following routine to do that and it may help in future:
DECLARE @OldCipherSecret NVARCHAR(100)
DECLARE @NewCipherSecret NVARCHAR(100)
DECLARE @PlainText NVARCHAR(20)
DECLARE @CipherText NVARCHAR(1000)
DECLARE @CustomerId INT
DECLARE @PaymentCardNumber NVARCHAR(1000)
DECLARE @HResult INT
DECLARE @EncryptedData INT
DECLARE @src varchar(255), @desc varchar(255)
DECLARE @LoopIndex INT
Â
SET @OldCipherSecret = 'OldSecret'
SET @NewCipherSecret = 'NewSecret'
DECLARE @CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM INT
SET @CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM = 0
DECLARE @CAPICOM_ENCRYPTION_ALGORITHM_3DES INT
SET @CAPICOM_ENCRYPTION_ALGORITHM_3DES = 3
EXEC @HResult = sp_OACreate 'CAPICOM.EncryptedData', @EncryptedData OUT
IF @HResult <> 0
BEGIN
 EXEC sp_OAGetErrorInfo @EncryptedData, @src OUT, @desc OUT
 SELECT hr = convert(varbinary(4), @HResult), Source = @src, Description = @desc
 --RETURN
END
ELSE
BEGIN
  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, PaymentCardNumber FROM tblCustomer WHERE DATALENGTH(PaymentCardNumber) > 100
  FOR UPDATE OF PaymentCardNumber
  OPEN ToBeDecrypted
  FETCH NEXT FROM ToBeDecrypted
  INTO @CustomerId, @PaymentCardNumber
  WHILE @@FETCH_STATUS = 0
  BEGIN
EXEC sp_OAMethod @EncryptedData, 'Decrypt', NULL, @PaymentCardNumber
EXEC sp_OAGetProperty @EncryptedData, 'Content', @PlainText OUTPUT
PRINT CAST(@CustomerId AS NVARCHAR(10)) + ': ' + @PlainText
UPDATE tblCustomer
SET PaymentCardNumber = @PlainText
WHERE CURRENT OF ToBeDecrypted
FETCH NEXT FROM ToBeDecrypted
INTO @CustomerId, @PaymentCardNumber
  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, PaymentCardNumber FROM tblCustomer WHERE PaymentCardNumber IS NOT NULL AND DATALENGTH(PaymentCardNumber) > 1
  FOR UPDATE OF PaymentCardNumber
 Â
  OPEN ToBeEncrypted
  FETCH NEXT FROM ToBeEncrypted
  INTO @CustomerId, @PaymentCardNumber
  WHILE @@FETCH_STATUS = 0
  BEGIN
EXEC sp_OASetProperty @EncryptedData, 'Content', @PaymentCardNumber
EXEC sp_OAMethod @EncryptedData, 'Encrypt', @CipherText OUTPUT
UPDATE tblCustomer
SET PaymentCardNumber = @CipherText
WHERE CURRENT OF ToBeEncrypted
FETCH NEXT FROM ToBeEncrypted
INTO @CustomerId, @PaymentCardNumber
  END
  CLOSE ToBeEncrypted
  DEALLOCATE ToBeEncrypted
  EXEC sp_OADestroy @EncryptedData
END
This would be easier in SQL 2005 where you could make the decrypt/encrypt user defined functions written in .NET.
--
Joe (Microsoft MVP - XML)
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/19/2006 11:02:18 AM
|
using the script I have what would be your best advice for encrypting a table with columns. CustomerID, PaymentCardNumber.
Yours deletes the credit card number. I will like to encrypt the number stored and then decrypt when needed.
Jaime E. Maccou
|
|
Reply By:
|
joefawcett
|
Reply Date:
|
10/19/2006 11:55:50 AM
|
quote: Originally posted by jemacc
using the script I have what would be your best advice for encrypting a table with columns. CustomerID, PaymentCardNumber.
Yours deletes the credit card number. I will like to encrypt the number stored and then decrypt when needed.
Jaime E. Maccou
If you mean my script then on my server it decrypts and then encrypts using the new secret.
--
Joe (Microsoft MVP - XML)
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/19/2006 12:34:33 PM
|
Yes your scripts. I have changed the column and table name. What I see it does is sets the credit card number to NULL. Here is my table structure
CREATE TABLE [dbo].[customer_test] ( [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 , [CardNumber] [varchar] (50) NULL ) ON [PRIMARY] GO
I will like to store the paymentcardnumber encrypted, then decrypted if necessary at another time.
Thanks
Jaime E. Maccou
|
|
Reply By:
|
joefawcett
|
Reply Date:
|
10/19/2006 1:57:44 PM
|
Sorry a mistake, I've edited the script, change @PlainText to @PaymentCardNumber in the encrypt section. But my script is designed to overcome the "secret" changing problem. There was already a script to encrypt in isolation.
--
Joe (Microsoft MVP - XML)
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/20/2006 5:50:31 AM
|
Thank you joefawcett, as you have been so help in this.
The encryption process has work and I have tried to decrypt using the cursor but was unsuccessful, can you walk me through this process. Once again you have being great.
Jaime E. Maccou
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/20/2006 4:35:43 PM
|
How can I remove the history from your script. Once the number is inserted and encrypted I can decrypted using
select dbo.ufn_paymentCreditCardDecrypt(CardNumber, 'NewSecret')PmtCrdCardNumberDecrypted from customer I only want to encrypt the new inserted records.
your help will be greatly appreciated.
Jaime E. Maccou
|
|
Reply By:
|
joefawcett
|
Reply Date:
|
10/21/2006 3:22:44 AM
|
Do you want to encrypt one record as it is inserted or a batch in one go?
--
Joe (Microsoft MVP - XML)
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/21/2006 2:05:35 PM
|
I will like to insert each record when inserted.
Jaime E. Maccou
|
|
Reply By:
|
jemacc
|
Reply Date:
|
10/23/2006 8:45:07 PM
|
Hi All,
Here are my final results; try it and see if it works for you.
/*Download this file from here. You will need it: http://www.microsoft.com/downloads/details.aspx?FamilyID=860ee43a-a843-462f-abb5-ff88ea5896f6&displaylang=en&Hash=nukHU0e%2bqo6NIplVN69Kvuc2%2fU8U4g5dSo5gNjFs7DPU%2fib6Ae3W9CcQrEwhZWPpHpvYi%2bP2slgP%2fvVc8ee5Fg%3d%3d
In addition, here is the site where I got it from: http://www.dbazine.com/sql/sql-articles/larsen2 the instruction is here as well.*/
USE [Northwind] GO /****** Object: Table [dbo].[customers] Script Date: 10/23/2006 20:27:52 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[customers]( [SubscriptionID] [int] IDENTITY(1,1) NOT NULL, [CustomerID] [int] NOT NULL, [NameOnCard] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [CardType] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [ExpirationDate] [datetime] NOT NULL, [AuthCode] [int] NOT NULL, [DateCreated] [datetime] NOT NULL CONSTRAINT [DF_customers_DateCreated] DEFAULT (getdate()), [DateModified] [datetime] NOT NULL CONSTRAINT [DF_customers_DateModified] DEFAULT (getdate()), [CardNumber] [varchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, CONSTRAINT [PK_customers] PRIMARY KEY CLUSTERED ( [SubscriptionID] ASC )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY]
GO SET ANSI_PADDING OFF
--update all customer to encrypt CardNumber numbers using 'password' UPDATE customers SET CardNumber = dbo.CAPICOMEncrypt(CardNumber, 'password') WHERE len(CardNumber) < 20
--update all customer to decrypt CardNumber numbers using 'password' UPDATE customers SET CardNumber = dbo.CAPICOMDecrypt(CardNumber, 'password') WHERE len(CardNumber) > 20
--update all customer to encrypt CardNumber numbers using 'new password', that were encrypted using 'password' UPDATE customers SET CardNumber = dbo.CAPICOMEncrypt(dbo.CAPICOMDecrypt(CardNumber, 'password'), 'newpassword') WHERE len(CardNumber) < 20
CREATE FUNCTION dbo.CAPICOMEncrypt (@TextToEncrypt varchar(4000), @Secret varchar(1000)) RETURNS varchar(4000) AS BEGIN 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 @EncryptedText END
CREATE FUNCTION dbo.CAPICOMDecrypt (@TextToDecrypt varchar(4000), @Secret varchar(1000)) RETURNS varchar(4000) AS BEGIN 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 @DecryptedText END
--Step 1
--A.Create the encrypt function to call the com application CAPICOM
CREATE FUNCTION dbo.CAPICOMEncrypt
(@TextToEncrypt varchar(4000), @Secret varchar(1000))
RETURNS varchar(4000) AS BEGIN 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 @EncryptedText
END
--B. Create the Decrypt function to call the com application CAPICOM
CREATE FUNCTION dbo.CAPICOMDecrypt
(@TextToDecrypt varchar(4000), @Secret varchar(1000))
RETURNS varchar(4000)
AS
BEGIN
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 @DecryptedText
END
--Step2 --Create store procedure to update and encrypt credit card number Create procedure usp_EncryptCardNumber as UPDATE customers SET CardNumber = dbo.CAPICOMDecrypt(CardNumber, 'password')—Here we will decide best password to use WHERE len(CardNumber) < 20
--Create store procedure to update and decrypt credit card number Create procedure usp_DecryptCardNumber as UPDATE customers SET CardNumber = dbo.CAPICOMDecrypt(CardNumber, 'password')—Must be the same as encrypted password WHERE len(CardNumber) > 20
thanks to all Greg Larsen joefawcett snSQL
Jaime E. Maccou
|