Tag Archives: darknet

Hacking around with Twitter (Part 3 !) …

Well that took a little while, but it is now all done 🙂

Et voila :

#!/usr/bin/perl -w
#use strict;

use Getopt::Long;
use Storable;
use Net::Twitter::Lite;
use Crypt::OpenSSL::Random;
use Crypt::OpenSSL::RSA;
use MIME::Base64;

#----------------------------------------------#
#                  This is :                   #
 $clientname = "twitter crypt";       #
#                  Version :                   #
 $clientver = "0.1";            #
#----------------------------------------------#
#            By : Simon Biles                  #
$clienturl="http://computersecurityonline.com";#
#----------------------------------------------#

# Saved Public Keys File
$Public_Keys_File = "twc_public_keys";

GetOptions("genkey=s" => \$genkey,
 "publishkey=s" => \$publishkey,
 "getkeys" => \$getkeys,
 "showkeys" => \$showkeys,
 "encrypt=s" => \$encrypt,
 "getmessages=s" => \$getmessages,
 "user=s" => \$user,
 "pass=s" => \$password );

if (defined $genkey){
 $good_entropy = "10010101001010101";

 Crypt::OpenSSL::Random::random_seed($good_entropy);
 Crypt::OpenSSL::RSA->import_random_seed();

 $rsa = Crypt::OpenSSL::RSA->generate_key(640);

 $private = $rsa->get_private_key_string();
 $public = $rsa->get_public_key_string();

 print "\nprivate key is:\n $private\n";
 print "\npublic key (in PKCS1 format) is:\n $public\n"; 

 open(KEYFILE, "> $genkey") or die $!;
 print KEYFILE "$private\n$public";
 close KEYFILE;

 print "\nKeys written to file $genkey ...\n\n";

 exit 0;
}

if (defined $publishkey && defined $user && defined $password){

 my $nt = Net::Twitter::Lite->new(
 username => $user,
 password => $password,
 clientname => $clientname,
 clientver => $clientver,
 clienturl => $clienturl
 );

 open (KEYFILE, "< $publishkey");
 $flag = 0;
 $public_key = "";
 while (<KEYFILE>){
 if ($_ =~ /-----END RSA PUBLIC KEY-----/) { last; };
 if ($flag == 1) { $public_key = $public_key.$_; };
 if ($_ =~ /-----BEGIN RSA PUBLIC KEY-----/) { $flag = 1; };
 }

 $public_key = "twc-public -".$public_key;

 $key_length = length $public_key;

 print "Length: $key_length \n$public_key";

 if($key_length > 140){
 print "\nFor some reason we've over shot our 140 chars for Twitter, complain ...\n";
 exit 0;
 }

 my $result = eval { $nt->update($public_key) };

 exit 0;
}

if($getkeys && defined $user && defined $password){

if(-e $Public_Keys_File){
 %keys_hash = %{retrieve($Public_Keys_File)};
} else {
 %keys_hash = ();
}

 my $nt = Net::Twitter::Lite->new(
 username => $user,
 password => $password,
 clientname => $clientname,
 clientver => $clientver,
 clienturl => $clienturl
 );

 eval {
 my $statuses = $nt->friends_timeline();
 for my $status ( @$statuses ) {
 if ($status->{text} =~ /twc-public -/){
 ($public_key_string = $status->{text}) =~ s/twc-public -//;
 $keys_hash{ $status->{user}{screen_name} } = $public_key_string;
 }
 }
 };
 warn "$@\n" if $@;

store(\%keys_hash, $Public_Keys_File) or die "\nCan't save public keys to $Public_Keys_File.\n\n";

 exit 0;
}

if($showkeys){

if(-e $Public_Keys_File){
 %keys_hash = %{retrieve($Public_Keys_File)};
 while (($key, $value) = each(%keys_hash)){
 print "$key - $value\n";
 }

} else {

 print "\n\n Public Keys file $Public_Keys_File does not exist, create it using the --getkeys option.";

}

 exit 0;
}

if(defined $encrypt && defined $user && defined $password){

if(-e $Public_Keys_File){
 %keys_hash = %{retrieve($Public_Keys_File)};

 $encryption_key = "-----BEGIN RSA PUBLIC KEY-----\n"."$keys_hash{$encrypt}\n"."-----END RSA PUBLIC KEY-----\n";

 print "$encryption_key";

 $rsa_pub = Crypt::OpenSSL::RSA->new_public_key($encryption_key);
 print "                                           |------------------------------------|\n";
 print "Enter your message : (between the lines !) ";
 $plaintext = <STDIN>;    

 if ((length $plaintext) > 38){
 print "Message too long I'm afraid, I did say to stay between the lines ...\n";
 exit 0;
 }

 $ciphertext = $rsa_pub->encrypt($plaintext);

 $encoded_ciphertext = "twc-msg-$encrypt-".encode_base64($ciphertext);
 $encoded_length = length $encoded_ciphertext;

 if ($encoded_length > 140){
 print "Uh-oh, we've had an over Twitter length moment there !\n";
 exit 0;
 }

 my $nt = Net::Twitter::Lite->new(
 username => $user,
 password => $password,
 clientname => $clientname,
 clientver => $clientver,
 clienturl => $clienturl
 );

 my $result = eval { $nt->update($encoded_ciphertext) };

} else {
 print "\n\n Public Keys file $Public_Keys_File does not exist, so there is no key for $encrypt create it using the --getkeys option.";
 exit 0;
}

 exit 0;
}

if(defined $getmessages && defined $user && defined $password){

$private_key = "";

 if (-e $getmessages){
 open (FILEHANDLE, "< $getmessages");
 while(<FILEHANDLE>){
 if ($_ =~ /-----BEGIN RSA PRIVATE KEY-----/){
 $flag = 1;
 }
 if ($flag == 1){
 $private_key = "$private_key"."$_";
 }
 if($_ =~ /-----END RSA PRIVATE KEY-----/){ last; }
 }

 $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($private_key);

 my $nt = Net::Twitter::Lite->new(
 username => $user,
 password => $password,
 clientname => $clientname,
 clientver => $clientver,
 clienturl => $clienturl
 );

 eval {
 my $statuses = $nt->friends_timeline();
 for my $status ( @$statuses ) {
 if ($status->{text} =~ /twc-msg-$user-/){
 $from = $status->{user}{screen_name};
 ($encoded_ciphertext = $status->{text}) =~ s/twc-msg-$user-//;
 $ciphertext = decode_base64($encoded_ciphertext);
 $decrypted = $rsa_priv->decrypt($ciphertext);
 print "Message from $from : $decrypted\n";
 }
 }
 };
 warn "$@\n" if $@;

 exit 0;
 } else {
 print "That key file doesn't appear to exist ...\n";
 exit 0;
 }

 exit 0;
}

#Useage information ... should get here if all else fails !

print "\nSorry the correct useage of twcrypt.pl is :\n\n";
print "twcrypt.pl --genkey keyfile\n\t- generate a key file of name keyfile.\n\n";
print "twcrypt.pl --publishkey keyfile --user username --pass password\n\t- publish the keyfile to twitter for specified account.\n\n";
print "twcrypt.pl --getkeys --user username --pass password\n\t- collect keys published by people you are following.\n\n";
print "twcrypt.pl --showkeys\n\t- show cached public keys.\n\n";
print "twcrypt.pl --encrypt to --user username --pass password\n\t- encrypt a message to a given user.\n\n";
print "twcrypt.pl --getmessages --user username --pass password\n\t- get messages sent to you.\n\n\n";
print "I do realise this isn't the best interface, but hell, live with it ...\n\n";

exit 0;

It works too ! Creating, uploading, encrypting and decrypting through Twitter – Twitter PKI – you saw it here first 😛

I only made one small modification to the planed implementation, and that was to include the name of the recipient – I found that the attempt to decrypt a message with the wrong private key for the encryption caused a crash out, so I though that it would be best to keep it to only decrypting what it is supposed to.

All comments and critique of my code welcome … Please remember though that it’s only a proof of concept – I would be interested in any major flaws though … ( A low key length isn’t a flaw, it’s a practicality by the way – 640 bits should keep most people at bay for a fairly reasonable amount of time 🙂 and is all I could fit into Twitter. ) I hope that the code is self explanatory, if you do have any questions, please drop me a line at si at thinking-security.com

I’m going to go and have a break from the computer now … I might fiddle with this some more later to make it a little more useable, maybe a GUI or iPhone version 😉

Tagged , , ,

Hacking around with Twitter … ( Part 2 ! )

Cryptographically secure pseudorandom number g...

 (Photo credit: Wikipedia)

Well, I’m into day two of this project – well into the code now, and it’s comming on ok …

Phase 4(a) : Get Net::Twitter::Lite to connect to, pick up and update an account. This is pretty well documented in the examples on CPAN, although I’ve pared it right down to the minimum in just to get the post, as the date was throwing up an error, as it isn’t important to the proof of concept at this point ( might be a nicety later on … ) so the code stands like this just now …

#!/usr/bin/perl -w
#use strict;

use Net::Twitter::Lite;

#----------------------------------------------#
#                  This is :                   #
 $clientname = "twitter crypt";       #
#                  Version :                   #
 $clientver = "0.1";            #
#----------------------------------------------#
#            By : Simon Biles                  #
$clienturl="http://computersecurityonline.com";#
#----------------------------------------------#

$user="twcrypt";
$password="*********";

 my $nt = Net::Twitter::Lite->new(
 username => $user,
 password => $password,
 clientname => $clientname,
 clientver => $clientver,
 clienturl => $clienturl
 );

 my $result = eval { $nt->update('Hello, world!') };

 eval {
 my $statuses = $nt->friends_timeline();
 for my $status ( @$statuses ) {
 print "<$status->{user}{screen_name}> $status->{text}\n";
 }
 };
 warn "$@\n" if $@;

In theory the $clientname and $clientver should change the “via” entry, however this doesn’t seem to be the case as it appears to remain as “via Perl Net::Twitter” in TweetDeck.

This gives out the result of :

MacBook:TWCrypt si$ ./twcrypt.pl
 Hullooo ?
 twcrypt_a test
 Hello, world!

Which are either from <twcrypt> the result of the update or are pulling from the following list posts. So far so good !

Phase 4(b) : Right, now for RSA Encryption … If you aren’t familiar with RSA ( and I only vaugely remember the maths from University … ) it is a public key crypto system developed originally at GCHQ, although the offical secrets act meant that Ron Rivest, Adi Shamir, and Leonard Adleman got there independently. I’m _not_ going to go through how it works, mostly ‘cos I’d confuse the matter more, but the Wikipedia Article is pretty good ! Ignore the maths and work through the example to really get how it works 🙂

The example code for Crypt::OpenSSL::RSA isn’t quite so good, there are some typos which have left me stumped for ages … But I got there in the end, and in conjunction with MIME::Base64 have a way of encoding and decoding the strings into something that Twitter will accept. After playing around with key lengths, I’ve gone with 640bits, as this gives a nice ciphertext size of 110 chars and accomodates an encrypted message of upto 38 chars – not exactly War and Peace – I may have to implement that multi-part message sooner rather than later ! 640 bits also gives an RSA encoded key of 122 chars, so we are still comfortably within the 140 char Twitter limit.

#!/usr/bin/perl -w
#use strict;

use Crypt::OpenSSL::Random;
use Crypt::OpenSSL::RSA;
use MIME::Base64;

$plaintext = "12345678901234567890123456789012345678";
$good_entropy = "10010101001010101";

Crypt::OpenSSL::Random::random_seed($good_entropy);
Crypt::OpenSSL::RSA->import_random_seed();$rsa = Crypt::OpenSSL::RSA->generate_key(640);print "private key is:\n", $rsa->get_private_key_string();
print "public key (in PKCS1 format) is:\n", $rsa->get_public_key_string();print "Plaintext = $plaintext\n";
$ciphertext = $rsa->encrypt($plaintext);
print "Encrypted = -!-$ciphertext-!-\n";
$encoded = encode_base64($ciphertext);
$encoded_length = length $encoded;
print "Encoded = $encoded Length = $encoded_length\n";
$decoded = decode_base64($encoded);
print "Decoded = $decoded\n";
$decrypted = $rsa->decrypt($decoded);
print "Decrypted = $decrypted\n";

This gives us an output of :

MackBook:TWCrypt si$ ./twcrypt.pl
private key is:
-----BEGIN RSA PRIVATE KEY-----
MIIBgwIBAAJRAO2VqyVoQFyJkddP+zPzUuoyfDZVaPgn8LxHKFNETwVKdcAOfvm4
koOBcMcGGgwhaFQjEeg5JpNXBvXg67CbWvGpSLpCxonhFdoJprFAC/GBAgMBAAEC
UQCF0hGuZkQqW0qMTn6dymZfh8QzDnSrokOUqTfrfsRLpJ8iaIfYvL+4wPBb0+9z
1DALyIk9SX+MVTwdE7zanrHAxZVOb/zWVioVca0ih3M4yQIpAPi5mTO0lVU4mSw5
acNoPJhkJp901OYgCXVK75MiKJSb+31TmjSoSo8CKQD0iKdHs1ieaoMMx/K91Zmi
dnb80l7aRkU04OZ1ed201OMyP489D0rvAikA+JxzkOYo+iT3nefJWqO/Jce9f1dF
UrylF5OOgm/7RgffyfadxZKN6wIoRczYCwRrkFSQ8c4FQSC+iPxNvJ8ECkQyrwRf
ZDsUCPEXpRk1dtVtqwIobkZm67KhVm5Hp4NRhWIiFODNuzcfwZfakM8Fhvk9dBtv
1GAKqXOeEQ==
-----END RSA PRIVATE KEY-----
public key (in PKCS1 format) is:
-----BEGIN RSA PUBLIC KEY-----
MFgCUQDtlaslaEBciZHXT/sz81LqMnw2VWj4J/C8RyhTRE8FSnXADn75uJKDgXDH
BhoMIWhUIxHoOSaTVwb14Ouwm1rxqUi6QsaJ4RXaCaaxQAvxgQIDAQAB
-----END RSA PUBLIC KEY-----
Plaintext = 12345678901234567890123456789012345678
Encrypted = -!-g$S9?+?????<}&3~?"?q?    ?=???):??R'?+?/?*3?:??x:??p{?!?o??-??m??ʣ??N?<ɍI?q-!-
Encoded = ZyRTOa8rH531r56PPH99JjN+ryKEcYoJhD2WgqUpOtjIUieLFCuqL5ccKjPuOokT9ng6/NBwe5wh
HOtvkfct4cxtl8LKo4HFTos8yY1J+3E=
 Length = 110
Decoded = g$S9?+?????<}&3~?"?q?    ?=???):??R'?+?/?*3?:??x:??p{?!?o??-??m??ʣ??N?<ɍI?q
Decrypted = 12345678901234567890123456789012345678

So that all appears to be working ok …

Phase 4(c): Stich the two things together into a useable program ! This is only a proof of concept, so I’m going to just write a simple command line utility with a few switches to show the point, the plan ( at the moment ) is to end up with something like this :

twcrypt [--genkey keyfile] [--publishkey keyfile] [--getkeys] [--showkeys] [--encrypt to] [--getmessages keyfile] [--user user] [--pass password]

I hope that is quite self explanitory, but read on anyhoo and you’ll get the drift I’m sure …

I got somewhat distracted last night by a terrible film rental (“Thick as Thieves”, Morgan Freeman and Antonio Banderas – don’t bother, it’s not worth it … ) so I’ve not finished this off yet – I thought that I’d post this much and then the final part soon.

Tagged , , , , , ,

Hacking around with Twitter …

Image representing Twitter as depicted in Crun...

Image via CrunchBase

Twitter is an interesting beast … I’m still not too sure if I really see that there is any real benefit from it – I do find it fun though 🙂 Anyhoo, it occurred to me as I was driving home tonight, stuck in the pouring rain, in Oxford traffic, that Twitter, like all of these social networking sites, is a great way to send coded messages. ( Watch my hit count rise drastically as the NSA and GCHQ hammer me 😉 ) There are enough tweets, and they are random enough to drown out pretty much any useful data, but even so, I’d be reluctant as a spy or other to use twitter either in code or directly to communicate with my handlers / followers … It’s a bit too obvious – this led me to think of encryption, and rather conveniently, Twitter itself sets the key size ! Allowing for a few control characters to identify the different types of message, I think that it is possible to implement a neat little public key exchange / encryption setup using Twitter & using Perl, a few CPAN libraries, and this blog, I’m going to set out to do it as a proof of concept over the next few days …

Phase 1 : Completed before I started typing this up – get myself a few extra twitter accounts to play with TweetDeck graciously supports multiple accounts so I can monitor the Perl back processes, so I now have twcrypt, twcrypt_a and twcrypt_b to play with …

Phase 2: Raid CPAN for someone else’s hard work 🙂 Net::Twitter::Lite by Marc Mims and Crypt::OpenSSL::RSA by Ian Robertson ( after several false starts with other RSA implementations and much fun with Math::Pari. ). So that I stand some chance of getting _some_ sleep before morning ! ( If you are on MacOS X, as I am, running cpan sudo aids in the installation somewhat …  )

Phase 2(a): Install Komodo Edit on new laptop, because I’ve not done it yet … Great Perl editor, and free !

Phase 3: Quick planning stage … 140 chars – 128 char for the key leaves … drum roll … 12 for signals soooo …

01 02 03 04 05 06 07 08 09 10 11 12t  w  c                          -  = type marker ( note the - at char 12 )
t  w  c  -  p  u  b  l  i  c     -  = public key distro indicator
t  w  c  -  m  s  g              -  = message indicator ( thinking about allowing multipart messages later )

That’s about it for now, either I’m too tired, too stupid or there just plain aren’t any more required at this time ( could abbreviate I guess and have a stronger key ? ) At the moment, I think that the two communicating parties are going to have to be followers, with only 12 chars to spare there’s not enough room to use @names …

Quick Aside : This isn’t a 128 bit key, this is a 128 byte key or 8 times that e.g. 1024 bit – this is considered pretty much the minimum standard in the world of encryption with 2048 and larger keys being in common, difficult to break, use. You should bear in mind though that a 1024 bit key still supplies a fair standard of encryption. Having said all of this, OpenSSL is being a bugger for actually generating a key that _is_ 128 bytes long, if I generate a 1024bit key, I seem to end up with a 217 byte public section when all is said and done … More investigation tomorrow !
 
With thanks to ...

With thanks to xkcd

Phase 4: Start writing program … in the morning 🙂

Tagged , , , , , ,