Replicating Asp.net Identity Password Hash to Chilkat - pbkdf2

Hi I want to replicate the password hashing that is done in asp.net identity such that, the resulting value of password hashed by asp.net identity and the password hashed by Chilkat are same. Is that even possible?
In C# asp.net, we use Rfc2898DeriveBytes that does the pbkdf2 for us. How can I do the same in Chilkat?
private const int PBKDF2IterCount = 1000; // default for Rfc2898DeriveBytes
private const int PBKDF2SubkeyLength = 256 / 8; // 256 bits
private const int SaltSize = 128 / 8; // 128 bits
//[ComVisible(true)]
public string HashPassword(string password)
{
if (password == null)
{
throw new ArgumentNullException("password cannot be null");
}
// Produce a version 0 (see comment above) text hash.
byte[] salt;
byte[] subkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
{
salt = deriveBytes.Salt;
subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
var outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
return Convert.ToBase64String(outputBytes);
}
Currently, the parameters I am using at Chilkat are:
Function EncryptChilkat(sPassword As String) As String
Dim crypt As New ChilkatCrypt2
Dim success As Long
success = crypt.UnlockComponent("ACHIEV.CR1082018_dCrRA3zr4e1M ")
If (success <> 1) Then
Debug.Print crypt.LastErrorText
Exit Function
End If
Dim hexKey As String
Dim pw As String
pw = "pwd"
Dim pwCharset As String
pwCharset = "base64"
' Hash algorithms may be: sha1, md2, md5, etc.
Dim hashAlg As String
hashAlg = "HMCSHA1"
' The salt should be 8 bytes:
Dim saltHex As String
saltHex = "78578E5A5D63CB06"
Dim iterationCount As Long
iterationCount = 1000
' Derive a 128-bit key from the password.
Dim outputBitLen As Long
outputBitLen = 128
' The derived key is returned as a hex or base64 encoded string.
' (Note: The salt argument must be a string that also uses
' the same encoding.)
Dim enc As String
enc = "base64"
hexKey = crypt.Pbkdf2(pw, pwCharset, hashAlg, saltHex, iterationCount, outputBitLen, enc)
EncryptChilkat = hexKey
End Function

Check the binary values of both the password and the salt on both sides. Also check for trailing nulls, carriage returns, and line feeds.
Additionally, you can see which, if either, algorithm is misbehaving - I have a copy of Jither's .NET PBKDF2 implementation at my github repository including test vectors, and for your Chillkat, you can create what you need from my LibreOffice Calc sheet of PBKDF2 test vectors.
Run these through both implementations; whichever one fails is wrong.
If both succeed... then you're not giving both the same parameters.

Related

Node.JS encrypt using MD5 / ECB and padding w/PKCS7

I inherited a database that has the passwords utilizing the following functions to encrypt/decrypt in VB.NET
Public Shared Function EncryptString(ByVal Message As String, ByVal Passphrase As String) As String
Dim Results As Byte()
Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
Dim HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
Dim TDESKey As Byte() = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase))
Dim TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider()
TDESAlgorithm.Key = TDESKey
TDESAlgorithm.Mode = CipherMode.ECB
TDESAlgorithm.Padding = PaddingMode.PKCS7
Dim DataToEncrypt As Byte() = UTF8.GetBytes(Message)
Dim Encryptor As ICryptoTransform = TDESAlgorithm.CreateEncryptor()
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length)
Return Convert.ToBase64String(Results)
End Function
Public Shared Function DecryptString(ByVal Message As String, ByVal Passphrase As String) As String
Dim Results As Byte()
Dim UTF8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
Dim HashProvider As MD5CryptoServiceProvider = New MD5CryptoServiceProvider()
Dim TDESKey As Byte() = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase))
Dim TDESAlgorithm As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider()
TDESAlgorithm.Key = TDESKey
TDESAlgorithm.Mode = CipherMode.ECB
TDESAlgorithm.Padding = PaddingMode.PKCS7
Dim DataToDecrypt As Byte() = Convert.FromBase64String(Message)
Dim Decryptor As ICryptoTransform = TDESAlgorithm.CreateDecryptor()
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length)
Return UTF8.GetString(Results)
End Function
I am having a hard time encrypting the data to query the SQL server.
When using EncryptString with the following parameters:
Message = stack-overflow
Passphrase = Danielle
I get:
1c2wL+guV34oyVS0vkxwVA==
I need to do this encryption and decryption with node.js
I tried this but it did not work:
var crypto = require('crypto');
encrypt(text, paraphrase) {
const key =text;
const secret =paraphrase;
// Encryption
const cipher = crypto.createCipheriv("aes-192-ecb", Buffer.from(key, "base64"), null);
const encryptedSecret = cipher.update(secret, "utf8", "base64") + cipher.final("base64");
return(encryptedSecret);
};
I also tried installing MD5 by npm but I had no luck either.
Any help to encrypt and decrypt will be appreciated. Thank you all.
For the NodeJS code to be compatible with the VB code, TripleDES must be used instead of AES. The key must be derived with MD5. Since MD5 provides a 16 bytes key, TripleDES is applied in the double-length key variant (2TDEA), which combines two DES keys K1 and K2 to a TripleDES key K1|K2|K1. One possible implementation is:
var key16 = crypto.createHash('md5').update(passphrase).digest();
var cipher = crypto.createCipheriv("des-ede-ecb", key16, null);
var ciphertext = cipher.update(data, "utf8", "base64") + cipher.final("base64");
If des-ede-ecb is not supported, des-ede3-ecb can be used as an alternative. This implements TripleDES in the triple-length key variant (3TDEA), which combines three DES keys K1, K2 and K3 to a TripleDES key K1|K2|K3. For K3 = K1 this is equivalent to 2TDEA:
var key16 = crypto.createHash('md5').update(passphrase).digest();
var key24 = Buffer.concat([key16, key16.slice(0, 8)]);
var cipher = crypto.createCipheriv("des-ede3-ecb", key24, null);
Note that ECB is insecure (better a mode with an IV like GCM), as is key derivation via a cryptographic hash function (better a reliable key derivation function like PBKDF2) and the broken MD5 as such (better SHA256). TripleDES is deprecated and slow (better AES).
Edit:
The decryption is completely analog, e.g. for 2TDEA:
var key16 = crypto.createHash('md5').update(passphrase).digest();
var decipher = crypto.createDecipheriv("des-ede-ecb", key16, null);
var decrypted = decipher.update(ciphertext, "base64", "utf8") + decipher.final("utf8");

TripleDes CBC Nodejs implementation throuble

i need to replicate in Nodejs the results of the 3DS CBC encrypt in http://tripledes.online-domain-tools.com/.
This is my code:
const crypto = require('crypto');
const cipher = crypto.createCipher('des-ede3-cbc', key);
password = Buffer.from('MYPASS', 'utf8');
let encrypted = [cipher.update(password)];
encrypted.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
console.log(encrypted.toString('hex'));
The result of tripledes.online-domain-tools.com is:
Note that the result should be 59 30 20 02 a5 8c dd 5e, but my code gives me 33 97 d8 b0 e3 00 d1 53.
What am i missing?
Edit2:
Following your suggestions, I changed my code (Also added some Tests made with the guide of the NIST Publication):
const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
let shortkey = Buffer.from(inputkey, keyformat);
let key = Buffer.alloc(24);
key.fill('\0');
for (i = 0; i < shortkey.length; i++) {
key[i] = shortkey[i];
}
let IV = Buffer.alloc(8);
const cipher = crypto.createCipheriv('des-ede3-cbc', key, IV);
password = Buffer.from(password, passwordformat);
let encryptedArr = [cipher.update(password)];
encryptedArr.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
return encrypted;
}
console.log(encrypt('1046913489980131','hex','0000000000000000','hex')); // works
console.log(encrypt('1007103489988020','hex','0000000000000000','hex')); // works
console.log(encrypt('10071034C8980120','hex','0000000000000000','hex')); // works
console.log(encrypt('1046103489988020','hex','0000000000000000','hex')); // works
console.log(encrypt('MYKEY','utf8','MYPASS','utf8')); // fails
Every Permutation Operation Known Answer Test of the NIST works great, but several other examples (including the one of the image) just fails
The reason i'm testing with this shady page is because my service provider is using it as reference.
This site made me some troubles for some time , well here is the implementation it uses internally to expand the key to be a 24 bytes !
i am going to talk about tripledes but i guess this would apply to other algorithms used by this site
step 1
it first checks if the key entered has the length that it expects it to be, (you can find a table at the bottom of that site telling the length of key for each Encryption algorithm)
if it does not it will complete with 0x00 bytes like this:
var key;// is a string containing the bytes wich will be used to encrypt the msg
var nullByte = 0x00;
var padding_needed;
for (var i=key.length ;i < expected_key_length ; ++)
{padding_needed =padding_needed + nullBute.tostring(16); }
key = key + padding_needed
so for example the length that it expects for 3DES is 24 bytes ; if you happen to enter just 15 bytes like this (112233445566778899aabbccddeeff) it will be like if you entered (112233445566778899aabbccddeeff00)
step2
in the case of tripledes the algorithm to expand the 16 bytes to 24 bytes key (which is the key length required by the algorithm) this site has a simple approach to do that
it copies the first 8 bytes and append it to the end of the key like this
key =key + key.substring(0,8);
and that is the key that is going to be given to the 3DES encryption function to work with
this simple approache is not used by openssl for example , open ssl uses the first 8 bytes of the MD5 of the key ,and append them to the 16 bytes of the original key to get the 24 bytes key that is required by 3DES, like this
key = key + (MD5(key)).substring(0,8);
Summary
in that tool if you enter the key 112233445566778899AABBCCDDEEFF is the same as if you entered 112233445566778899AABBCCDDEEFF00 and same as if you entered 112233445566778899AABBCCDDEEFF001122334455667788 so to solve your problem you should give your function the complete 24 bytes of key that you gave to that site and you will surely get the same results, beacause nodejs is probably is doing the same thing as openssl does to expand the key(uses md5)
PS
if you are using the cbc mode which is your case try to specify the IV to be 8 bytes of \x00 like this "0000000000000000"
the results will be the same !!
here is a working implementation of your code you can check it in the site
const crypto = require('crypto');
function encrypt (inputkey, keyformat, password, passwordformat) {
let shortkey = Buffer.from(inputkey, keyformat);
let key = Buffer.alloc(24);
key.fill('\0');
for (i = 0; i < shortkey.length; i++) {
key[i] = shortkey[i];
}
let IV = Buffer.alloc(8);
var expansionStart = shortkey.length>16?shortkey.length:16;
for (i=expansionStart;i<24;i++){
key[i]=key[i-expansionStart];
}
console.log(key);
const cipher = crypto.createCipheriv('des-ede3-cbc', key, IV);
password = Buffer.from(password, passwordformat);
let encryptedArr = [cipher.update(password)];
encryptedArr.push(cipher.final());
encrypted = Buffer.concat(encryptedArr);
return encrypted;
}
var enc = encrypt("112233445566778899AABBCCDDEEFF","hex","password","utf8");
console.log(enc);

How to find SHA1 hash?

i got interesting task at school. I have to find message which sha-1 hash lasts with my birthday example. if i was born on 4th may 1932 then the hash must end with 040532. Any suggestions how to find it out?
my solution in C#:
//A create Sha1 function:
using System.Security.Cryptography;
public static string GetSHA1Hash(string text)
{
var SHA1 = new SHA1CryptoServiceProvider();
byte[] arrayData;
byte[] arrayResult;
string result = null;
string temp = null;
arrayData = Encoding.ASCII.GetBytes(text);
arrayResult = SHA1.ComputeHash(arrayData);
for (int i = 0; i < arrayResult.Length; i++)
{
temp = Convert.ToString(arrayResult[i], 16);
if (temp.Length == 1)
temp = "0" + temp;
result += temp;
}
return result;
}
Source
Then a Random String generator:
private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
private string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
Source
and now you can bruteforce for your combination:
string search = "32";
string result = String.Empty;
int slen = 5;
string myTry = RandomString(slen);
while (!result.EndsWith(search))
{
myTry = RandomString(slen);
result = GetSHA1Hash(myTry);
}
MessageBox.Show(result + " " + myTry);
This would search for a Hash String ending with 32. Happy Bruteforcing :)
EDIT: found one for your example: HXMQVNMRFT gives e5c9fa9f6acff07b89c617c7fd16a9a043040532
Start generating hashes from distinct messages1.
Eventually a hash will be generated with such a property. This is not that bad to brute-force as the range is only 224 (or ~16 million) and SHA is very fast.
There is no shortcut as SHA is a one way cryptographic hash function. In particular here, SHA has the property that "it is infeasible to generate a message that has a given hash".
1 The inputs should be distinct, and a simple counter will suffice. However, it may be more interesting to generate quasi-random messages based on the birthday being sought - e.g. including the date in various forms and sentences Mad Lib style. As long as this doesn't limit the domain, such that there is no qualifying hash, it'll work just as well as any other set of source messages.

Signing a string with HMAC-MD5 with C#

I got the following HMAC key (in hexadecimal format):
52320e181a481f5e19507a75b3cae4d74d5cfbc328f7f2b738e9fb06b2e05b55b632c1c3d331dcf3baacae8d3000594f839d770f2080910b52b7b8beb3458c08
I need to sign this string:
1100002842850CHF91827364
The result should be this (in hexadecimal format):
2ad2f79111afd818c1dc0916d824b0a1
I have the following code:
string key = "52320e181a481f5e19507a75b3cae4d74d5cfbc328f7f2b738e9fb06b2e05b55b632c1c3d331dcf3baacae8d3000594f839d770f2080910b52b7b8beb3458c08";
string payload = "1100002842850CHF91827364";
byte[] keyInBytes = Encoding.UTF8.GetBytes(key);
byte[] payloadInBytes = Encoding.UTF8.GetBytes(payload);
var md5 = new HMACMD5(keyInBytes);
byte[] hash = md5.ComputeHash(payloadInBytes);
var result = BitConverter.ToString(hash).Replace("-", string.Empty);
However, I am not getting the result. What am I doing wrong?
when hashing with key HMAC md5
var data = Encoding.UTF8.GetBytes(plaintext);
// key
var key = Encoding.UTF8.GetBytes(transactionKey);
// Create HMAC-MD5 Algorithm;
var hmac = new HMACMD5(key);
// Compute hash.
var hashBytes = hmac.ComputeHash(data);
// Convert to HEX string.
return System.BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
Instead of doing this:
byte[] keyInBytes = Encoding.UTF8.GetBytes(key);
you need to convert key from a hex string to array of bytes. Here you can find example:
How do you convert Byte Array to Hexadecimal String, and vice versa?

How to check whether a string is Base64 encoded or not

I want to decode a Base64 encoded string, then store it in my database. If the input is not Base64 encoded, I need to throw an error.
How can I check if a string is Base64 encoded?
You can use the following regular expression to check if a string constitutes a valid base64 encoding:
^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$
In base64 encoding, the character set is [A-Z, a-z, 0-9, and + /]. If the rest length is less than 4, the string is padded with '=' characters.
^([A-Za-z0-9+/]{4})* means the string starts with 0 or more base64 groups.
([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$ means the string ends in one of three forms: [A-Za-z0-9+/]{4}, [A-Za-z0-9+/]{3}= or [A-Za-z0-9+/]{2}==.
If you are using Java, you can actually use commons-codec library
import org.apache.commons.codec.binary.Base64;
String stringToBeChecked = "...";
boolean isBase64 = Base64.isArrayByteBase64(stringToBeChecked.getBytes());
[UPDATE 1] Deprecation Notice
Use instead
Base64.isBase64(value);
/**
* Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
* method treats whitespace as valid.
*
* #param arrayOctet
* byte array to test
* #return {#code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
* {#code false}, otherwise
* #deprecated 1.5 Use {#link #isBase64(byte[])}, will be removed in 2.0.
*/
#Deprecated
public static boolean isArrayByteBase64(final byte[] arrayOctet) {
return isBase64(arrayOctet);
}
Well you can:
Check that the length is a multiple of 4 characters
Check that every character is in the set A-Z, a-z, 0-9, +, / except for padding at the end which is 0, 1 or 2 '=' characters
If you're expecting that it will be base64, then you can probably just use whatever library is available on your platform to try to decode it to a byte array, throwing an exception if it's not valid base 64. That depends on your platform, of course.
As of Java 8, you can simply use java.util.Base64 to try and decode the string:
String someString = "...";
Base64.Decoder decoder = Base64.getDecoder();
try {
decoder.decode(someString);
} catch(IllegalArgumentException iae) {
// That string wasn't valid.
}
Try like this for PHP5
//where $json is some data that can be base64 encoded
$json=some_data;
//this will check whether data is base64 encoded or not
if (base64_decode($json, true) == true)
{
echo "base64 encoded";
}
else
{
echo "not base64 encoded";
}
Use this for PHP7
//$string parameter can be base64 encoded or not
function is_base64_encoded($string){
//this will check if $string is base64 encoded and return true, if it is.
if (base64_decode($string, true) !== false){
return true;
}else{
return false;
}
}
var base64Rejex = /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i;
var isBase64Valid = base64Rejex.test(base64Data); // base64Data is the base64 string
if (isBase64Valid) {
// true if base64 formate
console.log('It is base64');
} else {
// false if not in base64 formate
console.log('it is not in base64');
}
Try this:
public void checkForEncode(String string) {
String pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(string);
if (m.find()) {
System.out.println("true");
} else {
System.out.println("false");
}
}
It is impossible to check if a string is base64 encoded or not. It is only possible to validate if that string is of a base64 encoded string format, which would mean that it could be a string produced by base64 encoding (to check that, string could be validated against a regexp or a library could be used, many other answers to this question provide good ways to check this, so I won't go into details).
For example, string flow is a valid base64 encoded string. But it is impossible to know if it is just a simple string, an English word flow, or is it base 64 encoded string ~Z0
There are many variants of Base64, so consider just determining if your string resembles the varient you expect to handle. As such, you may need to adjust the regex below with respect to the index and padding characters (i.e. +, /, =).
class String
def resembles_base64?
self.length % 4 == 0 && self =~ /^[A-Za-z0-9+\/=]+\Z/
end
end
Usage:
raise 'the string does not resemble Base64' unless my_string.resembles_base64?
Check to see IF the string's length is a multiple of 4. Aftwerwards use this regex to make sure all characters in the string are base64 characters.
\A[a-zA-Z\d\/+]+={,2}\z
If the library you use adds a newline as a way of observing the 76 max chars per line rule, replace them with empty strings.
/^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/
this regular expression helped me identify the base64 in my application in rails, I only had one problem, it is that it recognizes the string "errorDescripcion", I generate an error, to solve it just validate the length of a string.
For Flutter, I tested couple of the above comments and translated that into dart function as follows
static bool isBase64(dynamic value) {
if (value.runtimeType == String){
final RegExp rx = RegExp(r'^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$',
multiLine: true,
unicode: true,
);
final bool isBase64Valid = rx.hasMatch(value);
if (isBase64Valid == true) {return true;}
else {return false;}
}
else {return false;}
}
In Java below code worked for me:
public static boolean isBase64Encoded(String s) {
String pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(s);
return m.find();
}
This works in Python:
import base64
def IsBase64(str):
try:
base64.b64decode(str)
return True
except Exception as e:
return False
if IsBase64("ABC"):
print("ABC is Base64-encoded and its result after decoding is: " + str(base64.b64decode("ABC")).replace("b'", "").replace("'", ""))
else:
print("ABC is NOT Base64-encoded.")
if IsBase64("QUJD"):
print("QUJD is Base64-encoded and its result after decoding is: " + str(base64.b64decode("QUJD")).replace("b'", "").replace("'", ""))
else:
print("QUJD is NOT Base64-encoded.")
Summary: IsBase64("string here") returns true if string here is Base64-encoded, and it returns false if string here was NOT Base64-encoded.
C#
This is performing great:
static readonly Regex _base64RegexPattern = new Regex(BASE64_REGEX_STRING, RegexOptions.Compiled);
private const String BASE64_REGEX_STRING = #"^[a-zA-Z0-9\+/]*={0,3}$";
private static bool IsBase64(this String base64String)
{
var rs = (!string.IsNullOrEmpty(base64String) && !string.IsNullOrWhiteSpace(base64String) && base64String.Length != 0 && base64String.Length % 4 == 0 && !base64String.Contains(" ") && !base64String.Contains("\t") && !base64String.Contains("\r") && !base64String.Contains("\n")) && (base64String.Length % 4 == 0 && _base64RegexPattern.Match(base64String, 0).Success);
return rs;
}
There is no way to distinct string and base64 encoded, except the string in your system has some specific limitation or identification.
This snippet may be useful when you know the length of the original content (e.g. a checksum). It checks that encoded form has the correct length.
public static boolean isValidBase64( final int initialLength, final String string ) {
final int padding ;
final String regexEnd ;
switch( ( initialLength ) % 3 ) {
case 1 :
padding = 2 ;
regexEnd = "==" ;
break ;
case 2 :
padding = 1 ;
regexEnd = "=" ;
break ;
default :
padding = 0 ;
regexEnd = "" ;
}
final int encodedLength = ( ( ( initialLength / 3 ) + ( padding > 0 ? 1 : 0 ) ) * 4 ) ;
final String regex = "[a-zA-Z0-9/\\+]{" + ( encodedLength - padding ) + "}" + regexEnd ;
return Pattern.compile( regex ).matcher( string ).matches() ;
}
If the RegEx does not work and you know the format style of the original string, you can reverse the logic, by regexing for this format.
For example I work with base64 encoded xml files and just check if the file contains valid xml markup. If it does not I can assume, that it's base64 decoded. This is not very dynamic but works fine for my small application.
This works in Python:
def is_base64(string):
if len(string) % 4 == 0 and re.test('^[A-Za-z0-9+\/=]+\Z', string):
return(True)
else:
return(False)
Try this using a previously mentioned regex:
String regex = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
if("TXkgdGVzdCBzdHJpbmc/".matches(regex)){
System.out.println("it's a Base64");
}
...We can also make a simple validation like, if it has spaces it cannot be Base64:
String myString = "Hello World";
if(myString.contains(" ")){
System.out.println("Not B64");
}else{
System.out.println("Could be B64 encoded, since it has no spaces");
}
if when decoding we get a string with ASCII characters, then the string was
not encoded
(RoR) ruby solution:
def encoded?(str)
Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count.zero?
end
def decoded?(str)
Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count > 0
end
Function Check_If_Base64(ByVal msgFile As String) As Boolean
Dim I As Long
Dim Buffer As String
Dim Car As String
Check_If_Base64 = True
Buffer = Leggi_File(msgFile)
Buffer = Replace(Buffer, vbCrLf, "")
For I = 1 To Len(Buffer)
Car = Mid(Buffer, I, 1)
If (Car < "A" Or Car > "Z") _
And (Car < "a" Or Car > "z") _
And (Car < "0" Or Car > "9") _
And (Car <> "+" And Car <> "/" And Car <> "=") Then
Check_If_Base64 = False
Exit For
End If
Next I
End Function
Function Leggi_File(PathAndFileName As String) As String
Dim FF As Integer
FF = FreeFile()
Open PathAndFileName For Binary As #FF
Leggi_File = Input(LOF(FF), #FF)
Close #FF
End Function
import java.util.Base64;
public static String encodeBase64(String s) {
return Base64.getEncoder().encodeToString(s.getBytes());
}
public static String decodeBase64(String s) {
try {
if (isBase64(s)) {
return new String(Base64.getDecoder().decode(s));
} else {
return s;
}
} catch (Exception e) {
return s;
}
}
public static boolean isBase64(String s) {
String pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(s);
return m.find();
}
For Java flavour I actually use the following regex:
"([A-Za-z0-9+]{4})*([A-Za-z0-9+]{3}=|[A-Za-z0-9+]{2}(==){0,2})?"
This also have the == as optional in some cases.
Best!
I try to use this, yes this one it's working
^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$
but I added on the condition to check at least the end of the character is =
string.lastIndexOf("=") >= 0

Resources