2004-03-20 07:22:06 +03:00
|
|
|
#!/usr/local/bin/perl
|
2000-06-15 02:44:19 +04:00
|
|
|
#
|
|
|
|
# der_chop ... this is one total hack that Eric is really not proud of
|
|
|
|
# so don't look at it and don't ask for support
|
|
|
|
#
|
|
|
|
# The "documentation" for this (i.e. all the comments) are my fault --tjh
|
|
|
|
#
|
|
|
|
# This program takes the "raw" output of derparse/asn1parse and
|
|
|
|
# converts it into tokens and then runs regular expression matches
|
|
|
|
# to try to figure out what to grab to get the things that are needed
|
|
|
|
# and it is possible that this will do the wrong thing as it is a *hack*
|
|
|
|
#
|
|
|
|
# SSLeay 0.5.2+ should have direct read support for x509 (via -inform NET)
|
|
|
|
# [I know ... promises promises :-)]
|
|
|
|
#
|
|
|
|
# To convert a Netscape Certificate:
|
|
|
|
# der_chop < ServerCert.der > cert.pem
|
|
|
|
# To convert a Netscape Key (and encrypt it again to protect it)
|
|
|
|
# rsa -inform NET -in ServerKey.der -des > key.pem
|
|
|
|
#
|
|
|
|
# 23-Apr-96 eay Added the extra ASN.1 string types, I still think this
|
|
|
|
# is an evil hack. If nothing else the parsing should
|
|
|
|
# be relative, not absolute.
|
|
|
|
# 19-Apr-96 tjh hacked (with eay) into 0.5.x format
|
|
|
|
#
|
|
|
|
# Tim Hudson
|
|
|
|
# tjh@cryptsoft.com
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
|
|
require 'getopts.pl';
|
|
|
|
|
|
|
|
$debug=0;
|
|
|
|
|
|
|
|
# this was the 0.4.x way of doing things ...
|
|
|
|
$cmd="derparse";
|
|
|
|
$x509_cmd="x509";
|
|
|
|
$crl_cmd="crl";
|
|
|
|
$rc4_cmd="rc4";
|
|
|
|
$md2_cmd="md2";
|
|
|
|
$md4_cmd="md4";
|
|
|
|
$rsa_cmd="rsa -des -inform der ";
|
|
|
|
|
|
|
|
# this was the 0.5.x way of doing things ...
|
|
|
|
$cmd="openssl asn1parse";
|
|
|
|
$x509_cmd="openssl x509";
|
|
|
|
$crl_cmd="openssl crl";
|
|
|
|
$rc4_cmd="openssl rc4";
|
|
|
|
$md2_cmd="openssl md2";
|
|
|
|
$md4_cmd="openssl md4";
|
|
|
|
$rsa_cmd="openssl rsa -des -inform der ";
|
|
|
|
|
|
|
|
&Getopts('vd:') || die "usage:$0 [-v] [-d num] file";
|
|
|
|
$depth=($opt_d =~ /^\d+$/)?$opt_d:0;
|
|
|
|
|
|
|
|
&init_der();
|
|
|
|
|
|
|
|
if ($#ARGV != -1)
|
|
|
|
{
|
|
|
|
foreach $file (@ARGV)
|
|
|
|
{
|
|
|
|
print STDERR "doing $file\n";
|
|
|
|
&dofile($file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$file="/tmp/a$$.DER";
|
|
|
|
open(OUT,">$file") || die "unable to open $file:$!\n";
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
$i=sysread(STDIN,$b,1024*10);
|
|
|
|
last if ($i <= 0);
|
|
|
|
$i=syswrite(OUT,$b,$i);
|
|
|
|
}
|
|
|
|
&dofile($file);
|
|
|
|
unlink($file);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub dofile
|
|
|
|
{
|
|
|
|
local($file)=@_;
|
|
|
|
local(@p);
|
|
|
|
|
|
|
|
$b=&load_file($file);
|
|
|
|
@p=&load_file_parse($file);
|
|
|
|
|
|
|
|
foreach $_ (@p)
|
|
|
|
{
|
|
|
|
($off,$d,$hl,$len)=&parse_line($_);
|
|
|
|
$d-=$depth;
|
|
|
|
next if ($d != 0);
|
|
|
|
next if ($len == 0);
|
|
|
|
|
|
|
|
$o=substr($b,$off,$len+$hl);
|
|
|
|
($str,@data)=&der_str($o);
|
|
|
|
print "$str\n" if ($opt_v);
|
|
|
|
if ($str =~ /^$crl/)
|
|
|
|
{
|
|
|
|
open(OUT,"|$crl_cmd -inform d -hash -issuer") ||
|
|
|
|
die "unable to run $crl_cmd:$!\n";
|
|
|
|
print OUT $o;
|
|
|
|
close(OUT);
|
|
|
|
}
|
|
|
|
elsif ($str =~ /^$x509/)
|
|
|
|
{
|
|
|
|
open(OUT,"|$x509_cmd -inform d -hash -subject -issuer")
|
|
|
|
|| die "unable to run $x509_cmd:$!\n";
|
|
|
|
print OUT $o;
|
|
|
|
close(OUT);
|
|
|
|
}
|
|
|
|
elsif ($str =~ /^$rsa/)
|
|
|
|
{
|
|
|
|
($type)=($data[3] =~ /OBJECT_IDENTIFIER :(.*)\s*$/);
|
|
|
|
next unless ($type eq "rsaEncryption");
|
|
|
|
($off,$d,$hl,$len)=&parse_line($data[5]);
|
|
|
|
$os=substr($o,$off+$hl,$len);
|
|
|
|
open(OUT,"|$rsa_cmd")
|
|
|
|
|| die "unable to run $rsa_cmd:$!\n";
|
|
|
|
print OUT $os;
|
|
|
|
close(OUT);
|
|
|
|
}
|
|
|
|
elsif ($str =~ /^0G-1D-1G/)
|
|
|
|
{
|
|
|
|
($off,$d,$hl,$len)=&parse_line($data[1]);
|
|
|
|
$os=substr($o,$off+$hl,$len);
|
|
|
|
print STDERR "<$os>\n" if $opt_v;
|
|
|
|
&do_certificate($o,@data)
|
|
|
|
if (($os eq "certificate") &&
|
|
|
|
($str =! /^0G-1D-1G-2G-3F-3E-2D/));
|
|
|
|
&do_private_key($o,@data)
|
|
|
|
if (($os eq "private-key") &&
|
|
|
|
($str =! /^0G-1D-1G-2G-3F-3E-2D/));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub der_str
|
|
|
|
{
|
|
|
|
local($str)=@_;
|
|
|
|
local(*OUT,*IN,@a,$t,$d,$ret);
|
|
|
|
local($file)="/tmp/b$$.DER";
|
|
|
|
local(@ret);
|
|
|
|
|
|
|
|
open(OUT,">$file");
|
|
|
|
print OUT $str;
|
|
|
|
close(OUT);
|
|
|
|
open(IN,"$cmd -inform 'd' -in $file |") ||
|
|
|
|
die "unable to run $cmd:$!\n";
|
|
|
|
$ret="";
|
|
|
|
while (<IN>)
|
|
|
|
{
|
|
|
|
chop;
|
|
|
|
push(@ret,$_);
|
|
|
|
|
|
|
|
print STDERR "$_\n" if ($debug);
|
|
|
|
|
|
|
|
@a=split(/\s*:\s*/);
|
|
|
|
($d)=($a[1] =~ /d=\s*(\d+)/);
|
|
|
|
$a[2] =~ s/\s+$//;
|
|
|
|
$t=$DER_s2i{$a[2]};
|
|
|
|
$ret.="$d$t-";
|
|
|
|
}
|
|
|
|
close(IN);
|
|
|
|
unlink($file);
|
|
|
|
chop $ret;
|
|
|
|
$ret =~ s/(-3H(-4G-5F-5[IJKMQRS])+)+/-NAME/g;
|
|
|
|
$ret =~ s/(-3G-4B-4L)+/-RCERT/g;
|
|
|
|
return($ret,@ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub init_der
|
|
|
|
{
|
|
|
|
$crl= "0G-1G-2G-3F-3E-2G-NAME-2L-2L-2G-RCERT-1G-2F-2E-1C";
|
|
|
|
$x509="0G-1G-2B-2G-3F-3E-2G-NAME-2G-3L-3L-2G-NAME-2G-3G-4F-4E-3C-1G-2F-2E-1C";
|
|
|
|
$rsa= "0G-1B-1G-2F-2E-1D";
|
|
|
|
|
|
|
|
%DER_i2s=(
|
|
|
|
# SSLeay 0.4.x has this list
|
|
|
|
"A","EOC",
|
|
|
|
"B","INTEGER",
|
|
|
|
"C","BIT STRING",
|
|
|
|
"D","OCTET STRING",
|
|
|
|
"E","NULL",
|
|
|
|
"F","OBJECT",
|
|
|
|
"G","SEQUENCE",
|
|
|
|
"H","SET",
|
|
|
|
"I","PRINTABLESTRING",
|
|
|
|
"J","T61STRING",
|
|
|
|
"K","IA5STRING",
|
|
|
|
"L","UTCTIME",
|
|
|
|
"M","NUMERICSTRING",
|
|
|
|
"N","VIDEOTEXSTRING",
|
|
|
|
"O","GENERALIZEDTIME",
|
|
|
|
"P","GRAPHICSTRING",
|
|
|
|
"Q","ISO64STRING",
|
|
|
|
"R","GENERALSTRING",
|
|
|
|
"S","UNIVERSALSTRING",
|
|
|
|
|
|
|
|
# SSLeay 0.5.x changed some things ... and I'm
|
|
|
|
# leaving in the old stuff but adding in these
|
|
|
|
# to handle the new as well --tjh
|
|
|
|
# - Well I've just taken them out and added the extra new
|
|
|
|
# ones :-) - eay
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach (keys %DER_i2s)
|
|
|
|
{ $DER_s2i{$DER_i2s{$_}}=$_; }
|
|
|
|
}
|
|
|
|
|
|
|
|
sub parse_line
|
|
|
|
{
|
|
|
|
local($_)=@_;
|
|
|
|
|
|
|
|
return(/\s*(\d+):d=\s*(\d+)\s+hl=\s*(\d+)\s+l=\s*(\d+|inf)\s/);
|
|
|
|
}
|
|
|
|
|
|
|
|
# 0:d=0 hl=4 l=377 cons: univ: SEQUENCE
|
|
|
|
# 4:d=1 hl=2 l= 11 prim: univ: OCTET_STRING
|
|
|
|
# 17:d=1 hl=4 l=360 cons: univ: SEQUENCE
|
|
|
|
# 21:d=2 hl=2 l= 12 cons: univ: SEQUENCE
|
|
|
|
# 23:d=3 hl=2 l= 8 prim: univ: OBJECT_IDENTIFIER :rc4
|
|
|
|
# 33:d=3 hl=2 l= 0 prim: univ: NULL
|
|
|
|
# 35:d=2 hl=4 l=342 prim: univ: OCTET_STRING
|
|
|
|
sub do_private_key
|
|
|
|
{
|
|
|
|
local($data,@struct)=@_;
|
|
|
|
local($file)="/tmp/b$$.DER";
|
|
|
|
local($off,$d,$hl,$len,$_,$b,@p,$s);
|
|
|
|
|
|
|
|
($type)=($struct[4] =~ /OBJECT_IDENTIFIER :(.*)\s*$/);
|
|
|
|
if ($type eq "rc4")
|
|
|
|
{
|
|
|
|
($off,$d,$hl,$len)=&parse_line($struct[6]);
|
|
|
|
open(OUT,"|$rc4_cmd >$file") ||
|
|
|
|
die "unable to run $rc4_cmd:$!\n";
|
|
|
|
print OUT substr($data,$off+$hl,$len);
|
|
|
|
close(OUT);
|
|
|
|
|
|
|
|
$b=&load_file($file);
|
|
|
|
unlink($file);
|
|
|
|
|
|
|
|
($s,@p)=&der_str($b);
|
|
|
|
die "unknown rsa key type\n$s\n"
|
|
|
|
if ($s ne '0G-1B-1G-2F-2E-1D');
|
|
|
|
local($off,$d,$hl,$len)=&parse_line($p[5]);
|
|
|
|
$b=substr($b,$off+$hl,$len);
|
|
|
|
($s,@p)=&der_str($b);
|
|
|
|
open(OUT,"|$rsa_cmd") || die "unable to run $rsa_cmd:$!\n";
|
|
|
|
print OUT $b;
|
|
|
|
close(OUT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
print "'$type' is unknown\n";
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub do_certificate
|
|
|
|
{
|
|
|
|
local($data,@struct)=@_;
|
|
|
|
local($file)="/tmp/b$$.DER";
|
|
|
|
local($off,$d,$hl,$len,$_,$b,@p,$s);
|
|
|
|
|
|
|
|
($off,$d,$hl,$len)=&parse_line($struct[2]);
|
|
|
|
$b=substr($data,$off,$len+$hl);
|
|
|
|
|
|
|
|
open(OUT,"|$x509_cmd -inform d") || die "unable to run $x509_cmd:$!\n";
|
|
|
|
print OUT $b;
|
|
|
|
close(OUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub load_file
|
|
|
|
{
|
|
|
|
local($file)=@_;
|
|
|
|
local(*IN,$r,$b,$i);
|
|
|
|
|
|
|
|
$r="";
|
|
|
|
open(IN,"<$file") || die "unable to open $file:$!\n";
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
$i=sysread(IN,$b,10240);
|
|
|
|
last if ($i <= 0);
|
|
|
|
$r.=$b;
|
|
|
|
}
|
|
|
|
close(IN);
|
|
|
|
return($r);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub load_file_parse
|
|
|
|
{
|
|
|
|
local($file)=@_;
|
|
|
|
local(*IN,$r,@ret,$_,$i,$n,$b);
|
|
|
|
|
|
|
|
open(IN,"$cmd -inform d -in $file|")
|
|
|
|
|| die "unable to run der_parse\n";
|
|
|
|
while (<IN>)
|
|
|
|
{
|
|
|
|
chop;
|
|
|
|
push(@ret,$_);
|
|
|
|
}
|
|
|
|
return($r,@ret);
|
|
|
|
}
|
|
|
|
|