All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bitcoinj.crypto.PBKDF2SHA512 Maven / Gradle / Ivy

There is a newer version: 21.1.2
Show newest version
/*
 * Copyright (c) 2012 Cole Barnes [cryptofreek{at}gmail{dot}com]
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * 
 */

package org.bitcoinj.crypto;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;

/**
 * 

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

* *

http://cryptofreek.org/2012/11/29/pbkdf2-pure-java-implementation/
* Modified to use SHA-512 - Ken Sedgwick [email protected]

*/ public class PBKDF2SHA512 { public static byte[] derive(String P, String S, int c, int dkLen) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { int hLen = 20; if (dkLen > ((Math.pow(2, 32)) - 1) * hLen) { throw new IllegalArgumentException("derived key too long"); } else { int l = (int) Math.ceil((double) dkLen / (double) hLen); // int r = dkLen - (l-1)*hLen; for (int i = 1; i <= l; i++) { byte[] T = F(P, S, c, i); baos.write(T); } } } catch (Exception e) { throw new RuntimeException(e); } byte[] baDerived = new byte[dkLen]; System.arraycopy(baos.toByteArray(), 0, baDerived, 0, baDerived.length); return baDerived; } private static byte[] F(String P, String S, int c, int i) throws Exception { byte[] U_LAST = null; byte[] U_XOR = null; SecretKeySpec key = new SecretKeySpec(P.getBytes(StandardCharsets.UTF_8), "HmacSHA512"); Mac mac = Mac.getInstance(key.getAlgorithm()); mac.init(key); for (int j = 0; j < c; j++) { if (j == 0) { byte[] baS = S.getBytes(StandardCharsets.UTF_8); byte[] baI = INT(i); byte[] baU = new byte[baS.length + baI.length]; System.arraycopy(baS, 0, baU, 0, baS.length); System.arraycopy(baI, 0, baU, baS.length, baI.length); 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; } private static byte[] INT(int i) { ByteBuffer bb = ByteBuffer.allocate(4); bb.order(ByteOrder.BIG_ENDIAN); bb.putInt(i); return bb.array(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy