Fix OTP generation for long secret key #848

This commit is contained in:
J-Jamet
2021-01-13 16:46:19 +01:00
parent 23468290df
commit 4b4fd2a11d
3 changed files with 13 additions and 18 deletions

View File

@@ -123,7 +123,7 @@ dependencies {
// Apache Commons Collections
implementation 'commons-collections:commons-collections:3.2.2'
// Apache Commons Codec
implementation 'commons-codec:commons-codec:1.14'
implementation 'commons-codec:commons-codec:1.15'
// Icon pack
implementation project(path: ':icon-pack-classic')
implementation project(path: ':icon-pack-material')

View File

@@ -151,16 +151,16 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {
@Throws(IllegalArgumentException::class)
fun setBase32Secret(secret: String) {
if (isValidBase32(secret))
otpModel.secret = Base32().decode(replaceBase32Chars(secret).toByteArray())
else
if (isValidBase32(secret)) {
otpModel.secret = Base32().decode(replaceBase32Chars(secret))
} else
throw IllegalArgumentException()
}
@Throws(IllegalArgumentException::class)
fun setBase64Secret(secret: String) {
if (isValidBase64(secret))
otpModel.secret = Base64().decode(secret.toByteArray())
otpModel.secret = Base64().decode(secret)
else
throw IllegalArgumentException()
}
@@ -209,30 +209,24 @@ data class OtpElement(var otpModel: OtpModel = OtpModel()) {
fun isValidBase32(secret: String): Boolean {
val secretChars = replaceBase32Chars(secret)
return secretChars.isNotEmpty() && checkBase32Secret(secretChars)
return secret.isNotEmpty()
&& (Pattern.matches("^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=)?$", secretChars))
}
fun isValidBase64(secret: String): Boolean {
// TODO replace base 64 chars
return secret.isNotEmpty() && checkBase64Secret(secret)
return secret.isNotEmpty()
&& (Pattern.matches("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", secret))
}
fun replaceBase32Chars(parameter: String): String {
// Add 'A' at end if not Base32 length
// Add padding '=' at end if not Base32 length
var parameterNewSize = parameter.toUpperCase(Locale.ENGLISH).removeSpaceChars()
while (parameterNewSize.length % 8 != 0) {
parameterNewSize += 'A'
parameterNewSize += '='
}
return parameterNewSize
}
fun checkBase32Secret(secret: String): Boolean {
return (Pattern.matches("^(?:[A-Z2-7]{8})*(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}=)?$", secret))
}
fun checkBase64Secret(secret: String): Boolean {
return (Pattern.matches("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", secret))
}
}
}

View File

@@ -247,8 +247,9 @@ object OtpEntryFields {
encodeParameter(username)
else
encodeParameter(otpElement.name)
val secret = encodeParameter(otpElement.getBase32Secret())
val uriString = StringBuilder("otpauth://$otpAuthority/$issuer%3A$accountName" +
"?$SECRET_URL_PARAM=${otpElement.getBase32Secret()}" +
"?$SECRET_URL_PARAM=${secret}" +
"&$counterOrPeriodLabel=$counterOrPeriodValue" +
"&$DIGITS_URL_PARAM=${otpElement.digits}" +
"&$ISSUER_URL_PARAM=$issuer")