Skip to content

Commit

Permalink
Expose HMAC-SHA-256 interface on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
vitoreiji committed Jan 9, 2025
1 parent 63a06b7 commit 8d0447d
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,17 @@ class CompatibilityTest {
}
}

@Test
fun hmac_sha256() = runBlocking {
for(td in testData.hmacSha256Tests) {
val key = hexToBytes(td.keyHex)
val data = hexToBytes(td.dataHex)
val givenTag = hexToBytes(td.hmacSha256TagHex)
val computedTag = crypto.hmacSha256(key, data)
assertArrayEquals(givenTag, computedTag)
}
}

private fun hexToKyberPrivateKey(privateKey: String): KyberPrivateKey {
val keyComponents = bytesToByteArrays(hexToBytes(privateKey), 5)
return KyberPrivateKey(DataWrapper(keyComponents[0] + keyComponents[3] + keyComponents[4] + keyComponents[1] + keyComponents[2]))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.tutao.tutanota.testdata;

public class HmacSha256TestData {

String keyHex;
String dataHex;
String hmacSha256TagHex;

public HmacSha256TestData() {
}

public HmacSha256TestData(String keyHex, String dataHex, String hmacSha256TagHex) {
this.keyHex = keyHex;
this.dataHex = dataHex;
this.hmacSha256TagHex = hmacSha256TagHex;
}

public String getKeyHex() {
return keyHex;
}

public void setKeyHex(String keyHex) {
this.keyHex = keyHex;
}

public String getDataHex() {
return dataHex;
}

public void setDataHex(String dataHex) {
this.dataHex = dataHex;
}

public String getHmacSha256TagHex() {
return hmacSha256TagHex;
}

public void setHmacSha256TagHex(String hmacSha256TagHex) {
this.hmacSha256TagHex = hmacSha256TagHex;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class TestData {
List<PQCryptTestData> pqCryptEncryptionTests = new LinkedList<>();
List<ByteArrayEncodingTestData> byteArrayEncodingTests = new LinkedList<>();
List<HkdfTestData> hkdfTests = new LinkedList<>();
List<HmacSha256TestData> hmacSha256Tests = new LinkedList<>();

public TestData addRsaEncryptionTest(EncryptionTestData test) {
this.rsaEncryptionTests.add(test);
Expand Down Expand Up @@ -99,6 +100,11 @@ public TestData addHkdfTest(HkdfTestData test) {
return this;
}

public TestData addHmacSha256Test(HmacSha256TestData test) {
this.hmacSha256Tests.add(test);
return this;
}

public List<EncryptionTestData> getRsaEncryptionTests() {
return rsaEncryptionTests;
}
Expand Down Expand Up @@ -159,5 +165,8 @@ public List<ByteArrayEncodingTestData> getByteArrayEncodingTests() {
public List<HkdfTestData> getHkdfTests() {
return hkdfTests;
}
public List<HmacSha256TestData> getHmacSha256Tests() {
return hmacSha256Tests;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class AndroidNativeCryptoFacade(
const val AES256_KEY_LENGTH = 256
const val AES256_KEY_LENGTH_BYTES = AES256_KEY_LENGTH / 8

const val HMAC_256 = "HmacSHA256"
const val HMAC_SHA_256 = "HmacSHA256"

/**
* Converts the given byte array to a key.
Expand Down Expand Up @@ -115,12 +115,13 @@ class AndroidNativeCryptoFacade(

}

private fun hmac256(key: ByteArray, data: ByteArray): ByteArray {
val macKey = SecretKeySpec(key, HMAC_256)
val hmac = Mac.getInstance(HMAC_256)
hmac.init(macKey)
return hmac.doFinal(data)
}
}

fun hmacSha256(key: ByteArray, data: ByteArray): ByteArray {
val macKey = SecretKeySpec(key, HMAC_SHA_256)
val hmac = Mac.getInstance(HMAC_SHA_256)
hmac.init(macKey)
return hmac.doFinal(data)
}

override suspend fun generateKyberKeypair(seed: DataWrapper): KyberKeyPair {
Expand Down Expand Up @@ -247,7 +248,7 @@ class AndroidNativeCryptoFacade(
val data = tempOut.toByteArray()
out.write(byteArrayOf(1))
out.write(data)
val macBytes = hmac256(subKeys.mKey!!, data)
val macBytes = hmacSha256(subKeys.mKey!!, data)
out.write(macBytes)
} else {
out.write(tempOut.toByteArray())
Expand Down Expand Up @@ -409,7 +410,7 @@ class AndroidNativeCryptoFacade(
val cipherText = tempOut.toByteArray()
val cipherTextWithoutMac = cipherText.copyOfRange(1, cipherText.size - 32)
val providedMacBytes = cipherText.copyOfRange(cipherText.size - 32, cipherText.size)
val computedMacBytes = hmac256(subKeys.mKey!!, cipherTextWithoutMac)
val computedMacBytes = hmacSha256(subKeys.mKey!!, cipherTextWithoutMac)
if (!Arrays.equals(computedMacBytes, providedMacBytes)) {
throw CryptoError("invalid mac")
}
Expand Down

0 comments on commit 8d0447d

Please sign in to comment.