Przepisuje z języka C# na Javę HOTP
Kod C#
internal sealed class Base32
{
private const int InByteSize = 8;
private const int OutByteSize = 5;
private const string Base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
internal static string ToBase32String(byte[] bytes)
{
if (bytes == null)
{
return null;
}
else if (bytes.Length == 0)
{
return string.Empty;
}
StringBuilder builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize);
int bytesPosition = 0;
int bytesSubPosition = 0;
byte outputBase32Byte = 0;
int outputBase32BytePosition = 0;
while (bytesPosition < bytes.Length)
{
int bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition);
outputBase32Byte <<= bitsAvailableInByte;
outputBase32Byte |= (byte)(bytes[bytesPosition] >> (InByteSize - (bytesSubPosition + bitsAvailableInByte)));
bytesSubPosition += bitsAvailableInByte;
if (bytesSubPosition >= InByteSize)
{
bytesPosition++;
bytesSubPosition = 0;
}
outputBase32BytePosition += bitsAvailableInByte;
if (outputBase32BytePosition >= OutByteSize)
{
outputBase32Byte &= 0x1F;
builder.Append(Base32Alphabet[outputBase32Byte]);
outputBase32BytePosition = 0;
}
}
if (outputBase32BytePosition > 0)
{
outputBase32Byte <<= (OutByteSize - outputBase32BytePosition);
outputBase32Byte &= 0x1F;
builder.Append(Base32Alphabet[outputBase32Byte]);
}
return builder.ToString();
}
internal static byte[] FromBase32String(string base32String)
{
if (base32String == null)
{
return null;
}
else if (base32String == string.Empty)
{
return new byte[0];
}
string base32StringUpperCase = base32String.ToUpperInvariant();
byte[] outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize];
if (outputBytes.Length == 0)
{
throw new ArgumentException("Specified string is not valid Base32 format because it doesn't have enough data to construct a complete byte array");
}
int base32Position = 0;
int base32SubPosition = 0;
int outputBytePosition = 0;
int outputByteSubPosition = 0;
while (outputBytePosition < outputBytes.Length)
{
int currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]);
if (currentBase32Byte < 0)
{
throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position]));
}
int bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition);
outputBytes[outputBytePosition] <<= bitsAvailableInByte;
outputBytes[outputBytePosition] |= (byte)(currentBase32Byte >> (OutByteSize - (base32SubPosition + bitsAvailableInByte)));
outputByteSubPosition += bitsAvailableInByte;
if (outputByteSubPosition >= InByteSize)
{
outputBytePosition++;
outputByteSubPosition = 0;
}
base32SubPosition += bitsAvailableInByte;
if (base32SubPosition >= OutByteSize)
{
base32Position++;
base32SubPosition = 0;
}
}
return outputBytes;
}
}
public static string HOTP2(string key, ulong counter, int digits = 6)
{
byte[] hmac_result = new byte[] { };
byte[] counter_bytes = BitConverter.IsLittleEndian ? BitConverter.GetBytes(counter).Reverse().ToArray() : BitConverter.GetBytes(counter);
HMACSHA512 hamac = new HMACSHA512(Base32.FromBase32String(key));
hmac_result = hamac.ComputeHash(counter_bytes);
// compute SHA-1 HMAC of the key
//System.Security.Cryptography.HMACSHA1 hmac =
//new System.Security.Cryptography.HMACSHA1(Base32.FromBase32String(key), true);
// convert the counter to bytes, check if the system is little endian and reverse if necessary
// compute the hash using the counter value
//byte[] hmac_result = hmac.ComputeHash(counter_bytes);
// get the last 4 bits of the HMAC Result to determine the offset
int tab_index = hmac_result.Length - 1;
int offset = hmac_result[tab_index] & 0xf;
// get the value of 4 bytes of the HMAC Result starting at the offset position
int bin_code = (hmac_result[offset] & 0x7f) << 24
| (hmac_result[offset + 1] & 0xff) << 16
| (hmac_result[offset + 2] & 0xff) << 8
| (hmac_result[offset + 3] & 0xff);
// HOTP = bin_code modulo 10^(digits)
int hotp = bin_code % (int)Math.Pow(10, digits);
// truncate the string to the number of significant digits
return hotp.ToString(String.Empty.PadRight(digits, '0'));
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
label1.Text= HOTP2("S4P6W7M522SC3OXX55K3NN77666N34M2", hotp_counter, 6);
}
private void label1_Click(object sender, EventArgs e)
{
label1.Text = HOTP2("S4P6W7M522SC3OXX55K3NN77666N34M2", hotp_counter, 6);
hotp_counter++;
}
}
wartości są poprawne natomiast mam problemy z Java
public class Hotp {
public static byte[] hmac_sha1(byte[] keyBytes, byte[] text)
throws NoSuchAlgorithmException, InvalidKeyException {
// try {
Mac hmacSha1;
try {
hmacSha1 = Mac.getInstance("HmacSHA512");
} catch (NoSuchAlgorithmException nsae) {
hmacSha1 = Mac.getInstance("HmacSHA512");
}
SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
hmacSha1.init(macKey);
return hmacSha1.doFinal(text);
}
static String generateOTP(byte[] secret, long movingFactor,
int codeDigits) throws NoSuchAlgorithmException,
InvalidKeyException {
// put movingFactor value into text byte array
String result = null;
byte[] text = new byte[6];
for (int i = text.length - 1; i >= 0; i--) {
text[i] = (byte) (movingFactor & 0xff);
movingFactor >>= 6;
}
// compute hmac hash
byte[] hash = hmac_sha1(secret, text);
int tab_index = hash.length - 1;
// put selected bytes into result int
int offset = hash[tab_index] & 0xf;
int binary = ((offset & 0x7f) << 24)
| ((hash[offset + 1] & 0xff) << 16)
| ((hash[offset + 2] & 0xff) << 8)
| (hash[offset + 3] & 0xff);
int otp = (int) (binary % Math.pow(10, codeDigits));
result = Integer.toString(otp);
while (result.length() < codeDigits) {
result = "0" + result;
}
return result;
}
}
pokazują są blednę wartości nie wiem próbuje to debugować ale nie wiem dlaczego to jest żle