SQL सर्वर व्यवस्थापक के लिए WITH ENCRYPTION
का उपयोग करके संरक्षित संग्रहीत कार्यविधियों, विचारों, कार्यों और ट्रिगर के पाठ को पुनर्प्राप्त करना बहुत आसान है। . इसके बारे में कई लेख लिखे गए हैं, और कई व्यावसायिक उपकरण उपलब्ध हैं। सामान्य पद्धति की मूल रूपरेखा है:
- समर्पित व्यवस्थापक कनेक्शन का उपयोग करके एन्क्रिप्टेड फॉर्म (ए) प्राप्त करें।
- लेनदेन शुरू करें।
- ऑब्जेक्ट परिभाषा को ज्ञात टेक्स्ट (बी) के साथ कम से कम मूल के समान लंबाई के साथ बदलें।
- ज्ञात टेक्स्ट (सी) के लिए एन्क्रिप्टेड फॉर्म प्राप्त करें।
- लक्ष्य वस्तु को उसकी प्रारंभिक अवस्था में छोड़ने के लिए लेन-देन को वापस रोल करें।
- अनएन्क्रिप्टेड मूल प्राप्त करें एक अनन्य-या प्रत्येक वर्ण के लिए लागू करके:
A XOR (B XOR C)
यह सब बहुत सीधा है, लेकिन थोड़ा सा जादू जैसा लगता है:यह यह कैसे और क्यों काम करता है के बारे में बहुत कुछ नहीं बताता है . इस लेख में आप में से उन लोगों के लिए उस पहलू को शामिल किया गया है जो इस प्रकार के विवरण को दिलचस्प पाते हैं, और डिक्रिप्शन के लिए एक वैकल्पिक विधि प्रदान करते हैं जो प्रक्रिया का अधिक उदाहरण है।
स्ट्रीम सिफर
अंतर्निहित एन्क्रिप्शन एल्गोरिथम SQL सर्वर मॉड्यूल एन्क्रिप्शन के लिए उपयोग करता है RC4™ स्ट्रीम सिफर है। एन्क्रिप्शन प्रक्रिया की रूपरेखा है:
- RC4 सिफर को क्रिप्टोग्राफ़िक कुंजी के साथ प्रारंभ करें।
- बाइट्स की एक छद्म यादृच्छिक धारा उत्पन्न करें।
- एक्सक्लूसिव-या का उपयोग करके मॉड्यूल प्लेन टेक्स्ट को बाइट स्ट्रीम के साथ मिलाएं।
हम इस प्रक्रिया को डिबगर और सार्वजनिक प्रतीकों का उपयोग करते हुए देख सकते हैं। उदाहरण के लिए, नीचे दिया गया स्टैक ट्रेस दिखाता है कि SQL सर्वर मॉड्यूल टेक्स्ट को एन्क्रिप्ट करने की तैयारी करते समय RC4 कुंजी को इनिशियलाइज़ कर रहा है:
यह अगला वाला SQL सर्वर RC4 छद्म यादृच्छिक बाइट स्ट्रीम का उपयोग करके पाठ को एन्क्रिप्ट करते हुए दिखाता है:
अधिकांश स्ट्रीम सिफर की तरह, डिक्रिप्शन की प्रक्रिया एन्क्रिप्शन के समान है, इस तथ्य का उपयोग करते हुए कि अनन्य-या प्रतिवर्ती है (A XOR B XOR B = A
)।
स्ट्रीम सिफर का उपयोग इसका कारण है अनन्य-या लेख की शुरुआत में वर्णित विधि में प्रयोग किया जाता है। अनन्य का उपयोग करने के बारे में कुछ भी स्वाभाविक रूप से असुरक्षित नहीं है-या, बशर्ते कि एक सुरक्षित एन्क्रिप्शन विधि का उपयोग किया जाता है, प्रारंभिक कुंजी को गुप्त रखा जाता है, और कुंजी का पुन:उपयोग नहीं किया जाता है।
RC4 विशेष रूप से मजबूत नहीं है, लेकिन यह यहाँ मुख्य मुद्दा नहीं है। उस ने कहा, यह ध्यान देने योग्य है कि RC4 का उपयोग करने वाले एन्क्रिप्शन को SQL सर्वर से धीरे-धीरे हटाया जा रहा है, और एक सममित कुंजी बनाने जैसे उपयोगकर्ता संचालन के लिए बहिष्कृत (या अक्षम, संस्करण और डेटाबेस संगतता स्तर पर निर्भर करता है)।
RC4 आरंभीकरण कुंजी
SQL सर्वर RC4 स्ट्रीम सिफर को इनिशियलाइज़ करने के लिए उपयोग की जाने वाली कुंजी उत्पन्न करने के लिए सूचना के तीन टुकड़ों का उपयोग करता है:
- डेटाबेस परिवार GUID.
इसे sys.database_recovery_status . को क्वेरी करके सबसे आसानी से प्राप्त किया जा सकता है . यह
DBCC DBINFO
. जैसे गैर-दस्तावेज आदेशों में भी दिखाई देता है औरDBCC DBTABLE
. - लक्ष्य मॉड्यूल की ऑब्जेक्ट आईडी।
यह सिर्फ परिचित वस्तु आईडी है। ध्यान दें कि एन्क्रिप्शन की अनुमति देने वाले सभी मॉड्यूल स्कीमा-स्कोप वाले नहीं होते हैं। आपको मेटाडेटा दृश्यों का उपयोग करना होगा (sys.triggers या sys.server_triggers ) sys.objects के बजाय DDL और सर्वर-स्कोप्ड ट्रिगर के लिए ऑब्जेक्ट ID प्राप्त करने के लिए या
OBJECT_ID
, क्योंकि ये केवल स्कीमा-स्कोप्ड ऑब्जेक्ट्स के साथ काम करते हैं। - लक्ष्य मॉड्यूल की उप-वस्तु आईडी।
यह क्रमांकित संग्रहीत कार्यविधियों के लिए प्रक्रिया संख्या है। यह बिना क्रमांक वाली संग्रहीत कार्यविधि के लिए 1 है, और अन्य सभी मामलों में शून्य है।
फिर से डिबगर का उपयोग करके, हम देख सकते हैं कि परिवार GUID को कुंजी आरंभीकरण के दौरान पुनर्प्राप्त किया जा रहा है:
डेटाबेस परिवार GUID टाइप किया गया है अद्वितीय पहचानकर्ता , ऑब्जेक्ट आईडी पूर्णांक है , और उप-वस्तु आईडी छोटा है ।
कुंजी का प्रत्येक भाग होना चाहिए एक विशिष्ट बाइनरी प्रारूप में परिवर्तित किया जा सकता है। डेटाबेस परिवार GUID के लिए, अद्वितीय पहचानकर्ता . को परिवर्तित करना बाइनरी(16) . में टाइप करें सही बाइनरी प्रतिनिधित्व पैदा करता है। दो आईडी को छोटे-एंडियन प्रतिनिधित्व (कम से कम महत्वपूर्ण बाइट पहले) में बाइनरी में परिवर्तित किया जाना चाहिए।
नोट: बहुत सावधान रहें कि गलती से GUID को एक स्ट्रिंग के रूप में प्रदान न करें! यह टाइप किया जाना चाहिए अद्वितीय पहचानकर्ता ।
नीचे दिया गया कोड स्निपेट कुछ नमूना मानों के लिए सही रूपांतरण संचालन दिखाता है:
DECLARE @family_guid binary(16) = CONVERT(binary(16), {guid 'B1FC892E-5824-4FD3-AC48-FBCD91D57763'}), @objid binary(4) = CONVERT(binary(4), REVERSE(CONVERT(binary(4), 800266156))), @subobjid binary(2) = CONVERT(binary(2), REVERSE(CONVERT(binary(2), 0)));
RC4 इनिशियलाइज़ेशन कुंजी जनरेट करने का अंतिम चरण उपरोक्त तीन बाइनरी मानों को एक बाइनरी (22) में संयोजित करना है, और परिणाम के SHA-1 हैश की गणना करना है:
DECLARE @RC4key binary(20) = HASHBYTES('SHA1', @family_guid + @objid + @subobjid);
ऊपर दिए गए नमूना डेटा के लिए, अंतिम आरंभीकरण कुंजी है:
0x6C914908E041A08DD8766A0CFEDC113585D69AF8
SHA-1 हैश में लक्ष्य मॉड्यूल की ऑब्जेक्ट आईडी और उप-ऑब्जेक्ट आईडी का योगदान एक डीबगर स्क्रीनशॉट में देखना मुश्किल है, लेकिन इच्छुक पाठक initspkey के एक हिस्से के डिस्सेप्लर का उल्लेख कर सकते हैं। नीचे:
call sqllang!A_SHAInit lea rdx,[rsp+40h] lea rcx,[rsp+50h] mov r8d,10h call sqllang!A_SHAUpdate lea rdx,[rsp+24h] lea rcx,[rsp+50h] mov r8d,4 call sqllang!A_SHAUpdate lea rdx,[rsp+20h] lea rcx,[rsp+50h] mov r8d,2 call sqllang!A_SHAUpdate lea rdx,[rsp+0D0h] lea rcx,[rsp+50h] call sqllang!A_SHAFinal lea r8,[rsp+0D0h] mov edx,14h mov rcx,rbx call sqllang!rc4_key (00007fff`89672090)
शैनिट और SHAUpdate कॉल SHA हैश में घटक जोड़ते हैं, जिसकी गणना अंततः SHAFinal . को कॉल करके की जाती है ।
शैनिट कॉल [rsp+40h] पर संग्रहीत 10h बाइट्स (16 दशमलव) का योगदान देता है, जो कि पारिवारिक GUID है . पहला SHAUpdate कॉल 4 बाइट्स जोड़ता है (जैसा कि r8d रजिस्टर में दर्शाया गया है), [rsp+24h] पर संग्रहीत है, जो कि ऑब्जेक्ट है पहचान। दूसरा SHAUpdate कॉल 2 बाइट्स जोड़ता है, जो [rsp+20h] पर संग्रहीत होता है, जो कि subobjid है ।
अंतिम निर्देश परिकलित SHA-1 हैश को RC4 कुंजी इनिशियलाइज़ेशन रूटीन rc4_key में पास कर देते हैं . हैश की लंबाई रजिस्टर edx:14h (20 दशमलव) बाइट्स में संग्रहीत होती है, जो SHA और SHA-1 (160 बिट) के लिए परिभाषित हैश लंबाई है।
RC4 कार्यान्वयन
कोर RC4 एल्गोरिथ्म प्रसिद्ध है, और अपेक्षाकृत सरल है। दक्षता और प्रदर्शन कारणों से इसे .Net भाषा में बेहतर तरीके से लागू किया जाएगा, लेकिन नीचे एक टी-एसक्यूएल कार्यान्वयन है।
ये दो T-SQL फ़ंक्शन RC4 कुंजी-शेड्यूलिंग एल्गोरिथम और छद्म यादृच्छिक संख्या जनरेटर को लागू करते हैं, और मूल रूप से SQL सर्वर MVP पीटर लार्सन द्वारा लिखे गए थे। मैंने प्रदर्शन में थोड़ा सुधार करने के लिए कुछ मामूली संशोधन किए हैं, और LOB-लंबाई बायनेरिज़ को एन्कोड और डीकोड करने की अनुमति दी है। प्रक्रिया के इस भाग को किसी भी मानक RC4 कार्यान्वयन से बदला जा सकता है।
/* ** RC4 functions ** Based on http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=76258 ** by Peter Larsson (SwePeso) */ IF OBJECT_ID(N'dbo.fnEncDecRc4', N'FN') IS NOT NULL DROP FUNCTION dbo.fnEncDecRc4; GO IF OBJECT_ID(N'dbo.fnInitRc4', N'TF') IS NOT NULL DROP FUNCTION dbo.fnInitRc4; GO CREATE FUNCTION dbo.fnInitRc4 (@Pwd varbinary(256)) RETURNS @Box table ( i tinyint PRIMARY KEY, v tinyint NOT NULL ) WITH SCHEMABINDING AS BEGIN DECLARE @Key table ( i tinyint PRIMARY KEY, v tinyint NOT NULL ); DECLARE @Index smallint = 0, @PwdLen tinyint = DATALENGTH(@Pwd); WHILE @Index <= 255 BEGIN INSERT @Key (i, v) VALUES (@Index, CONVERT(tinyint, SUBSTRING(@Pwd, @Index % @PwdLen + 1, 1))); INSERT @Box (i, v) VALUES (@Index, @Index); SET @Index += 1; END; DECLARE @t tinyint = NULL, @b smallint = 0; SET @Index = 0; WHILE @Index <= 255 BEGIN SELECT @b = (@b + b.v + k.v) % 256 FROM @Box AS b JOIN @Key AS k ON k.i = b.i WHERE b.i = @Index; SELECT @t = b.v FROM @Box AS b WHERE b.i = @Index; UPDATE b1 SET b1.v = (SELECT b2.v FROM @Box AS b2 WHERE b2.i = @b) FROM @Box AS b1 WHERE b1.i = @Index; UPDATE @Box SET v = @t WHERE i = @b; SET @Index += 1; END; RETURN; END; GO CREATE FUNCTION dbo.fnEncDecRc4 ( @Pwd varbinary(256), @Text varbinary(MAX) ) RETURNS varbinary(MAX) WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT AS BEGIN DECLARE @Box AS table ( i tinyint PRIMARY KEY, v tinyint NOT NULL ); INSERT @Box (i, v) SELECT FIR.i, FIR.v FROM dbo.fnInitRc4(@Pwd) AS FIR; DECLARE @Index integer = 1, @i smallint = 0, @j smallint = 0, @t tinyint = NULL, @k smallint = NULL, @CipherBy tinyint = NULL, @Cipher varbinary(MAX) = 0x; WHILE @Index <= DATALENGTH(@Text) BEGIN SET @i = (@i + 1) % 256; SELECT @j = (@j + b.v) % 256, @t = b.v FROM @Box AS b WHERE b.i = @i; UPDATE b SET b.v = (SELECT w.v FROM @Box AS w WHERE w.i = @j) FROM @Box AS b WHERE b.i = @i; UPDATE @Box SET v = @t WHERE i = @j; SELECT @k = b.v FROM @Box AS b WHERE b.i = @i; SELECT @k = (@k + b.v) % 256 FROM @Box AS b WHERE b.i = @j; SELECT @k = b.v FROM @Box AS b WHERE b.i = @k; SELECT @CipherBy = CONVERT(tinyint, SUBSTRING(@Text, @Index, 1)) ^ @k, @Cipher = @Cipher + CONVERT(binary(1), @CipherBy); SET @Index += 1; END; RETURN @Cipher; END; GO
एन्क्रिप्टेड मॉड्यूल टेक्स्ट
SQL सर्वर व्यवस्थापक के लिए इसे प्राप्त करने का सबसे आसान तरीका varbinary(max) . को पढ़ना है imageval . में संग्रहीत मान sys.sysobjvalues . का स्तंभ , जो केवल समर्पित व्यवस्थापक कनेक्शन (DAC) के माध्यम से पहुँचा जा सकता है।
यह वही विचार है जो परिचय में वर्णित नियमित पद्धति के रूप में है, हालांकि हम valclass पर एक फ़िल्टर जोड़ते हैं =1. यह आंतरिक तालिका subobjid . प्राप्त करने के लिए एक सुविधाजनक स्थान भी है . अन्यथा, हमें sys.numbered_procedures . की जांच करनी होगी जब लक्ष्य वस्तु एक प्रक्रिया है, तो पहले बताए गए अनुसार किसी भी संख्याहीन प्रक्रिया के लिए 1 या किसी अन्य चीज़ के लिए शून्य का उपयोग करें।
DAC के उपयोग से बचना . संभव है इमेजवैल . पढ़कर sys.sysobjvalues . से सीधे, एकाधिक DBCC PAGE
का उपयोग करके कॉल। इसमें मेटाडेटा से पृष्ठों का पता लगाने के लिए थोड़ा और काम शामिल है, इमेजवैल . का पालन करें LOB श्रृंखला, और प्रत्येक पृष्ठ से लक्ष्य बाइनरी डेटा पढ़ें। बाद वाला चरण टी-एसक्यूएल के अलावा किसी अन्य प्रोग्रामिंग भाषा में करना बहुत आसान है। ध्यान दें कि DBCC PAGE
काम करेगा, भले ही मूल वस्तु गैर-डैक कनेक्शन से सामान्य रूप से पठनीय नहीं है। अगर पेज मेमोरी में नहीं है, तो इसे सामान्य रूप से लगातार स्टोरेज से पढ़ा जाएगा।
डीएसी की आवश्यकता से बचने का अतिरिक्त प्रयास कई उपयोगकर्ताओं को एक साथ डिक्रिप्टिंग प्रक्रिया का उपयोग करने की अनुमति देकर भुगतान करता है। मैं इस लेख में सरलता और स्थान कारणों के लिए डीएसी दृष्टिकोण का उपयोग करूंगा।
कार्य उदाहरण
निम्न कोड एक परीक्षण एन्क्रिप्टेड स्केलर फ़ंक्शन बनाता है:
CREATE FUNCTION dbo.FS() RETURNS varchar(255) WITH ENCRYPTION, SCHEMABINDING AS BEGIN RETURN ( SELECT 'My code is so awesome is needs to be encrypted!' ); END;
पूर्ण डिक्रिप्शन कार्यान्वयन नीचे है। एकमात्र पैरामीटर जिसे अन्य वस्तुओं के लिए काम करने के लिए बदलने की आवश्यकता है, वह है @objectid
. का प्रारंभिक मान पहले DECLARE
. में सेट करें बयान।
-- *** DAC connection required! *** -- Make sure the target database is the context USE Sandpit; DECLARE -- Note: OBJECT_ID only works for schema-scoped objects @objectid integer = OBJECT_ID(N'dbo.FS', N'FN'), @family_guid binary(16), @objid binary(4), @subobjid binary(2), @imageval varbinary(MAX), @RC4key binary(20); -- Find the database family GUID SELECT @family_guid = CONVERT(binary(16), DRS.family_guid) FROM sys.database_recovery_status AS DRS WHERE DRS.database_id = DB_ID(); -- Convert object ID to little-endian binary(4) SET @objid = CONVERT(binary(4), REVERSE(CONVERT(binary(4), @objectid))); SELECT -- Read the encrypted value @imageval = SOV.imageval, -- Get the subobjid and convert to little-endian binary @subobjid = CONVERT(binary(2), REVERSE(CONVERT(binary(2), SOV.subobjid))) FROM sys.sysobjvalues AS SOV WHERE SOV.[objid] = @objectid AND SOV.valclass = 1; -- Compute the RC4 initialization key SET @RC4key = HASHBYTES('SHA1', @family_guid + @objid + @subobjid); -- Apply the standard RC4 algorithm and -- convert the result back to nvarchar PRINT CONVERT ( nvarchar(MAX), dbo.fnEncDecRc4 ( @RC4key, @imageval ) );
nvarchar . में अंतिम रूपांतरण पर ध्यान दें क्योंकि मॉड्यूल टेक्स्ट nvarchar(max) . के रूप में टाइप किया गया है ।
आउटपुट है:
निष्कर्ष
परिचय कार्य में वर्णित विधि के कारण हैं:
- SQL सर्वर RC4 स्ट्रीम सिफर का उपयोग रिवर्सली एक्सक्लूसिव-या सोर्स टेक्स्ट के लिए करता है।
- RC4 कुंजी केवल डेटाबेस फ़ैमिली गाइड, ऑब्जेक्ट आईडी और सबोबजीड पर निर्भर करती है।
- मॉड्यूल टेक्स्ट को अस्थायी रूप से बदलने का मतलब है कि वही (SHA-1 हैशेड) RC4 कुंजी उत्पन्न होती है।
- एक ही कुंजी के साथ, एक ही RC4 स्ट्रीम उत्पन्न होती है, जिससे अनन्य-या डिक्रिप्शन की अनुमति मिलती है।
जिन उपयोगकर्ताओं के पास सिस्टम टेबल, डेटाबेस फ़ाइलों या अन्य व्यवस्थापक-स्तरीय एक्सेस तक पहुंच नहीं है, वे एन्क्रिप्टेड मॉड्यूल टेक्स्ट को पुनः प्राप्त नहीं कर सकते हैं। चूंकि SQL सर्वर को स्वयं मॉड्यूल को डिक्रिप्ट करने में सक्षम होना चाहिए, इसलिए उपयुक्त विशेषाधिकार प्राप्त उपयोगकर्ताओं को ऐसा करने से रोकने का कोई तरीका नहीं है।