4

モバイル プラットフォーム オペレーティング システム用の Java アプリケーションの開発を検討しています。

Windows 環境用の C# WPF でアプリケーションを開発しました。次のコードを使用して文字列を暗号化および復号化するために、暗号ストリームを使用しています。以下に示すコードは暗号化のみです

public string encrypt(string encryptionString)
    {
        byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString);

        SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();

        MemoryStream ms = new MemoryStream();
        byte[] rgbIV = Encoding.ASCII.GetBytes("ryojvlzmdalyglrj");
        byte[] key = Encoding.ASCII.GetBytes("hcxilkqbbhczfeultgbskdmaunivmfuo");
        CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write);

        cs.Write(clearTextBytes, 0, clearTextBytes.Length);

        cs.Close();

        return Convert.ToBase64String(ms.ToArray());
    }

暗号化された文字列は、オンライン データベースに格納されます。私ができる必要があるのは、Java アプリケーションがデータベースから文字列を読み取り、C# アプリケーションからの同じ暗号化キーを使用して文字列を復号化できるようにすることです。

ご協力いただきありがとうございます。

4

7 に答える 7

6

個人的には、Java 暗号用のBouncyCastleが好きです。このコード (BouncyCastle 軽量 API を使用) でうまくいくはずです。

String decrypt(byte[] cryptoBytes, byte[] key, byte[] iv) {
    BlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
    cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));
    byte[] out = new byte[cipher.getOutputSize(cryptoBytes.length)];
    int offset = cipher.processBytes(cryptoBytes, 0, cryptoBytes.length, out, 0);
    cipher.doFinal(out, offset);
    return new String(out);
}

BouncyCastle の軽量 API は、JCE プロバイダーのものよりも痛みが少ないと思いますが、必要に応じてプロバイダーとして使用できます。

.netSymmetricAlgorithmと BC の両方のPaddedBufferedBlockCipherデフォルトの PKCS7 パディングのように見えるので、デフォルトを使用しても問題ないはずです。

于 2011-01-04T22:49:43.443 に答える
2

javax.crypto.CipherInputStream と javax.crypto.CipherOutputStream を確認してください。

http://download.oracle.com/javase/1.5.0/docs/api/javax/crypto/CipherInputStream.html http://download.oracle.com/javase/1.5.0/docs/api/javax/crypto /CipherOutputStream.html

Cipher オブジェクトの初期化は若干異なる場合がありますが、上記のサンプルとほぼ同じ方法で使用されます。

于 2011-01-04T22:37:18.467 に答える
0

.netとjavaの間の暗号化には以下を使用します

.netで私は使用します:

    /// <summary>
    /// DES Encryption method - used to encryp password for the java.
    /// </summary>
    /// <param name="plainText"></param>
    /// <returns></returns>
    public string EncryptData(string plainText)
    {
        DES des = new DESCryptoServiceProvider();
        des.Mode = CipherMode.ECB;
        des.Padding = PaddingMode.PKCS7;

        des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));
        des.IV = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));

        byte[] bytes = Encoding.UTF8.GetBytes(plainText);
        byte[] resultBytes = des.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length);

        return Convert.ToBase64String(resultBytes);
    }

    /// <summary>
    /// DES Decryption method - used the decrypt password encrypted in java
    /// </summary>
    /// <param name="encryptedText"></param>
    /// <returns></returns>
    public string DecryptData(string encryptedText)
    {
        DES des = new DESCryptoServiceProvider();
        des.Mode = CipherMode.ECB;
        des.Padding = PaddingMode.PKCS7;
        des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));
        des.IV = System.Text.Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));

        byte[] bytes = Convert.FromBase64String(encryptedText);
        byte[] resultBytes = des.CreateDecryptor().TransformFinalBlock(bytes, 0, bytes.Length);

        return Encoding.UTF8.GetString(resultBytes);
    }

そしてJavaで私は使用します:

パブリッククラスCryptoUtil{

public static final Logger LOG = Logger.getLogger(CryptoUtil.class);

private Cipher cipher = null;

private SecretKey key = null;

// This variable holds a string based on which a unique key will be generated
private static final String SECRET_PHRASE = "SECRET PHRASE GOES HERE";

// Charset will be used to convert between String and ByteArray
private static final String CHARSET = "UTF8";

 // The algorithm to be used for encryption/decryption DES(Data Encryption Standard)
private static final String ALGORITHM = "DES";

public CryptoUtil() throws DDICryptoException {
    try {
        // generate a key from SecretKeyFactory
        DESKeySpec keySpec = new DESKeySpec(SECRET_PHRASE.getBytes(CHARSET));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        key = keyFactory.generateSecret(keySpec);
        cipher = Cipher.getInstance(ALGORITHM);
    } catch (Exception e) {
        LOG.error(e);
        throw new DDICryptoException(e);
    }
}


/**
 * This method takes a plain text string and returns encrypted string using DES algorithm
 * @param plainText
 * @return String
 * @throws DDICryptoException
 */
public String encrypt(String plainText) throws DDICryptoException {
    String encryptedString = null;
    try {
        // initializes the cipher with a key.
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] plainTextAsUTF8 = plainText.getBytes(CHARSET);

        // decrypts data in a single-part or multi-part operation
        byte[] encryptedBytes = cipher.doFinal(plainTextAsUTF8);

        encryptedString = new sun.misc.BASE64Encoder().encode(encryptedBytes);
    } catch (Exception e) {
        LOG.error(e);
        throw new DDICryptoException(e);

    }
    return encryptedString;

}

/**
 * This method takes a plain text string and returns encrypted string using DES algorithm
 * @param encryptedString
 * @return
 * @throws DDICryptoException
 */
public String decrypt(String encryptedString) throws DDICryptoException {    
    String decryptedString = null;
    try {
        byte[] decodedString = new sun.misc.BASE64Decoder().decodeBuffer(encryptedString);

        // initializes the cipher with a key.
        cipher.init(Cipher.DECRYPT_MODE, key);

        // decrypts data in a single-part or multi-part operation
        byte[] decryptedBytes = cipher.doFinal(decodedString);
        decryptedString = new String(decryptedBytes, CHARSET);
    } catch (Exception e) {
        LOG.error(e);
        throw new DDICryptoException(e);
    }
    return decryptedString;
}

}

于 2011-01-04T22:54:05.753 に答える
0

Java での CryptoStream .NET と同等の 回答 #5 を参照してください。

一番下のコメントを必ず読んでください...

KeySpec ks = new DESKeySpec("key12345".getBytes("UTF-8")); SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(ks);
IvParameterSpec iv = new IvParameterSpec( Hex.decodeHex("1234567890ABCDEF".toCharArray()));
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decoded = cipher.doFinal(Base64.decodeBase64("B3xogi/Qfsc="));
System.out.println("Decoded: " + new String(decoded, "UTF-8"));

これが役に立てば幸いです...
JK

于 2011-01-14T20:06:59.573 に答える
0
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;

        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) {
                strbuf.append("0");
            }

            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }

結果のバイト配列を文字列に変換する前にエンコードする必要があります。上記のコードは私にとってはうまくいきましたが、実際の暗号化機能は以下のとおりです。

public String encrypt(String data) throws Exception{
    try {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        Key k = new SecretKeySpec(key.getBytes(), 0, key.length(), "AES");

        // Calculate ciphertext size.
        int blocksize = 16;
        int ciphertextLength = 0;
        int remainder = data.getBytes().length % blocksize;
        if (remainder == 0) {
            ciphertextLength = data.getBytes().length + blocksize;
        } else {
            ciphertextLength = data.getBytes().length - remainder + blocksize;
        }


        cipher.init(Cipher.ENCRYPT_MODE, k);
        byte[] buf = new byte[ciphertextLength];
        cipher.doFinal(data.getBytes(), 0, data.length(), buf, 0);

        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;

        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) {
                strbuf.append("0");
            }

            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }
        return strbuf.toString();
    } catch (Exception e) {
        Logger.logException(e);
    }
    return null;
}
于 2011-01-11T08:37:14.883 に答える
0

私は何とか問題を解決することができました。復号化は正常に機能するようになりました。次のコードを使用する

    String plainPassword = "";
            try
            {
                SecretKeySpec key = new SecretKeySpec("hcxilkqbbhczfeultgbskdmaunivmfuo".getBytes("US-ASCII"), "AES");

                IvParameterSpec iv = new IvParameterSpec("ryojvlzmdalyglrj".getBytes("US_ASCII"));

                Cipher cipher = Cipher.getInsta

nce("AES/CBC/PKCS7Padding");

            cipher.init(Cipher.DECRYPT_MODE, key, iv);

            byte[] encoded = cipher.doFinal(Base64.decodeBase64(encryptedPassword.getBytes()));
            plainPassword = new String(encoded);
        }
        catch (Exception ex)
        {
            Log.d("Decryption Error", ex.toString());
        }

        return plainPassword;

問題は暗号化にあります。暗号を復号化モードから暗号化モードに変更した以外は同じコードを使用しましたが、何らかの理由で、暗号化された文字列を出力すると、C# が作成する文字列とはまったく異なる大量のごみが出力されます。以下は暗号化のコードです

public String encrypt(String plainPasword)
    {
        String password = "";
        try
        {
            SecretKeySpec key = new SecretKeySpec("hcxilkqbbhczfeultgbskdmaunivmfuo".getBytes("US-ASCII"), "AES");

            IvParameterSpec iv = new IvParameterSpec("ryojvlzmdalyglrj".getBytes("US_ASCII"));

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

            cipher.init(Cipher.ENCRYPT_MODE, key, iv);

            byte[] encoded = cipher.doFinal(plainPasword.getBytes());
            password = new String(encoded);


        }
        catch (Exception ex)
        {
            Log.d("Encryption Error", ex.toString());
        }
        return password;
    }

これのどこが間違っているように思えますか?ありがとう

于 2011-01-08T18:12:07.923 に答える
-1

セメロン、きちんとしたコードがあります!

お客様がIVにキーと同じものを与えたという興味深い状況に遭遇しました。

パディング例外が発生するさまざまな組み合わせを試した後、うまくいった解決策は

byte[] iv=new byte[8]; // assuming RC2
System.arraycopy(key.getBytes(), 0, iv, 0, key.getBytes().length > iv.length ? key.getBytes().length);

// Now decrypt and hopefully this should work
于 2013-12-13T05:05:44.710 に答える