Skip to content

Instantly share code, notes, and snippets.

@aminamid
Last active October 4, 2017 20:35
Show Gist options
  • Save aminamid/68d0fe65ffd5bcac1687 to your computer and use it in GitHub Desktop.
Save aminamid/68d0fe65ffd5bcac1687 to your computer and use it in GitHub Desktop.
decode fftp pw
#!/usr/bin/perl
use strict;
use warnings;
use Crypt::CBC;
use Crypt::Rijndael;
use Digest::SHA1 qw(sha1);
sub main() {
# FFFTPのパスワードを入力
my $ffftp_password = prompt('FFFTP Password');
my $tmp_password = '';
if ( $ffftp_password =~ /^0A/ ) {
# 従来のパスワード形式
$ffftp_password =~ s/^0A//;
$tmp_password = decode_password_original($ffftp_password);
}
elsif ( $ffftp_password =~ /^0C/ ) {
# マスターパスワードありの形式(AES)
$ffftp_password =~ s/^0C//;
$tmp_password = decode_password3($ffftp_password);
}
else {
# 従来のパスワード形式
$tmp_password = decode_password_original($ffftp_password);
}
my $password = ( split( /\x00/, $tmp_password ) )[0];
print $password, "\n";
}
sub prompt {
my ( $msg, $default ) = @_;
print "$msg ";
if ( defined($default) and $default ne '' ) {
print "[$default]";
}
print ": ";
my $value = <STDIN>;
$value =~ tr/\r\n//d;
if ( defined($default) and $default ne '' and $value eq '' ) {
$value = $default;
}
return $value;
}
sub decode_password_original {
my $ffftp_password = $_[0];
my $idx = 0;
my $tmp_password = '';
while ( $idx < length($ffftp_password) ) {
my $ord = ord( substr( $ffftp_password, $idx, 1 ) );
my $ord2 = ord( substr( $ffftp_password, $idx + 1, 1 ) );
my $rnd = ( $ord >> 4 ) & 0x03;
my $ch = ( $ord & 0x0F | ( $ord2 & 0x0F ) << 4 );
$ch <<= 8;
if ( ( $ord & 0x01 ) != 0 ) {
$idx++;
}
$idx += 2;
$ch >>= $rnd;
$ch = ( $ch & 0xFF ) | ( ( $ch >> 8 ) & 0xFF );
$tmp_password .= chr($ch);
}
$tmp_password .= "\x00";
return $tmp_password;
}
sub decode_password3 {
my $ffftp_password = $_[0];
my @ffftp_password = split( /:/, $ffftp_password, 2 );
my $iv = pack( 'H*', $ffftp_password[0] );
my $key = prompt('Master Password');
my $aes_key = create_aes_key($key);
my $cipher = Crypt::CBC->new(
{ key => $aes_key,
key_size => length($aes_key),
literal_key => 1,
cipher => 'Rijndael',
iv => $iv,
padding => 'standard',
prepend_iv => 0,
header => 'none',
}
);
my $tmp_password = $cipher->decrypt( pack( 'H*', $ffftp_password[1] ) );
return $tmp_password;
}
sub create_aes_key() {
my $key = $_[0];
my $hash_key = sha1( $key . '>g^r=@N7=//z<[`:' )
. sha1( $key . 'VG77dO1#EyC]$|C@' );
my $key_index = 0;
my $res_index = 0;
my $aes_key = '';
while ( $res_index < 8 ) {
my $ord
= ord( substr( $hash_key, $res_index * 4, 1 ) ) * 256**3
+ ord( substr( $hash_key, $res_index * 4 + 1, 1 ) ) * 256**2
+ ord( substr( $hash_key, $res_index * 4 + 2, 1 ) ) * 256**1
+ ord( substr( $hash_key, $res_index * 4 + 3, 1 ) ) * 256**0;
for ( my $byte_offset = 0; $byte_offset < 4; $byte_offset++ ) {
$aes_key .= chr( ( $ord >> ( $byte_offset * 8 ) ) & 0xFF );
}
$res_index++;
}
return $aes_key;
}
main();
exit;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment