Your Mother has asked for the wisdom of the Perl Monks concerning the following question:

For an uncookied, no authentication, setup I'd like to color users by their IPs. Not as security or anything, just to distinguish them a bit. My style of problem solving in new domains is woefully brute-trial-and-error and since this seems fun and interesting, I'm putting it up.

I've played around with things like this:

sub xor_it_together { my @ip = shift =~ /(\d+)/g; my $code = join'^',@ip; print eval "$code"; } # xor_it_together('67.167.26.54') --> 200 # xor_it_together('127.0.0.1') --> 126

That could be okay, maybe, for a gray scale; rgb(128,128,128). But different rgb would be nice. So this next bit seems to be passable (a final version should probably add a reproducable random seed, like an IP digest, so that IPs can't be reverse engineered from the colors).

use List::Util "sum"; sub ip2rgb { my @ip = shift =~ /(\d+)/g; my $r = eval "@{[ join '^', @ip ]}"; my $g = sum(@ip) % 255; # left-overs my ( $b ) = sort @ip; # lowest of group print "$r, $g, $b"; } # ip2rgb '220.17.120.164' --> 17, 11, 120 # ip2rgb '127.0.0.1' --> 126, 128, 0

Any nicer or alternative ideas?

update (20050829-1914): I'm glad I got over my temerity about posting the question. All the answers are cool and I am learning something new from all of them. Thanks!

Replies are listed 'Best First'.
Re: Creative presentation algorithm: IP to a color
by Zaxo (Archbishop) on Aug 29, 2005 at 01:18 UTC

    An alternative would be to let the r.g.b/24 subnet produce the color. That is simple, direct and irreversable, but still meaningful to the eye.

    sub ip2rgb { my @ip = @_; push @ip, (0) x 3; @ip[0..2]; }

    That takes the ip quad as a list of octets. The Socket::inet_*() functions can be used to convert address forms.

    After Compline,
    Zaxo

      Probably not too useful, but the last octet could be used for transparency.
      -- Argel
Re: Creative presentation algorithm: IP to a color
by QM (Parson) on Aug 29, 2005 at 01:18 UTC
    How many IPs do you expect as a max?

    Why not choose a list of colors, a suitable hash function for IPs, and use $color{hash(@ip)}?

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      MD5 could be used as a hash function here on the IP-string (or any string as a matter of fact), and the first 3 pairs of hex-characters could be used as rgb values:
      #!/usr/bin/perl -l use strict; use Digest::MD5 qw(md5_hex); my $ip="192.168.7.1"; my $ip2="192.168.7.2"; my $ip3="192.168.7.3"; my $ip4="192.168.7.4"; print join(",", ip2color($ip)); print join(",", ip2color($ip2)); print join(",", ip2color($ip3)); print join(",", ip2color($ip4)); sub ip2color { my ($ip) = @_; my $md5 = md5_hex($ip); my @rgb; foreach (0 .. 2) { my $value_in_hex = substr($md5,0+2*$_,2); push @rgb, hex($value_in_hex); } return @rgb; } __DATA__ 251,180,114 35,50,113 80,124,60 221,201,172
      Not meaningful for the eye these colors (like Zaxo's solution), but neighboring IPs very likely will have different colors.

      Indeterminate really; visitors' IPs from anywhere. Assume all of them. :) I liked Zaxo's below and I'm going to play with it. Love to see more ideas too. Just for fun.

Re: Creative presentation algorithm: IP to a color
by Elijah (Hermit) on Aug 29, 2005 at 04:19 UTC
    Here is simply another way of using the first three octets of the users ip address to create a hexadecimal string that can be used as html color argument.
    #!/usr/bin/perl -w use strict; my @octets = split(/\./, $ENV{'REMOTE_ADDR'}); pop(@octets); my @hexval; push(@hexval, dec2hex($_)) for (@octets); my $hex = join("", @hexval); print "Content-type: text/html; charset=ISO-8859-1\n\n"; print "The hex value is: <font color=$hex>$hex</font>\n"; sub dec2hex { my $decnum = shift; my ($hexnum, $modulus, @hexval); $hexnum = int($decnum / 16); $hexnum = chr($hexnum + 55) if ($hexnum > 9); push(@hexval, $hexnum); $modulus = $decnum % 16; $modulus = chr($modulus + 55) if ($modulus > 9); push(@hexval, $modulus); return join("", @hexval); }

    Not sure how you plan on making it irreversible. If you use the method of converting the IP into a hex number it will always be able to be reversed if anyone figures out how you vreate the hex. However all that will be able to be recovered is the first three octets. Also with this method you have the possibility of having 253 users (255 minus 1 for broadcast and one for gateway) with the same color. Be it a very very small chance that every user from that IP range will visit your site at once.

      I think using MD5 (as i demonstrated above) sort-of solves this irreversibility-problem. MD5 is a one-way hashing algorithm, so in principle you'll only be able to get back from rgb-value to IP if you have a full table of IP to rgb-value's (a 'brute force' attack). MD5 is not the strongest of one-way hashing algoritms, but it's widely used and widely available.
Re: Creative presentation algorithm: IP to a color
by Ven'Tatsu (Deacon) on Aug 29, 2005 at 15:27 UTC

    From a usability stand point I think that you don't want to use the full range of RGB colors. Otherwise you may have a color like #F0E7FA appear on a white page and be nearly invisable.

    for example: #F0E7FA

    The easyest way to do that would be to set the most significant bit of each byte of the RGB value to 0 for light backgrounds and 1 for dark backgrounds. This limits the color space to only 21 bits, however setting only one of the most significant bits opposite of the others doesn't move the color too far to make text illegable to me, so picking one or none of the 3 bits gives 4 options, or to look at it another way restores 2 bits to the color space without sacrificing readability of the text.

    In my code I do this by using the last 3 bytes of the IP address for the base RGB values, shifting off the least significant bit. Then take the first byte and and xor each 2 bit group with the others to get a 2 bit number to select which byte to set the most significant bit. Finely a flag toggles all the most significant bits if the text should be bright. I think this would effectivly hide the IP address while still keeping many 'close' ip addresses close in color. (though the choice of using the first byte of the IP address to affect the most significant bits by xoring it together will place many distant IP addresses near each other in the color space.)

    sub ip2rgb { my $ip = shift; my $bright = shift; my @octets = split /\./, $ip; my $mso = shift @octets; my @rgb = map { $_ >> 1 } @octets; my $msb = ($mso >> 6 & 0x03) ^ ($mso >> 4 & 0x03) ^ ($mso >> 2 & 0 +x03) ^ ($mso >> 2 & 0x03) ^ ($mso & 0x03); if ($msb != 3) { $rgb[$msb] |= 0x80; } if ($bright) { for (@rgb) { $_ ^= 0x80; } } return @rgb; }
Re: Creative presentation algorithm: IP to a color
by Codon (Friar) on Aug 29, 2005 at 17:33 UTC
    You could take the IP, XOR each element in succession to get a random seed, then randomly select three elements for RGB, then randomly XOR or AND the the fourth element with each of the selected RGB elements. This should have enough randomness to prevent RE of the IP and would (hopefully) produce something other than a nice even shade of grey.
    use strict; use warnings; my @ips = qw( 127.0.0.1 192.172.24.23 172.25.1.86 66.35.250.150 209.197.123.153 66.39.54.27 204.74.99.100 ); for my $ip (@ips) { my @ip = split /\./, $ip; my $seed = 0; $seed ^= $_ for @ip; srand($seed); my ($r,$g,$b,$mask) = map { splice @ip, int(rand(scalar @ip)), 1 } + (1 .. @ip); ($r,$g,$b) = map { int(rand(2)) ? $_ ^ $mask : $_ & $mask } ($r,$g +,$b); printf("%-15s => %3d %3d %3d\n",$ip,$r,$g,$b); }
    This will produce the following:
    127.0.0.1 => 0 0 0 192.172.24.23 => 4 16 215 172.25.1.86 => 250 173 181 66.35.250.150 => 2 212 66 209.197.123.153 => 190 170 226 66.39.54.27 => 45 38 2 204.74.99.100 => 96 46 168
    Here we have 2 coming from 66 in the Red column and 27 in the Blue column. I don't thing this is reverse-engineerable. And since we are using the IP to derive the random seed, we are guaranteed that the same IP will produce the same RGB value.

    Ivan Heffner
    Sr. Software Engineer, DAS Lead
    WhitePages.com, Inc.