java 一次一密,加解密
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13187652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
One time pad, encryption and decryption
提问by user1792962
I am trying to pick up cryptography and had been trying this exercise
我正在尝试学习密码学并且一直在尝试这个练习
Write a program (preferably Java) to generate a one-time pad, which is a relatively large file of all random data (say 1 MB). The program should also be able to encrypt/decrypt files based on the generated one time pad.
编写一个程序(最好是 Java)来生成一次性填充,这是一个包含所有随机数据的相对较大的文件(比如 1 MB)。该程序还应该能够根据生成的一次性密码对文件进行加密/解密。
Tip: use the following test vector to check if your program does encryption correctly.
提示:使用以下测试向量来检查您的程序是否正确加密。
Plaintext (ASCII): Every cloud has a silver lining
OTP (HEX): 6dc72fc595e35dcd38c05dca2a0d2dbd8e2df20b129b2cfa29ad17972922a2
ciphertext (HEX): 28b14ab7ecc33ea157b539ea426c5e9def0d81627eed498809c17ef9404cc5
明文 (ASCII):每朵云都有一线希望
OTP (HEX):6dc72fc595e35dcd38c05dca2a0d2dbd8e2df20b129b2cfa29ad17972922a2
密文 (HEX):28b14ab7ecc60340e7404040eac8408c840408c8408c8408c85e788c8408c840404040eac8404040e78c8e6e8c05dca2a0d2dbd8e2df20b129b2cfa29ad17972922
I have tried to generate a one time pad using random number generator as I need to convert them to HEX form. and I am pretty sure I am confused or not tackling it the right way
我尝试使用随机数生成器生成一次性垫,因为我需要将它们转换为十六进制形式。我很确定我很困惑或没有以正确的方式解决它
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())));
}
}
Above would be my one time pad, and I was wondering how any idea how I could implement the encryption using the one time pad and decrypting it.
上面是我的一次性密码本,我想知道如何使用一次性密码键盘实现加密并对其进行解密。
回答by Maciej A. Bednarz
Here you have a full working example:
这里有一个完整的工作示例:
// 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));
回答by Maarten Bodewes
For the one time pad you need a byte array, not hexadecimals. The hexadecimals are only required for displaying data (we tend to have trouble reading bits). You can use the Apache Commons libraries (codec package) to create hexadecimals from byte arrays, or back if you want to decode the test vectors from hexadecimals to bytes.
对于一次性填充,您需要一个字节数组,而不是十六进制。十六进制仅用于显示数据(我们往往在读取位时遇到问题)。您可以使用 Apache Commons 库(编解码器包)从字节数组创建十六进制,或者如果要将测试向量从十六进制解码为字节,则返回。
You should use a securerandom number generator, not Random
. So use new SecureRandom()
instead. To generate random data, first create a byte array, then call nextBytes()
on the random number generator. There is not need to generate integers.
您应该使用安全的随机数生成器,而不是Random
. 所以new SecureRandom()
改用。要生成随机数据,首先创建一个字节数组,然后调用nextBytes()
随机数生成器。不需要生成整数。
回答by chubbsondubs
First here is a OTP algorithm specified called HOTP which is a standard RFC. Almost all other OTP are propriety and we don't know the algorithm for those.
首先是指定的 OTP 算法,称为 HOTP,它是标准 RFC。几乎所有其他 OTP 都是专有的,我们不知道它们的算法。
http://tools.ietf.org/html/rfc4226
http://tools.ietf.org/html/rfc4226
There is some java code in there you can use to learn how its done. Second if you are going to do encryption don't use Random. Random is nice for psuedo random, but if you really want a good source of random data you need to adopt SecureRandom. That's a much better source of random numbers that are suitable for cryto algorithms.
那里有一些 Java 代码,您可以使用它来了解它是如何完成的。其次,如果您要进行加密,请不要使用随机。Random 很适合伪随机,但如果你真的想要一个好的随机数据源,你需要采用 SecureRandom。这是适用于加密算法的更好的随机数来源。
For converting things to Hex you can easily use
要将事物转换为十六进制,您可以轻松使用
http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toString(int)
http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toString(int)
Or any of the varieties Long.toString(value,radix), Integer.toString(value,radix), or Byte.toString(value,radix).
或 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 );
}
回答by Hur Abbas
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();
}
}
}
回答by ceph3us
https://en.wikipedia.org/wiki/One-time_pad
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");
test("test","1234");
test("test","123");
ps. you can refactor method by pull strings up and replace with bytes
附:您可以通过拉起字符串并用字节替换来重构方法
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;
}
回答by Eddie Jamsession
<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