2008-10-03 10 views
9

Ich bin auf der Suche nach einem selbstgewählten Weg, um Produktionsdaten für den Einsatz in Entwicklung und Test zu verschlüsseln. Ich habe ein paar Skripte gebaut, die zufällige Sozialversicherungsnummern machen, Geburtsdaten verschieben, E-Mails verschlüsseln, usw. Aber ich bin gegen eine Wand gestoßen, um Kundennamen zu verschlüsseln. Ich möchte echte Namen behalten, damit wir immer noch verwenden oder suchen können, damit die zufällige Buchstabengenerierung aus ist. Was ich bisher versucht habe, ist, eine temporäre Tabelle aller letzten Namen in der Tabelle zu erstellen und dann die Kundentabelle mit einer zufälligen Auswahl aus der temporären Tabelle zu aktualisieren. Wie folgt aus:Obfuscate/Mask/Scramble persönliche Informationen

DECLARE @Names TABLE (Id int IDENTITY(1,1),[Name] varchar(100)) 

/* Scramble the last names (randomly pick another last name) */ 
INSERT @Names SELECT LastName FROM Customer ORDER BY NEWID(); 
WITH [Customer ORDERED BY ROWID] AS 
(SELECT ROW_NUMBER() OVER (ORDER BY NEWID()) AS ROWID, LastName FROM Customer) 
UPDATE [Customer ORDERED BY ROWID] SET LastName=(SELECT [Name] FROM @Names WHERE ROWID=Id) 

Dies funktionierte gut in Test, aber völlig versinkt mit größeren Datenmengen zu tun (> 20 Minuten 40K Zeilen)

All das fragen, wie würden Sie Kundennamen Gerangel während man echte Namen und das Gewicht der Produktionsdaten behält?

UPDATE: Nie versagt, versuchen Sie, alle Informationen in den Beitrag zu setzen, und Sie etwas wichtiges vergessen. Diese Daten werden auch in unseren frei verfügbaren Demoumgebungen & verwendet. Einige der Antworten sind, was ich versuche zu tun, um die Namen zu "wechseln", aber meine Frage ist buchstäblich, wie in T-SQL zu programmieren?

Antwort

1

Eine sehr einfache Lösung wäre ROT13 der Text.

Eine bessere Frage könnte sein, warum Sie das Bedürfnis haben, die Daten zu verschlüsseln? Wenn Sie über einen Verschlüsselungsschlüssel verfügen, können Sie den Text auch über DES oder AES oder ähnliches ausführen. Dies hätte jedoch potenzielle Leistungsprobleme.

+0

Wie ich schon sagte, ich brauche echte Namen mit ähnlichen/gleichen Gewicht wie Produktion, so sucht die Suche ähnlich. –

+0

Zusätzliches ROT13 verschlüsselt nicht wirklich die Daten, da es ein leicht umkehrbarer Algorithmus ist ... – Guvante

+0

ja, es ist leicht reversibel - aber es erfüllt die Kriterien von "Maske" oder "verschleiern" - Sie müssen es zumindest erkennen gewesen ROT13, und un-ROT es :) – warren

3

Ich verwende generatedata. Es ist ein Open-Source-PHP-Skript, das alle Arten von Dummy-Daten generieren kann.

+0

ausgezeichneter Tipp - danke. [Es ist eines dieser Dinge, die ich seit Jahren schreiben möchte, aber nie Zeit hatte] ... –

-1

Ehrlich gesagt verwenden, ich bin nicht sicher, warum dies notwendig ist. Ihre Entwicklungs-/Testumgebungen sollten privat hinter Ihrer Firewall und nicht über das Internet zugänglich sein.

Ihre Entwickler sollten vertrauenswürdig sein, und Sie haben Rechtsbehelfe gegen sie, wenn sie Ihrem Vertrauen nicht gerecht werden.

Ich denke, die eigentliche Frage sollte sein "Sollte ich die Daten verschlüsseln?", Und die Antwort ist (in meinen Augen) "Nein".

Wenn Sie es aus irgendeinem Grund aus der Ferne senden, oder Sie müssen Ihre Umgebungen web-zugänglich haben, oder wenn Sie paranoid sind, würde ich einen zufälligen Schalter implementieren. Anstatt eine temporäre Tabelle zu erstellen, wechseln Sie zwischen den einzelnen Speicherorten und einer zufälligen Zeile in der Tabelle, wobei jeweils ein Datenelement ausgetauscht wird.

Das Endergebnis wird eine Tabelle mit den gleichen Daten sein, aber mit einer zufälligen Reorganisation. Es sollte auch schneller als Ihre temporäre Tabelle sein, glaube ich.

Es sollte einfach genug sein, um die Fisher-Yates Shuffle in SQL zu implementieren ... oder zumindest in einer Konsole App, die die DB liest und auf das Ziel schreibt.

Edit (2): Off-Manschette Antwort in T-SQL:

declare @name varchar (50) Satz @name = (Name von Person auswählen, wo personID = (random-ID-Nummer) -Update Person Satz Nachname = @name WHERE personID = (Person id der aktuellen Zeile)

Wrap diese in einer Schleife, und die Richtlinien von Fisher-Yates folgen für die Zufallswerteinschränkungen ändern, und Sie werden eingestellt werden.

+0

Es scheitert nie, Sie versuchen, alle Informationen in den Beitrag zu setzen, und Sie vergessen etwas Wichtiges. Dieser Datenbedarf wird auch in unseren öffentlich zugänglichen Vertriebs- und Demoumgebungen genutzt. Ihre Idee ist, was ich versuche, die Namen zu "wechseln", aber meine Frage ist wörtlich, wie man programmiert? –

+0

Sie könnten versuchen, die Fisher-Yates Shuffle Es sollte einfach genug sein, um in SQL zu implementieren ... oder in einer einfachen Konsole App, die in der DB liest und auf die Ziel-db schreibt. – Jeff

+0

http://en.wikipedia.org/wiki/Fisher-Yates_shuffle Das ist der richtige Link, denke, ich muss hier mehr über die Umgebung lernen;) Aktualisierung meiner Antwort. – Jeff

1

Wenn ich so etwas mache, ist es normal Schreiben Sie ein kleines Programm, das zuerst viele Namen und Nachnamen in zwei Arrays lädt und dann nur die Datenbank mit dem zufälligen Namen von Arrays aktualisiert. Es funktioniert sehr schnell auch für sehr große Datensätze (200.000 Datensätze)

0

Verwenden Sie stattdessen eine temporäre Tabelle und die Abfrage ist sehr schnell. Ich lief in 4 Sekunden auf 60K-Reihen. Ich werde diesen hier verwenden.

DECLARE TABLE #Names 
(Id int IDENTITY(1,1),[Name] varchar(100)) 

/* Scramble die Nachnamen (zufällig einen anderen Nachnamen wählen) */

INSERT #Names 
    SELECT LastName 
    FROM Customer 
    ORDER BY NEWID(); 
WITH [Customer ORDERED BY ROWID] AS 
(SELECT ROW_NUMBER() OVER (ORDER BY NEWID()) AS ROWID, LastName FROM Customer) 

UPDATE [Customer ORDERED BY ROWID] 

SET LastName=(SELECT [Name] FROM #Names WHERE ROWID=Id) 

DROP TABLE #Names 
+0

Sie könnten immer noch mit einem schlechten Wurf enden und zwei ... warten. NewID() erstellt UUIDs. Ich stehe korrigiert. – Broam

0

ich auf das in meinem Unternehmen jetzt arbeite - und es stellt sich ein sehr schwierig sein out Ding. Sie möchten Namen haben, die realistisch sind, aber keine echten persönlichen Informationen preisgeben sollen.

Meine Vorgehensweise bestand darin, zuerst eine zufällige "Zuordnung" von Nachnamen zu anderen Nachnamen zu erstellen und dann diese Zuordnung zu verwenden, um alle Nachnamen zu ändern. Dies ist nützlich, wenn Sie doppelte Namenseinträge haben. Angenommen, Sie haben 2 "John Smith" -Datensätze, die beide die gleiche reale Person darstellen. Wenn Sie einen Datensatz zu "John Adams" und den anderen zu "John Best" geändert haben, dann hat Ihre eine "Person" nun zwei verschiedene Namen! Bei einem Mapping werden alle Vorkommen von "Smith" in "Jones" geändert, sodass Duplikate (oder sogar Familienmitglieder) immer noch mit demselben Nachnamen enden, wodurch die Daten "realistischer" bleiben.

Ich werde auch die Adressen, Telefonnummern, Bankkontonummern, etc ... verschlüsseln müssen und ich bin mir nicht sicher, wie ich mich denen annähern werde. Die Daten beim Scrambling "realistisch" zu halten, ist sicherlich ein tiefes Thema. Das muss viele Unternehmen schon oft getan haben - wer hat das schon mal gemacht? Was hast du gelernt?

0

Der folgende Ansatz für uns gearbeitet, kann sagen, wir haben zwei Tabellen Kunden und Produkte.

CREATE FUNCTION [dbo].[GenerateDummyValues] 
(
    @dataType varchar(100), 
    @currentValue varchar(4000)=NULL 
) 
RETURNS varchar(4000) 
AS 
BEGIN 
IF @dataType = 'int' 
    BEGIN 
     Return '0' 
    END 
ELSE IF @dataType = 'varchar' OR @dataType = 'nvarchar' OR @dataType = 'char' OR @dataType = 'nchar' 
    BEGIN 
     Return 'AAAA' 
    END 
ELSE IF @dataType = 'datetime' 
    BEGIN 
     Return Convert(varchar(2000),GetDate()) 
    END 
-- you can add more checks, add complicated logic etc 
Return 'XXX' 
END 

Die obige Funktion bei der Erzeugung von verschiedenen Daten, basierend auf dem Datentyp in der kommenden helfen

Jetzt für jede Spalte in jeder Tabelle, die weitere Abfragen verwenden folgende Abfrage erzeugt kein Wort „id“ darin haben, um die Daten zu manipulieren:

select 'select ''update '' + TABLE_NAME + '' set '' + COLUMN_NAME + '' = '' + '''''''' + dbo.GenerateDummyValues(Data_type,'''') + '''''' where id = '' + Convert(varchar(10),Id) from INFORMATION_SCHEMA.COLUMNS, ' + table_name + ' where RIGHT(LOWER(COLUMN_NAME),2) <> ''id'' and TABLE_NAME = '''+ table_name + '''' + ';' from INFORMATION_SCHEMA.TABLES; 

Wenn y ou obige Abfrage ausführt es Aktualisierungsabfragen für jede Tabelle generieren und für jede Spalte der Tabelle, zum Beispiel:

select 'update ' + TABLE_NAME + ' set ' + COLUMN_NAME + ' = ' + '''' + dbo.GenerateDummyValues(Data_type,'') + ''' where id = ' + Convert(varchar(10),Id) from INFORMATION_SCHEMA.COLUMNS, Customers where RIGHT(LOWER(COLUMN_NAME),2) <> 'id' and TABLE_NAME = 'Customers'; 
select 'update ' + TABLE_NAME + ' set ' + COLUMN_NAME + ' = ' + '''' + dbo.GenerateDummyValues(Data_type,'') + ''' where id = ' + Convert(varchar(10),Id) from INFORMATION_SCHEMA.COLUMNS, Products where RIGHT(LOWER(COLUMN_NAME),2) <> 'id' and TABLE_NAME = 'Products'; 

Nun, wenn Sie über Abfragen ausführen werden Sie letzte Aktualisierungsabfragen erhalten, dass die Daten aktualisieren deine Tische.

Sie können dies auf jeder SQL Server-Datenbank ausführen, egal wie viele Tabellen Sie haben, es generiert Abfragen für Sie, die weiter ausgeführt werden können.

Hoffe, das hilft.

0

Eine andere Website zu generieren gefälschte Datensätze geformt, mit einer Option für T-SQL-Ausgang: https://mockaroo.com/

0

Hier ist ein Weg ROT47 verwendet, die reversibel ist, und eine andere, die zufällig ist. Sie können ein PK hinzufügen, um entweder zurück zu den "un-verschlüsselten" Versionen

declare @table table (ID int, PLAIN_TEXT nvarchar(4000)) 
insert into @table 
values 
(1,N'Some Dudes name'), 
(2,N'Another Person Name'), 
(3,N'Yet Another Name') 

--split your string into a column, and compute the decimal value (N) 
if object_id('tempdb..#staging') is not null drop table #staging 
select 
    substring(a.b, v.number+1, 1) as Val 
    ,ascii(substring(a.b, v.number+1, 1)) as N 
    --,dense_rank() over (order by b) as RN 
    ,a.ID 
into #staging 
from (select PLAIN_TEXT b, ID FROM @table) a 
    inner join 
     master..spt_values v on v.number < len(a.b) 
where v.type = 'P' 

--select * from #staging 


--create a fast tally table of numbers to be used to build the ROT-47 table. 

;WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 



--Here we put it all together with stuff and FOR XML 
select 
    PLAIN_TEXT 
    ,ENCRYPTED_TEXT = 
     stuff((
     select 
      --s.Val 
      --,s.N 
      e.ENCRYPTED_TEXT 
     from #staging s 
     left join(
     select 
      N as DECIMAL_VALUE 
      ,char(N) as ASCII_VALUE 
      ,case 
       when 47 + N <= 126 then char(47 + N) 
       when 47 + N > 126 then char(N-47) 
      end as ENCRYPTED_TEXT 
     from cteTally 
     where N between 33 and 126) e on e.DECIMAL_VALUE = s.N 
     where s.ID = t.ID 
     FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 0, '') 
from @table t 


--or if you want really random 
select 
    PLAIN_TEXT 
    ,ENCRYPTED_TEXT = 
     stuff((
     select 
      --s.Val 
      --,s.N 
      e.ENCRYPTED_TEXT 
     from #staging s 
     left join(
     select 
      N as DECIMAL_VALUE 
      ,char(N) as ASCII_VALUE 
      ,char((select ROUND(((122 - N -1) * RAND() + N), 0))) as ENCRYPTED_TEXT 
     from cteTally 
     where (N between 65 and 122) and N not in (91,92,93,94,95,96)) e on e.DECIMAL_VALUE = s.N 
     where s.ID = t.ID 
     FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 0, '') 
from @table t 
Verwandte Themen