8

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

编写一个程序(最好是 Java)来生成一次性便笺簿,这是一个包含所有随机数据的相对较大的文件(例如 1 MB)。该程序还应该能够根据生成的一次性密码对文件进行加密/解密。

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

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

我尝试使用随机数生成器生成一次性填充,因为我需要将它们转换为 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())));
    }
}

以上是我的一次性密码本,我想知道如何使用一次性密码本实现加密并对其进行解密。

4

6 回答 6

10

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

    // 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));
于 2013-05-24T09:31:41.010 回答
3

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

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

于 2012-11-02T01:01:00.067 回答
2

首先是指定的 OTP 算法,称为 HOTP,它是标准 RFC。几乎所有其他 OTP 都是适当的,我们不知道它们的算法。

https://www.rfc-editor.org/rfc/rfc4226

那里有一些 java 代码,您可以使用它来了解它是如何完成的。其次,如果您要进行加密,请不要使用随机。Random 非常适合伪随机,但如果你真的想要一个好的随机数据来源,你需要采用 SecureRandom。这是适用于加密算法的更好的随机数来源。

要将事物转换为十六进制,您可以轻松使用

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 );
}
于 2012-11-02T01:03:43.140 回答
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();    
        }
    }
}
于 2017-10-26T18:09:04.970 回答
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
于 2020-04-03T14:39:07.490 回答
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");

附言。您可以通过拉起字符串并用字节替换来重构方法

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;
}
于 2017-11-30T10:29:12.260 回答