一次性填充,加密和解密

时间:2012-11-02 00:38:16

标签: java encryption cryptography one-time-pad

我正在尝试接受密码学并且一直在尝试这个练习

编写程序(最好是Java)来生成一次性填充,这是一个相对较大的文件 随机数据(比如1 MB)。该程序还应该能够根据文件加密/解密文件 生成一次性垫。

提示:使用以下测试向量检查您的程序是否正确加密。

明文(ASCII):每一朵云都有一线希望             OTP(HEX):6dc72fc595e35dcd38c05dca2a0d2dbd8e2df20b129b2cfa29ad17972922a2
    密文(HEX):28b14ab7ecc33ea157b539ea426c5e9def0d81627eed498809c17ef9404cc5

我尝试使用随机数生成器生成一次性打击垫,因为我需要将它们转换为HEX格式。而且我很确定我很困惑或者没有以正确的方式解决它

public static void oneTimePad()
{
    Random ran = new Random();
    String s = "0123456789ABCDEF";
    for(int i = 0; i < 100; i++)
    {   
        System.out.print(s.charAt(ran.nextInt(s.length())));
    }
}

以上将是我的一次性填充,我想知道如何使用一次性密码并解密它来实现加密。

6 个答案:

答案 0 :(得分:8)

这里有一个完整的工作示例:

    // convert secret text to byte array
    final byte[] secret = "secret".getBytes()

    final byte[] encoded = new byte[secret.length];
    final byte[] decoded = new byte[secret.length];

    // Generate random key (has to be exchanged)
    final byte[] key = new byte[secret.length];
    new SecureRandom().nextBytes(key);

    // Encrypt
    for (int i = 0; i < secret.length; i++) {
        encoded[i] = (byte) (secret[i] ^ key[i]);
    }

    // Decrypt
    for (int i = 0; i < encoded.length; i++) {
        decoded[i] = (byte) (encoded[i] ^ key[i]);
    }

    assertTrue(Arrays.equals(secret, decoded));

答案 1 :(得分:3)

对于一次性填充,您需要一个字节数组,而不是十六进制数组。十六进制仅用于显示数据(我们往往难以读取位)。您可以使用Apache Commons库(编解码器包)从字节数组创建十六进制,如果要将测试向量从十六进制解码为字节,则可以返回。

您应该使用安全随机数生成器,而不是Random。所以请改用new SecureRandom()。要生成随机数据,首先要创建一个字节数组,然后在随机数生成器上调用nextBytes()。不需要生成整数。

答案 2 :(得分:2)

这里首先是一个名为HOTP的OTP算法,它是一个标准的RFC。几乎所有其他OTP都是适当的,我们不知道那些算法。

http://tools.ietf.org/html/rfc4226

你可以用一些java代码来学习它是如何完成的。其次,如果要进行加密,请不要使用Random。随机对于psuedo随机很好,但如果你真的想要一个好的随机数据源,你需要采用SecureRandom。这是一个更好的随机数源,适用于cryto算法。

将东西转换为Hex可以轻松使用

http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toString(int

或任何变种Long.toString(value,radix),Integer.toString(value,radix)或Byte.toString(value,radix)。

byte[] bytes = ...;
for( int i = 0; i < bytes.length; i++ ) {
    System.out.println( Integer.toString( bytes[i], 16 );
}

答案 3 :(得分:0)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace one_time_pad
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("                   TRYING\n");

            Console.WriteLine("Enter : ");
            int input= int.Parse( Console.ReadLine());

            //random num generation
            Random rnd = new Random();
            int random = rnd.Next(1,10);

            //binary conversion
            string binary = Convert.ToString(random,2);
            string inbinary = Convert.ToString(input,2);

            Console.WriteLine("Data :   " +input +"   Binary :   " + inbinary);
            Console.WriteLine(" Key :   " +random + "   Binary :    " + binary);    

            // taking xor
            int Ghul = input ^ random;

            //binary conversion
            string intcon = Convert.ToString(Ghul,2);

            Console.WriteLine("Encrypted : " + intcon);

            Console.WriteLine(":)");

            Console.Read();    
        }
    }
}

答案 4 :(得分:0)

https://en.wikipedia.org/wiki/One-time_pad

public static String crypt(String string, String keyString) {
    // convert secret text to byte array
    byte[] bytes = string != null ? string.getBytes() : new byte[0];
    int size = bytes != null ? bytes.length : 0;
    final byte[] encoded = new byte[size];
    final byte[] key = keyString != null ? keyString.getBytes() : new byte[0];
    // loop on input  bytes
    for (int i = 0; i < size; i++) {
        // shift key index 
        // (we assume key can be smaller or equal if larger then adjust)
        int keyi = i >= keySize ? size % (keySize-1) : i;
        // pad
        encoded[i] = (byte) (bytes[i] ^ key[keyi]);
    }
    return new String(encoded);
}

public static void test(String string, String keyString) {
    String encrypt = crypt(string, keyString);
    String decrypt = crypt(encrypt, keyString);
    assert(string.equals(decrypt));
}
  • test("test","1234");
  • test("test","123");

PS。你可以通过拉取字符串来重构方法并用字节替换

public static byte[] crypt(byte[] bytes, byte[] key) {
    int size = bytes != null ? bytes.length : 0;
    final byte[] encoded = new byte[size];
    int keySize = key != null ? key.length : 0;
    // loop on input bytes 
    for (int i = 0; i < size; i++) {
        // shift key index (assuming key <= bytes)
        int keyi = i >= keySize ? size % (keySize-1) : i;
        // pad 
        encoded[i] = (byte) (bytes[i] ^ key[keyi]);
    }
    return encoded;
}

答案 5 :(得分:0)

<dependency>
    <groupId>work.eddiejamsession</groupId>
    <artifactId>jam-one-time-pad</artifactId>
    <version>0.67</version>
</dependency>
JamOneTimePad pad = new JamOneTimePad();
String heyEncrypted = pad.encrypt("hey"); //encodes additionally in base64 for url safety
String heyDecrypted = pad.decrypt(heyEncrypted);
System.out.println(heyDecrypted.equals("hey"));
Output: true