1

XOR「暗号化」クラスの次のJAVAクラスがあります。

import java.io.PrintStream;

public class Encryptor
{

    private static final String m_strPrivateKey = "4p0L@r1$";

    public Encryptor()
    {
    }

    public static String encrypt(String pass)
    {
        String strTarget = XORString(pass);
        strTarget = StringToHex(strTarget);
        return strTarget;
    }

    public static String decrypt(String pass)
    {
        String strTarget = HexToString(pass);
        strTarget = XORString(strTarget);
        return strTarget;
    }

    private static String GetKeyForLength(int nLength)
    {
        int nKeyLen = "4p0L@r1$".length();
        int nRepeats = nLength / nKeyLen + 1;
        String strResult = "";
        for(int i = 0; i < nRepeats; i++)
        {
            strResult = strResult + "4p0L@r1$";
        }

        return strResult.substring(0, nLength);
    }

    private static String HexToString(String str)
    {
        StringBuffer sb = new StringBuffer();
        char buffDigit[] = new char[4];
        buffDigit[0] = '0';
        buffDigit[1] = 'x';
        int length = str.length() / 2;
        byte bytes[] = new byte[length];
        for(int i = 0; i < length; i++)
        {
            buffDigit[2] = str.charAt(i * 2);
            buffDigit[3] = str.charAt(i * 2 + 1);
            Integer b = Integer.decode(new String(buffDigit));
            bytes[i] = (byte)b.intValue();
        }

        return new String(bytes);
    }

    private static String XORString(String strTarget)
    {
        int nTargetLen = strTarget.length();
        String strPaddedKey = GetKeyForLength(nTargetLen);
        String strResult = "";
        byte bytes[] = new byte[nTargetLen];
        for(int i = 0; i < nTargetLen; i++)
        {
            int b = strTarget.charAt(i) ^ strPaddedKey.charAt(i);
            bytes[i] = (byte)b;
        }

        String result = new String(bytes);
        return result;
    }

    private static String StringToHex(String strInput)
    {
        StringBuffer hex = new StringBuffer();
        int nLen = strInput.length();
        for(int i = 0; i < nLen; i++)
        {
            char ch = strInput.charAt(i);
            int b = ch;
            String hexStr = Integer.toHexString(b);
            if(hexStr.length() == 1)
            {
                hex.append("0");
            }
            hex.append(Integer.toHexString(b));
        }

        return hex.toString();
    }

    public static void main(String args[])
    {
        if(args.length < 1)
        {
            System.err.println("Missing password!");
            System.exit(-1);
        }
        String pass = args[0];
        String pass2 = encrypt(pass);
        System.out.println("Encrypted: " + pass2);
        pass2 = decrypt(pass2);
        System.out.println("Decrypted: " + pass2);
        if(!pass.equals(pass2))
        {
            System.out.println("Test Failed!");
            System.exit(-1);
        }
    }
}

次のようにPerlに移植しようとしました:

#!/usr/bin/perl

use strict;
use warnings;

my $pass = shift || die "Missing password!\n";
my $pass2 = encrypt($pass);
print "Encrypted: $pass2\n";
$pass2 = decrypt($pass2);
print "Decrypted: $pass2\n";
if ($pass ne $pass2) {
    print "Test Failed!\n";
    exit(-1);
}

sub encrypt {
    my $pass = shift;
    my $strTarget = XORString($pass);
    $strTarget = StringToHex($strTarget);
    return $strTarget;
}

sub decrypt {
    my $pass = shift;
    my $strTarget = HexToString($pass);
    $strTarget = XORString($strTarget);
    return $strTarget;
}

sub GetKeyForLength {
    my $nLength = shift;
    my $nKeyLen = length '4p0L@r1$';
    my $nRepeats = $nLength / $nKeyLen + 1;
    my $strResult = '4p0L@r1$' x $nRepeats;
    return substr $strResult, 0, $nLength;
}

sub HexToString {
    my $str = shift;
    my @bytes;

    while ($str =~ s/^(..)//) {
        my $b = eval("0x$1");
        push @bytes, chr sprintf("%d", $b);
    }
    return join "", @bytes;
}

sub XORString {
    my $strTarget = shift;
    my $nTargetLen = length $strTarget;
    my $strPaddedKey = GetKeyForLength($nTargetLen);
    my @bytes;

    while ($strTarget) {
        my $b = (chop $strTarget) ^ (chop $strPaddedKey);
        unshift @bytes, $b;
    }
    return join "", @bytes;
}

sub StringToHex {
    my $strInput = shift;
    my $hex = "";
    for my $ch (split //, $strInput) {
        $hex .= sprintf("%02x", ord $ch);
    }
    return $hex;
}

コードは問題ないように見えますが、問題は Java クラスが Perl コードとは異なる結果を出力することです。JAVA にはプレーンテキストのパスワードがあります

メントス

そして、それは次のようにエンコードされます

&4\=80CHB'

同じ結果を得るには、Perl スクリプトをどうすればよいですか? どこで間違っていますか?

別の 2 つの例: プレーンテキスト

07ch4ssw3by

次のようにエンコードされます。

,#(0\=DM.'@ '8WQ2T

(@の後のスペースに注意してください)

最後の例、平文:

conf75

次のようにエンコードされます:

&7]P0G-#!

手伝ってくれてありがとう!

Joni Salonen のおかげで、これで終わりました。

#!/usr/bin/perl
# XOR password decoder
# Greets: Joni Salonen @ stackoverflow.com

$key = pack("H*","3cb37efae7f4f376ebbd76cd");

print "Enter string to decode: ";
$str=<STDIN>;chomp $str; $str =~ s/\\//g;
$dec = decode($str);
print "Decoded string value: $dec\n";

sub decode{ #Sub to decode
    @subvar=@_;
    my $sqlstr = $subvar[0];
    $cipher = unpack("u", $sqlstr);
    $plain = $cipher^$key;
    return substr($plain, 0, length($cipher));
}

私の唯一の最後の問題は、「\」が見つかった場合(実際には「\\」が実際の文字をエスケープしたため)、復号化がうまくいかないことです:-\ エンコードされた文字列の例:

"(4\\4XB\:7"G@、"

(二重引用符でエスケープしました。文字列の最後の文字はスペースです。デコードして

「ovFsB6mu」

更新: Joni Salonen のおかげで、100% 動作する最終バージョンができました:

#!/usr/bin/perl
# XOR password decoder
# Greets: Joni Salonen @ stackoverflow.com

$key = pack("H*","3cb37efae7f4f376ebbd76cd");

print "Enter string to decode: ";
$str=<STDIN>;chomp $str; $str =~s/\\(.)/$1/g;
$dec = decode($str);
print "Decoded string value: $dec\n";

sub decode{ #Sub to decode
    @subvar=@_;
    my $sqlstr = $subvar[0];
    $cipher = unpack("u", $sqlstr);
    $plain = $cipher^$key;
    return substr($plain, 0, length($cipher));
}
4

1 に答える 1

1

暗号化ループは、$strTargetたまたまの場合、 の最初の文字をスキップします'0'。「true」かどうかを確認する代わりに、空の文字列と比較できます。

while ($strTarget ne '') {
    my $b = (chop $strTarget) ^ (chop $strPaddedKey);
    unshift @bytes, $b;
}

更新:このプログラムは文字列を復号化します:

use feature ':5.10';

$key = pack("H*","3cb37efae7f4f376ebbd76cd");

say decrypt("&4\=80CHB'");          # mentos
say decrypt(",#(0\=DM.'@ '8WQ2T");  # 07ch4ssw3bby
say decrypt("&7]P0G-#!");           # conf75

sub decrypt {
    $in = shift;
    $cipher = unpack("u", $in);
    $plain = $cipher^$key;
    return substr($plain, 0, length($cipher));
}
于 2012-04-10T08:14:01.477 に答える