czwartek, maja 28, 2009
środa, maja 27, 2009
Haszowanie PESELu
public class PH {
private static byte[] hash(String in, String key) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(key.getBytes());
return md.digest(in.getBytes());
}
private static String fillNumber(String s, int len) {
while (s.length() < len)
s = "0"+s;
return s;
}
private static String byte2String(byte[] b, int len) {
StringBuffer sb = new StringBuffer();
for (int i=0; i < Math.min(b.length, len); i++) {
int c = '0' + (b[i] & 0xff)%10;
sb.append((char)c);
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
HashMap<String, String> map = new HashMap<String, String>();
int hc = 0;
for (int i=0; i < 100000; i++) {
String pesel = "721028" + fillNumber(i+"", 5);
String hash5 = byte2String( hash(pesel, "random123!"), 10);
if (map.get(hash5)!=null) {
System.err.println("Kolizja dla peselu "+pesel+" => "+hash5 + " => "+map.get(hash5));
hc++;
}
else
map.put(hash5, pesel);
}
System.err.println("Kolizji: "+hc);
}
}
Haszowanie PESELu ma być częściowe, czyli nie zmieniamy daty urodzenia, a tylko 5 ostatnich cyfr. Jeżeli ze standardowo zahaszowanego stringu z peselem wybierzemy poniżej 10 znaków (z 16) jako klucz, to mamy kolizje. Ponad 36000 na 100000 dla 5 znaków.
Workaround:
CREATE OR REPLACE
PROCEDURE HASH_OSOBY AS
type ROWID_TAB is table of rowid index by binary_integer;
collisions rowid_tab;
collisions_cnt number := 0;
passes number := 0;
key varchar2(4000) := 'klucz1';
err varchar2(4000) := '';
BEGIN
dbms_output.disable;
for rec in (select rowid from monitor.os) loop
begin
update monitor.os set pesel = haszujpesel(pesel, key) where rowid=rec.rowid;
exception when others then
collisions_cnt := collisions_cnt+1;
collisions(collisions_cnt) := rec.rowid;
err := SQLERRM;
insert into log_h(T,LOG) values(sysdate(),err);
end;
end loop;
insert into log_h(T,LOG) values(sysdate(), 'Pass '||passes||', number of collisions: '||collisions_cnt);
while collisions.count > 0 loop
key := key||key;
for i in collisions.first..collisions.last loop
begin
update monitor.os set pesel = haszujpesel(pesel, key) where rowid=collisions(i);
collisions.delete(i);
exception when others then
err := SQLERRM;
insert into log_h(T,LOG) values(sysdate(),err);
end;
end loop;
passes := passes + 1;
collisions_cnt := collisions.count;
insert into log_h(T,LOG) values(sysdate(), 'Pass '||passes||', number of collisions: '||collisions_cnt);
end loop;
END HASH_OSOBY;
Kończąc niniejsze rozważania należy powiedzieć, że w ramach ochrony danych osobowych dane testowe powinny zawierać w pełni zahaszowane PESELe, a o spójność PESELi z datami urodzenia po zahaszowaniu powinien zadbać autor bazy.
wtorek, maja 19, 2009
piątek, maja 15, 2009
java.sql.ResultSet over DOM
Taki wrapper pozwala zachować stary kod operujący tylko na strukturach bazodanowych (rs.getInt...) i jako źródła danych używać obiektów zserializowanych do XML-a.
Node g = DOMHelper.getElementsByTag(p, "group-list").get(0);
rs = new DOMResultSet(g);
while (rs.next()) { // iteracja po węzłach poniżej group-list
// obiekt z wezła group
Group g = Group.fromResultSet(rs);
// w group wskazujemy węzły group-attrib
if (rs.findColumn("group-attrib")>0) {
while (rs.next()) {
GroupAttrib ga = GroupAttrib.fromResultSet(rs, g);
}
rs.refreshRow(); // kasujemy wskazanie
}
Debug.println("Wczytano "+rs.getString("."),this);
// "." oznacza biężący węzeł do zwrócenia jako string XML
}
piątek, maja 08, 2009
17W zużycia energii na mobilnym Athlonie i z GeForce 9100
Sterowniki to 185.18.08 beta. Czyli poprzedni krótki czas pracy na baterii to była wina NVidii.
Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
Option "RegistryDwords" "PowerMizerLevel=0x1"
Option "Coolbits" "1"
EndSection
czwartek, maja 07, 2009
Subskrybuj:
Posty (Atom)