mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-01-31 15:22:16 +00:00
MnemonicCode: Clean up a bit.
This commit is contained in:
parent
29e2af7ec0
commit
43460f451a
@ -17,6 +17,7 @@
|
|||||||
package com.google.bitcoin.crypto;
|
package com.google.bitcoin.crypto;
|
||||||
|
|
||||||
import com.google.bitcoin.core.Sha256Hash;
|
import com.google.bitcoin.core.Sha256Hash;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -25,9 +26,7 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -92,11 +91,10 @@ public class MnemonicCode {
|
|||||||
// used as a pseudo-random function. Desired length of the
|
// used as a pseudo-random function. Desired length of the
|
||||||
// derived key is 512 bits (= 64 bytes).
|
// derived key is 512 bits (= 64 bytes).
|
||||||
//
|
//
|
||||||
String pass = joinStringList(words);
|
String pass = Joiner.on(' ').join(words);
|
||||||
String salt = new String("mnemonic" + passphrase);
|
String salt = "mnemonic" + passphrase;
|
||||||
|
|
||||||
byte[] hash = PBKDF2SHA512.derive(pass, salt, PBKDF2_ROUNDS, 64);
|
return PBKDF2SHA512.derive(pass, salt, PBKDF2_ROUNDS, 64);
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,7 +114,7 @@ public class MnemonicCode {
|
|||||||
// Find the words index in the wordlist.
|
// Find the words index in the wordlist.
|
||||||
int ndx = Collections.binarySearch(this.wordList, word);
|
int ndx = Collections.binarySearch(this.wordList, word);
|
||||||
if (ndx < 0)
|
if (ndx < 0)
|
||||||
throw new MnemonicException.MnemonicWordException("\"" + word + "\" invalid", word);
|
throw new MnemonicException.MnemonicWordException(word);
|
||||||
|
|
||||||
// Set the next 11 bits to the value of the index.
|
// Set the next 11 bits to the value of the index.
|
||||||
for (int ii = 0; ii < 11; ++ii)
|
for (int ii = 0; ii < 11; ++ii)
|
||||||
@ -139,9 +137,9 @@ public class MnemonicCode {
|
|||||||
boolean[] hashBits = bytesToBits(hash);
|
boolean[] hashBits = bytesToBits(hash);
|
||||||
|
|
||||||
// Check all the checksum bits.
|
// Check all the checksum bits.
|
||||||
for (int ii = 0; ii < checksumLengthBits; ++ii)
|
for (int i = 0; i < checksumLengthBits; ++i)
|
||||||
if (concatBits[entropyLengthBits + ii] != hashBits[ii])
|
if (concatBits[entropyLengthBits + i] != hashBits[i])
|
||||||
throw new MnemonicException.MnemonicChecksumException("checksum error");
|
throw new MnemonicException.MnemonicChecksumException();
|
||||||
|
|
||||||
return entropy;
|
return entropy;
|
||||||
}
|
}
|
||||||
@ -164,10 +162,8 @@ public class MnemonicCode {
|
|||||||
|
|
||||||
// We append these bits to the end of the initial entropy.
|
// We append these bits to the end of the initial entropy.
|
||||||
boolean[] concatBits = new boolean[entropyBits.length + checksumLengthBits];
|
boolean[] concatBits = new boolean[entropyBits.length + checksumLengthBits];
|
||||||
for (int ii = 0; ii < entropyBits.length; ++ii)
|
System.arraycopy(entropyBits, 0, concatBits, 0, entropyBits.length);
|
||||||
concatBits[ii] = entropyBits[ii];
|
System.arraycopy(hashBits, 0, concatBits, entropyBits.length, checksumLengthBits);
|
||||||
for (int ii = 0; ii < checksumLengthBits; ++ii)
|
|
||||||
concatBits[entropyBits.length + ii] = hashBits[ii];
|
|
||||||
|
|
||||||
// Next we take these concatenated bits and split them into
|
// Next we take these concatenated bits and split them into
|
||||||
// groups of 11 bits. Each group encodes number from 0-2047
|
// groups of 11 bits. Each group encodes number from 0-2047
|
||||||
@ -176,14 +172,14 @@ public class MnemonicCode {
|
|||||||
|
|
||||||
ArrayList<String> words = new ArrayList<String>();
|
ArrayList<String> words = new ArrayList<String>();
|
||||||
int nwords = concatBits.length / 11;
|
int nwords = concatBits.length / 11;
|
||||||
for (int ii = 0; ii < nwords; ++ii) {
|
for (int i = 0; i < nwords; ++i) {
|
||||||
int ndx = 0;
|
int index = 0;
|
||||||
for (int jj = 0; jj < 11; ++jj) {
|
for (int j = 0; j < 11; ++j) {
|
||||||
ndx <<= 1;
|
index <<= 1;
|
||||||
if (concatBits[(ii * 11) + jj])
|
if (concatBits[(i * 11) + j])
|
||||||
ndx |= 0x1;
|
index |= 0x1;
|
||||||
}
|
}
|
||||||
words.add(this.wordList.get(ndx));
|
words.add(this.wordList.get(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
return words;
|
return words;
|
||||||
@ -192,29 +188,15 @@ public class MnemonicCode {
|
|||||||
/**
|
/**
|
||||||
* Check to see if a mnemonic word list is valid.
|
* Check to see if a mnemonic word list is valid.
|
||||||
*/
|
*/
|
||||||
public void check(List<String> words) throws MnemonicException.MnemonicLengthException, MnemonicException.MnemonicWordException, MnemonicException.MnemonicChecksumException {
|
public void check(List<String> words) throws MnemonicException {
|
||||||
toEntropy(words);
|
toEntropy(words);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean[] bytesToBits(byte[] data) {
|
private static boolean[] bytesToBits(byte[] data) {
|
||||||
boolean[] bits = new boolean[data.length * 8];
|
boolean[] bits = new boolean[data.length * 8];
|
||||||
for (int ii = 0; ii < data.length; ++ii)
|
for (int i = 0; i < data.length; ++i)
|
||||||
for (int jj = 0; jj < 8; ++jj)
|
for (int j = 0; j < 8; ++j)
|
||||||
bits[(ii * 8) + jj] = (data[ii] & (1 << (7 - jj))) != 0;
|
bits[(i * 8) + j] = (data[i] & (1 << (7 - j))) != 0;
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private String joinStringList(List<String> list) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
boolean first = true;
|
|
||||||
for (String item : list)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
first = false;
|
|
||||||
else
|
|
||||||
sb.append(" ");
|
|
||||||
sb.append(item);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,13 @@ package com.google.bitcoin.crypto;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class MnemonicException extends Exception {
|
public class MnemonicException extends Exception {
|
||||||
|
public MnemonicException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
public MnemonicException(String msg) {
|
public MnemonicException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
public MnemonicException(Exception ex) {
|
|
||||||
super(ex);
|
|
||||||
}
|
|
||||||
public MnemonicException(String msg, Exception ex) {
|
|
||||||
super(msg, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when an argument to MnemonicCode is the wrong length.
|
* Thrown when an argument to MnemonicCode is the wrong length.
|
||||||
@ -38,26 +36,14 @@ public class MnemonicException extends Exception {
|
|||||||
public MnemonicLengthException(String msg) {
|
public MnemonicLengthException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
public MnemonicLengthException(Exception ex) {
|
|
||||||
super(ex);
|
|
||||||
}
|
|
||||||
public MnemonicLengthException(String msg, Exception ex) {
|
|
||||||
super(msg, ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when a list of MnemonicCode words fails the checksum check.
|
* Thrown when a list of MnemonicCode words fails the checksum check.
|
||||||
*/
|
*/
|
||||||
public static class MnemonicChecksumException extends MnemonicException {
|
public static class MnemonicChecksumException extends MnemonicException {
|
||||||
public MnemonicChecksumException(String msg) {
|
public MnemonicChecksumException() {
|
||||||
super(msg);
|
super();
|
||||||
}
|
|
||||||
public MnemonicChecksumException(Exception ex) {
|
|
||||||
super(ex);
|
|
||||||
}
|
|
||||||
public MnemonicChecksumException(String msg, Exception ex) {
|
|
||||||
super(msg, ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,22 +52,11 @@ public class MnemonicException extends Exception {
|
|||||||
*/
|
*/
|
||||||
public static class MnemonicWordException extends MnemonicException {
|
public static class MnemonicWordException extends MnemonicException {
|
||||||
/** Contains the word that was not found in the word list. */
|
/** Contains the word that was not found in the word list. */
|
||||||
public String badWord;
|
public final String badWord;
|
||||||
|
|
||||||
public MnemonicWordException(String msg, String badWord) {
|
public MnemonicWordException(String badWord) {
|
||||||
super(msg);
|
super();
|
||||||
this.badWord = badWord;
|
this.badWord = badWord;
|
||||||
}
|
}
|
||||||
public MnemonicWordException(String badWord, Exception ex) {
|
|
||||||
super(ex);
|
|
||||||
this.badWord = badWord;
|
|
||||||
}
|
|
||||||
public MnemonicWordException(String msg, String badWord, Exception ex) {
|
|
||||||
super(msg, ex);
|
|
||||||
this.badWord = badWord;
|
|
||||||
}
|
|
||||||
public String getBadWord() {
|
|
||||||
return badWord;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,214 +19,94 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* This is a clean-room implementation of PBKDF2 using RFC 2898 as a reference.
|
|
||||||
*
|
|
||||||
* RFC 2898:
|
|
||||||
* http://tools.ietf.org/html/rfc2898#section-5.2
|
|
||||||
*
|
|
||||||
* This code passes all RFC 6070 test vectors:
|
|
||||||
* http://tools.ietf.org/html/rfc6070
|
|
||||||
*
|
|
||||||
* The function "nativeDerive()" is supplied as an example of the native Java
|
|
||||||
* PBKDF2WithHmacSHA1 implementation. It is used for benchmarking and
|
|
||||||
* comparison only.
|
|
||||||
*
|
|
||||||
* The functions "fromHex()" and "toHex()" came from some message board
|
|
||||||
* somewhere. No license was included.
|
|
||||||
*
|
|
||||||
* http://cryptofreek.org/2012/11/29/pbkdf2-pure-java-implementation/
|
|
||||||
* Modified to use SHA-512 - Ken Sedgwick ken@bonsai.com
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.bitcoin.crypto;
|
package com.google.bitcoin.crypto;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.security.spec.KeySpec;
|
|
||||||
import java.util.Formatter;
|
/**
|
||||||
|
* <p>This is a clean-room implementation of PBKDF2 using RFC 2898 as a reference.</p>
|
||||||
import javax.crypto.Mac;
|
*
|
||||||
import javax.crypto.SecretKey;
|
* <p>RFC 2898: http://tools.ietf.org/html/rfc2898#section-5.2</p>
|
||||||
import javax.crypto.SecretKeyFactory;
|
*
|
||||||
import javax.crypto.spec.PBEKeySpec;
|
* <p>This code passes all RFC 6070 test vectors: http://tools.ietf.org/html/rfc6070</p>
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
*
|
||||||
|
* <p>http://cryptofreek.org/2012/11/29/pbkdf2-pure-java-implementation/<br>
|
||||||
public class PBKDF2SHA512
|
* Modified to use SHA-512 - Ken Sedgwick ken@bonsai.com</p>
|
||||||
{
|
*/
|
||||||
/* START RFC 2898 IMPLEMENTATION */
|
public class PBKDF2SHA512 {
|
||||||
public static byte[] derive(String P, String S, int c, int dkLen)
|
public static byte[] derive(String P, String S, int c, int dkLen) {
|
||||||
{
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
|
try {
|
||||||
try
|
int hLen = 20;
|
||||||
{
|
|
||||||
int hLen = 20;
|
if (dkLen > ((Math.pow(2, 32)) - 1) * hLen) {
|
||||||
|
throw new IllegalArgumentException("derived key too long");
|
||||||
if (dkLen > ((Math.pow(2, 32)) - 1) * hLen)
|
} else {
|
||||||
{
|
int l = (int) Math.ceil((double) dkLen / (double) hLen);
|
||||||
System.out.println("derived key too long");
|
// int r = dkLen - (l-1)*hLen;
|
||||||
}
|
|
||||||
else
|
for (int i = 1; i <= l; i++) {
|
||||||
{
|
byte[] T = F(P, S, c, i);
|
||||||
int l = (int) Math.ceil((double) dkLen / (double) hLen);
|
baos.write(T);
|
||||||
// int r = dkLen - (l-1)*hLen;
|
}
|
||||||
|
}
|
||||||
for (int i = 1; i <= l; i++)
|
} catch (Exception e) {
|
||||||
{
|
throw new RuntimeException(e);
|
||||||
byte[] T = F(P, S, c, i);
|
|
||||||
baos.write(T);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
byte[] baDerived = new byte[dkLen];
|
||||||
|
System.arraycopy(baos.toByteArray(), 0, baDerived, 0, baDerived.length);
|
||||||
|
|
||||||
|
return baDerived;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
{
|
private static byte[] F(String P, String S, int c, int i) throws Exception {
|
||||||
e.printStackTrace();
|
byte[] U_LAST = null;
|
||||||
}
|
byte[] U_XOR = null;
|
||||||
|
|
||||||
byte[] baDerived = new byte[dkLen];
|
SecretKeySpec key = new SecretKeySpec(P.getBytes("UTF-8"), "HmacSHA512");
|
||||||
System.arraycopy(baos.toByteArray(), 0, baDerived, 0, baDerived.length);
|
Mac mac = Mac.getInstance(key.getAlgorithm());
|
||||||
|
mac.init(key);
|
||||||
return baDerived;
|
|
||||||
}
|
for (int j = 0; j < c; j++) {
|
||||||
|
if (j == 0) {
|
||||||
private static byte[] F(String P, String S, int c, int i) throws Exception
|
byte[] baS = S.getBytes("UTF-8");
|
||||||
{
|
byte[] baI = INT(i);
|
||||||
byte[] U_LAST = null;
|
byte[] baU = new byte[baS.length + baI.length];
|
||||||
byte[] U_XOR = null;
|
|
||||||
|
System.arraycopy(baS, 0, baU, 0, baS.length);
|
||||||
SecretKeySpec key = new SecretKeySpec(P.getBytes("UTF-8"), "HmacSHA512");
|
System.arraycopy(baI, 0, baU, baS.length, baI.length);
|
||||||
Mac mac = Mac.getInstance(key.getAlgorithm());
|
|
||||||
mac.init(key);
|
U_XOR = mac.doFinal(baU);
|
||||||
|
U_LAST = U_XOR;
|
||||||
for (int j = 0; j < c; j++)
|
mac.reset();
|
||||||
{
|
} else {
|
||||||
if (j == 0)
|
byte[] baU = mac.doFinal(U_LAST);
|
||||||
{
|
mac.reset();
|
||||||
byte[] baS = S.getBytes("UTF-8");
|
|
||||||
byte[] baI = INT(i);
|
for (int k = 0; k < U_XOR.length; k++) {
|
||||||
byte[] baU = new byte[baS.length + baI.length];
|
U_XOR[k] = (byte) (U_XOR[k] ^ baU[k]);
|
||||||
|
}
|
||||||
System.arraycopy(baS, 0, baU, 0, baS.length);
|
|
||||||
System.arraycopy(baI, 0, baU, baS.length, baI.length);
|
U_LAST = baU;
|
||||||
|
}
|
||||||
U_XOR = mac.doFinal(baU);
|
|
||||||
U_LAST = U_XOR;
|
|
||||||
mac.reset();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
byte[] baU = mac.doFinal(U_LAST);
|
|
||||||
mac.reset();
|
|
||||||
|
|
||||||
for (int k = 0; k < U_XOR.length; k++)
|
|
||||||
{
|
|
||||||
U_XOR[k] = (byte) (U_XOR[k] ^ baU[k]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U_LAST = baU;
|
return U_XOR;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return U_XOR;
|
private static byte[] INT(int i) {
|
||||||
}
|
ByteBuffer bb = ByteBuffer.allocate(4);
|
||||||
|
bb.order(ByteOrder.BIG_ENDIAN);
|
||||||
private static byte[] INT(int i)
|
bb.putInt(i);
|
||||||
{
|
|
||||||
ByteBuffer bb = ByteBuffer.allocate(4);
|
return bb.array();
|
||||||
bb.order(ByteOrder.BIG_ENDIAN);
|
|
||||||
bb.putInt(i);
|
|
||||||
|
|
||||||
return bb.array();
|
|
||||||
}
|
|
||||||
/* END RFC 2898 IMPLEMENTATION */
|
|
||||||
|
|
||||||
/* START HELPER FUNCTIONS */
|
|
||||||
private static String toHex(byte[] ba)
|
|
||||||
{
|
|
||||||
String strHex = null;
|
|
||||||
|
|
||||||
if (ba != null)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder(ba.length * 2);
|
|
||||||
Formatter formatter = new Formatter(sb);
|
|
||||||
|
|
||||||
for (byte b : ba)
|
|
||||||
{
|
|
||||||
formatter.format("%02x", b);
|
|
||||||
}
|
|
||||||
|
|
||||||
formatter.close();
|
|
||||||
strHex = sb.toString().toLowerCase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return strHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] nativeDerive(String strPassword, String strSalt, int nIterations, int nKeyLen)
|
|
||||||
{
|
|
||||||
byte[] baDerived = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
|
||||||
KeySpec ks = new PBEKeySpec(strPassword.toCharArray(), strSalt.getBytes("UTF-8"), nIterations, nKeyLen * 8);
|
|
||||||
SecretKey s = f.generateSecret(ks);
|
|
||||||
baDerived = s.getEncoded();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return baDerived;
|
|
||||||
}
|
|
||||||
/* END HELPER FUNCTIONS */
|
|
||||||
|
|
||||||
public static void runTestVector(String P, String S, int c, int dkLen, String strExpectedDk)
|
|
||||||
{
|
|
||||||
System.out.println("Input:");
|
|
||||||
System.out.println(" P = \"" + P + "\"");
|
|
||||||
System.out.println(" S = \"" + S + "\"");
|
|
||||||
System.out.println(" c = " + c);
|
|
||||||
System.out.println(" dkLen = " + dkLen);
|
|
||||||
System.out.println();
|
|
||||||
|
|
||||||
long nStartDk = System.nanoTime();
|
|
||||||
byte[] DK = derive(P, S, c, dkLen);
|
|
||||||
long nStopDk = System.nanoTime();
|
|
||||||
|
|
||||||
long nStartDkNative = System.nanoTime();
|
|
||||||
byte[] DK_NATIVE = nativeDerive(P, S, c, dkLen);
|
|
||||||
long nStopDkNative = System.nanoTime();
|
|
||||||
|
|
||||||
System.out.println("Output:");
|
|
||||||
System.out.println(" DK = " + toHex(DK));
|
|
||||||
System.out.println(" DK_NATIVE = " + toHex(DK_NATIVE));
|
|
||||||
System.out.println(" DK_EXPECTED = " + strExpectedDk.replaceAll(" ", ""));
|
|
||||||
System.out.println();
|
|
||||||
|
|
||||||
System.out.println("Duration [my implementation]: " + (nStopDk - nStartDk) + " ns" );
|
|
||||||
System.out.println("Duration [native implementation]: " + (nStopDkNative - nStartDkNative) + " ns" );
|
|
||||||
|
|
||||||
System.out.println("---------------------------------------------------------------");
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RFC6070()
|
|
||||||
{
|
|
||||||
runTestVector("password", "salt", 1, 20, "0c 60 c8 0f 96 1f 0e 71 f3 a9 b5 24 af 60 12 06 2f e0 37 a6");
|
|
||||||
runTestVector("password", "salt", 2, 20, "ea 6c 01 4d c7 2d 6f 8c cd 1e d9 2a ce 1d 41 f0 d8 de 89 57");
|
|
||||||
runTestVector("password", "salt", 4096, 20, "4b 00 79 01 b7 65 48 9a be ad 49 d9 26 f7 21 d0 65 a4 29 c1");
|
|
||||||
runTestVector("password", "salt", 16777216, 20, "ee fe 3d 61 cd 4d a4 e4 e9 94 5b 3d 6b a2 15 8c 26 34 e9 84");
|
|
||||||
runTestVector("passwordPASSWORDpassword", "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, "3d 2e ec 4f e4 1c 84 9b 80 c8 d8 36 62 c0 e4 4a 8b 29 1a 96 4c f2 f0 70 38");
|
|
||||||
runTestVector("pass\0word", "sa\0lt", 4096, 16, "56 fa 6a a7 55 48 09 9d cc 37 d7 f0 34 25 e0 c3");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
RFC6070();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user