Invalid Hash Function Name on SHA2-512 when creating user - google-admin-sdk

Trying to create user using from golang using library "google.golang.org/api/admin/directory/v1"
As docs sad here https://developers.google.com/admin-sdk/directory/reference/rest/v1/users#User hashFunction could be MD5, DES, SHA2-256, SHA2-512, so i'm writing code:
hash := sha512.Sum512([]byte("random password value))
encoded := hex.EncodeToString(hash[:])
payload := &admin.User{
Password: "$6$" + encoded,
HashFunction: "SHA2-512"
}
This results: googleapi: Error 400: Invalid Hash Function Name, invalid
So how to understand, whats wrong with hash function name ?

So, i found here https://developers.google.com/resources/api-libraries/documentation/admin/directory_v1/python/latest/admin_directory_v1.users.html#insert that right now only supported SHA-1, crypt and MD5, so documentation is wrong, and for SHA2 hashes use string "crypt" as hashFunction value and add to password corresponding crypt prefix ( for example for SHA2-512 add $6$ to hex encoded value )

Related

problem to configure public key on google audit email api

I need a help! I'm trying to use the google auditing API (https://developers.google.com/admin-sdk/email-audit)
Im getting a problem to configure the public key on API (https://developers.google.com/admin-sdk/email-audit/auth#example), receiving the following error:
The value of attribute "value" associated with an element type "apps:property" must not contain the
'<' character.
Im following the documentation payload:
<atom:entry xmlns:atom='http://www.w3.org/2005/Atom' xmlns:apps='http://schemas.google.com/apps/2006'>
<apps:property name="publicKey" value="<em>my public key in base64 here</em>"/>
</atom:entry>
One example of public key that i generated and encoded on base64:
LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptUUlOQkdJOW96c0JFQUNkTWlUajY2UUNJeTlOSjNzQzFGS1dlaFZDaTRKaGRtZDVhemtnMlh5WlM5RXNGT2hDCkJ6elVlT2lyRnRaKzR2c3pQZUdNT3A5eXlKS0dCcnk3ZUVWV0JzZTE0aHFzSjJiY1NRSEFOMnpVdDl6WlZNbzkKS3lBdGZxNytxTGRhNjhMbUpmM1drT1RxVFVCWnZ5OTQvYnhCMmR2UkR0ZWtCRFo2TlZIMVpObFJLOXY3Si90cgpNYmFvRnhiSmF4RlA4ZkZrVGxhcS9aY2ZCRmcxOWV0YkpHWUdTSU9yRlZ5MXVyQmlUOGx2TFhEbi81a2JNc0o1Cms3am5sUUNqcDcrN0RLSXVlSXBISGZBY2xNaitreEl4WmdlZElVbzJ0RTV3UVVIYmNmSU96a010UEFFWENUTUgKZW9GR2drTVBaaHB1NlhhbFY0RnlHZzdPMEtLWGcweHFtdjI3UDd1a0VlaFRkbzVLZitzZW5YZzVEbVpLQm9mRwoyejlzQUg1MXplWXZkVHhDSkdtdUprdWJPMEcvTFhxOHlGRW5oZEkyZjNkazQwNUZ4UlJna1BGU2tOYjFVS21mCklCSU1uM0VDVG1qK1JOWE9aS0Rqd2hmdHpkRS9KVGpueU1JVUFWR0VEWGtGdEVXTVRpSmIrVURZQi9odm9QS2sKdUNXNUNDNWtuOG14Z2x4eWxIaUVhQWJ6dTQ3MFBaaW9NTWo5VHk2VGZOVXZDOXJsRGszSEsreUpIaWJqWmxOagoxREdaN01yZWs4STV0ZVlVcmtZYVNDNUt4SVhSRjZwaEIyZUdUdzh5SEp3UUd3RURPL1E1QmJ3Q2dqREN4VS9ICkUyTFF4MURZeFU1Q1l4U1dIR0xzcVkrQUxKNGlsSXdNWEZERFZOdzRFVTl0Yis3cWdTajhXR2FRM1FBUkFRQUIKdEE1S2I4T2pieUJrWlNCQmMzTnBjNGtDVkFRVEFRZ0FQaFloQkJnbEtEbGhsVHFpUStRVUd2WFc5blJHV05JbQpCUUppUGFNN0Foc0RCUWtIaGg5eUJRc0pDQWNDQmhVS0NRZ0xBZ1FXQWdNQkFoNEJBaGVBQUFvSkVQWFc5blJHCldOSW1CbDRQL1JUeDlkbW1oMitXUE9jRUpGMXcvVkZqRFBMbkFWV3VSQnRKYmd2SVlETVdBUHpaTC9OYlRCL0wKUE1BYVdqdFlsRUZrZkpJMGxjdnU0L2F0R0JydDBIeGZFMW5FRjkzME5HcGNSaU80blcyd1hZSUhmaHg2ZnRlZwo3a283TDVPN21jMDgwWnpQRXQrSjEzZTZnSVdwbWExSXh3djRFRTVCb1NoQnpTOVlOWjNVQUJPLyszTnhCZHF2CloybldCcVR0cXpWb2Z4SGJPejBLRGJLclNLaUNmZy9EWmxzYVBES2FLMURQOU8xU3pJcURJWGQ0Q25RSWw2WUEKQjJPV0cvTE05OWV5Y2pxQitVTWw3ZzR4c1hBRGV1SG12SzVUSDUwRzgvRGpsSmZtWllkdUZiSm5hZGlHUnZWbApzOVpFNnZDRzl2ajNxQUFFVDhIcHNJUldTaWNGZHczVzFYV1RDdE1pYWE1M3ZidkhVaWw5QnI5VWxWMjJLbThkCmdLM3VsZXVCMmg4WnRXeEVIbE9kVXBDQ3RsNVp3RVBMeTNTSWIrL3lnQWV5cTAxanFOY0VlZmg1emk0VXNIZmQKdXZDVDZ0T0E2bmwyTVZuSDhzWTRHUlcrM0xqZjNJSVlRNzQ3QXQ3bGRVTDJCdTUrQng1bUlEV0QzZ0kvWnJ4LwpFQVU2QWx4eTI0YWJQcG90VlBYQW1BKzMzVDZsR2dWeXUwV2U3Vm14RkxucENmby8xQXlROUNWOVhIb1NhdjhmCkRJYXNtc203VnNaYXd1VTRoVi9DV2FPcXQ4WlUzRndyRDI0NElIR2c2L1RQZU1DWlRrMVhVdEVKdW9PcUpyb04KdDVXay8vZTI2VDh2akFWQWhHOWFzNE5HQnRLbUlDdlJpUkdEalEwQ1A2WEMzOVFEeEF3VnVRSU5CR0k5b3pzQgpFQURRNGl2bTQ2YTAzTXJZcUZjay90VWYxZTdCcTNtOVdVbkVOTEdtQ1RGdG1TTVJlQm5DZEx0bTV3K3piS1hLCmZMYzdrUTFNcHJMbTJVMk1zdk9XeGVjNk91eWxXeCtxOXB5UlR1NU5VR0txN1ZPUVZRYW9TNCs5VHpTQTBETmUKcUxjbWhIakhvSVNJZWVEZXRIWEZ1ZklNcHMvVUxCSndWUzZKYzdOaUhNNmp6TVMxS1hkVzJlbEFOdDdYNXBTYwpsLy9wL1VYTWxkSmZqZHMxWmljWFlkZWtGeTVyR3pHT2s4ZEhmMDRTS0Vsa1d0Ry9xZnZqb1FoVFRuOHZFTFZXCmpxUjlwS08yVDhDNXB1VFFwQld1Z0lGMFVaalAvcWVZL0xDMmVOcHNqczZ1SjllbU5GRXZ6YkJlSjlQOWhLUzQKdHUvZWxtSWFqczBPdFpycWMrTWNSQmFvcVVWQ1BETkFabVRWTnkyQ3l1MTFkQUJIRVozQWZBTE1qNXB4TmJiQgpHTWkxblByY3lqdzFOd05CV3VKTDdaQlZ6d2J3bjVQcHNlWVB5Vi93TWszd3RWNi9XVW9vdTYxbDI3RDdnY1lKCmlyYXN4R0pmSWR5WkNVSEFmNHNIN3MxM1VRb2puVHdodGlBWFpIaWlSTlBDVWF2VXFuSDVlZ3UrOElhKzZnTDkKeGE0cUI5a1lqc1cyem1LbTY4QkpLWGJKb1ZleGdOaVVnajYxZkphOC85UTJyQ2V5Y1VpdXRDbzFsUDFVQzhYMQplekNBNi8vL0hxQUxoU2ZuQ0hONHZRMzUvdlNGaHo3LzREbTBzSjI3Qk5leG0vQ1JFYXNBdVVYVWJFdXF4Q2VVCkZCMHVDTlo4cXkxT2FpWnl0cDFCaDBjYjlQWDdaSE9QQmpMeWpGaEZCak16RlFBUkFRQUJpUUk4QkJnQkNBQW0KRmlFRUdDVW9PV0dWT3FKRDVCUWE5ZGIyZEVaWTBpWUZBbUk5b3pzQ0d3d0ZDUWVHSDNJQUNna1E5ZGIyZEVaWQowaVpNT2cvK0kzejdnOElCWE81SThaNmY4cjhVcVpRNjE0dlkyUGtUSk1kK1c5SnZyTmFBWDJOdXBxMFk1ZjlLCkFiSTVCcjBaOFp1MjQ2NjVZZFQyUkNOS3VDa0dmZUc3WWlvTnhDREc2dys2c1o3SWtWQjBhcDJwYk8wb1ZBcFgKYzlWc3RzY2p2dkJheC91djgrZElGUmpKUithb21KRzFURVpVcWNvMEJVcHRXRUs3azN5SXAyUlBDVW5oeEcySQpZbUUwMmEwNkljdE9oeUtBUW9FM2ZRQmdLUGN6Z0tnbWNCdjhreDU4Qld1UEkyZk9MMjhQSm1jSzg5ZWpFdEwxCnRoNHh2dE9ibXl6SkFZTUduMHYyenpvV0NJUENGL2FIaVhpOEFvSEJRRExpeVpnejRla2Q0Q3B3TEtJUmJxYzQKZkkzOEgzQlQvQmxML3Bic0RHeXUvc2NVbUVsc3MrbnhrOWhkZVdwdCt2TTFGc2duN1RCY0FUb21zaVBVSG1obQpBUCsvdFRMVnNBb3FnMHpoanBaNVhBS28yUHVGZk42M2EvMGwxOXR2SmxGa09ZT0JEYVZKOWoxZmhuclBaSnJmCjJwODNLM1lhZ3hIWEQvNUFhVGNoM0Z5V2Nja3RmVDkyME5LY3AzUHNtZnN2bU5HdUYrRnlmYVpCQXh4MmtkWmgKTG13MEx6NVE3ME8wd1J4NnJZNmN0bHRvdnVlY29IS1VTWWdPamFsNzc3cG5tODRYb2FkdXdUdDVnUXlrdmlScwpiVHhZMytaWWM4eFJ1QjJYaTVkZGFUWkw2bEJoclpDMHdDWnI2L2hPYTVhUFdVVStGeFdtZkpsZ3A0Z1VkeVIwCldkK1FOMXNMZmt0b2Y5amJXeFRwNjd5SUpBMDV6c2VpdUp4OEszTmxDWk80YTN1T2xuUT0KPWZmZWsKLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQ==
If you check on base64 decode for example, you can see that its a complete public key...
Any idea?
Thank you!
The error message points that there is a non valid character being passed on the "value" attribute, in this case the <> characters are non valid within the value field, checking your example you are adding it like this:
<apps:property name="publicKey" value="<em>my public key in base64 here</em>"/>
Where the "value=<em>my public key in base64 here</em>" is being passed with the "<>" characters, even though the documentation states that "<em>" and "</em>" is passed you can still just remove the tags and add the public key without them like this:
<apps:property name="publicKey" value="my public key in base64 here"/>

Best attribute to use from AWS CognitoUser class for primary key in DynamoDB

I am trying to make the primary key of my dynamodb table something like user_uuid. The user is being created in AWS Cognito and I can't seem to find a uuid like field as part of the CognitoUser class. I am trying to avoid using the username as the pk.
Can someone guide me to the right solution? I can't seem to find anything on the internet regarding a user_uuid field and for some reason I can't even find the documentation of CognitoUser class that is imported from "amazon-cognito-identity-js";
Depends if you plan to use email or phone as a 'username'. In that case, I would use the sub because it never changes. But, the sub is not k-sortable so that requires the use of an extra DB item and index/join to make users sortable by date added. If you plan to generate your GUID/KSUID, and only use email/phone as an alias, then I would use the 'username' as a common id between your DB and userpool.
Good luck with your project!
FWIW - the KSUID generators found in wild are massively overbuilt. 3000+ lines of code and 80+ dependencies. I made my own k-sortable and prefixed pseudo-random ID gen for Cognito users. Here's the code.
export function idGen(prefix: any) {
const validPrefix = [
'prefix1',
'prefix2'
];
//check if prefix argument is supplied
if (!prefix) {
return 'error! must supply prefix';
}
//check if value is a valid type
else if (validPrefix.indexOf(prefix) == -1) {
return 'error! prefix value supplied must be: ' + validPrefix;
} else {
// generate epoch time in seconds
const epoch = Math.round(Date.now() / 1000);
// convert epoch time to 6 character base36 string
const time = epoch.toString(36);
// generate 20 character base36 pseudo random string
const random =
Math.random().toString(36).substring(2, 12) +
Math.random().toString(36).substring(2, 12);
// combine prefix, strings, insert : divider and return id
return prefix + ':' + time + random;
}
}
Cognito user unique identifiers can be saved to a database using a combination of the "sub" value and the username, please refer to this question for a more lengthy discussion.
In the description of amazon-cognito-identity-js (found here, use case 5), they show how to get the userAttributes of a CognitoUser. One of the attributes is the sub value, which you can get at for example like this:
user.getUserAttributes(function(err, attributes) {
if (err) {
// Handle error
} else {
// Do something with attributes
const sub = attributes.find(obj => obj.Name === 'sub').Value;
}
});
I couldn't find any documentation on the available user attributes either, I recommend using the debugger to look at the user attributes returned from the function.

Regular Expression to detect private and public RSA keys

I've searched over the internet but with no results,
There is any pattern (to be implemented in regex) to detect RSA private or public keys ?
(not included strings such as ---- Public RSA key-- or "ssh rsa")
I'm stuck after create base64 regex
var re = regexp.MustCompile(`(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3})=`)
Thanks
Get pem formatted block
If your document contains not only PEM formatted block than Decode function from encoding/pem package will be helpful:
Decode will find the next PEM formatted block (certificate, private key etc) in the input. It returns that block and the remainder of the input. If no PEM data is found, p is nil and the whole of the input is returned in rest.
Parse key and check for rsa conformity
Go contains package named crypto to do such things like parsing keys and certifies. For purpose of parsing public keys provided function ParsePKIXPublicKey:
Supported key types include RSA, DSA, and ECDSA. Unknown key types result in an error.
On success, pub will be of type *rsa.PublicKey, *dsa.PublicKey, or *ecdsa.PublicKey.
On return you obtain concrete type which is easy to assert with type switch (idiomatic way to determine type of variable):
Example:
// There is a key
const pubPEM = `MIICIjANBgkqhkiG9...`
// Ignore the rest of document
block, _ := pem.Decode([]byte(pubPEM))
if block == nil {
log.Fatal("The document doesn't contain PEM blocks.")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
log.Fatal("The block is not a DER encoded public key.")
}
switch pub := pub.(type) {
case *rsa.PublicKey:
fmt.Println("pub is of type RSA:", pub)
default:
log.Fatal("The key is not RSA encripted.")
}

QT Blowfish Charset

I need use Blowfish for check password into a database using by CMS.
I work with QBlowfish because I thinking basic class and easy to use but no, I have a problem :
I crypt same string ("AfuYeew7l") with same salt ("$2y$04$pzmGaIWodB/7jTZ8Y.082u")
When I use C++, I have : ("G?(?"?WIk???*?")
So when I use PHP, I have good hash : ("$2y$04$pzmGaIWodB/7jTZ8Y.082uA15Z.5VwrLXiBPebxNZ2ET75NqX1QOq")
My slot who hash :
QByteArray key = NULL;
QByteArray crypt = NULL;
QByteArray pass(ui->_Input_Pass_Clair->text().toLocal8Bit()); // Clear Password
QByteArray hash(ui->_Label_Retour_Hash->text().toLocal8Bit()); // Crypt Password
key.push_back(ui->_Label_Retour_ID->text().toLocal8Bit()); // SALT
key.push_back(ui->_Label_Retour_CA->text().toLocal8Bit()); // SALT
key.push_back(ui->_Label_Retour_SEL->text().toLocal8Bit()); // SALT
key.push_back("$"); // SALT
QBlowfish fish(key);
fish.setPaddingEnabled(true);
crypt = fish.encrypted(pass);
ui->_Label_Retour_Pass_Crypte->setText(crypt);
I think crypt is not on correct formated or also key is not correct formated but I haven't anything idea for correct this
I join source code if necessary

Authenticating DotNetNuke Users in ColdFusion

Is there any way to authenticate users from other web apps using the DNN logins?
We have a main site that is using DNN and user logins are stored in the asp net membership table. From what I have been reading, the passwords are encrypted using the machine key and then salted. I see where this info is, but can't seem to encrypt passwords correctly using this method.
I'm trying with a Coldfusion web application on the same server where our DNN site is, but it doesn't want to work. You'd think it would be strait forward with the ColdFusion encryption function:
Encrypt(passwordstring, key [, algorithm, encoding, IVorSalt, iterations])
No matter what I try, I never get a matching value.
Any help, insight or pointing me in the right direction would be greatly appreciated!
(Edit: Original answer did not work in all cases. Substantially revised ...)
From what I have read, DNN uses an "SHA1" hash by default. The thread #barnyr posted shows it simply hashes the concatenated salt and password, but with a few twists.
DNN uses UTF-16LE to extract the password bytes, rather than CF's typical UTF-8.
It also extracts the salt and password bytes separately, which may produce different results than just decoding everything as a single string, which is what hash() does. (See demo below)
Given that CF9's Hash function does not accept binary (supported in CF11), I do not think it is possible to duplicate the results with native CF functions alone. Instead I would suggest decoding the strings into binary, then using java directly:
Code:
<cfscript>
thePassword = "DT!#12";
base64Salt = "+muo6gAmjvvyy5doTdjyaA==";
// extract bytes of the salt and password
saltBytes = binaryDecode(base64Salt, "base64");
passBytes = charsetDecode(thePassword, "UTF-16LE" );
// next combine the bytes. note, the returned arrays are immutable,
// so we cannot use the standard CF tricks to merge them
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
dataBytes = ArrayUtils.addAll( saltBytes, passBytes );
// hash binary using java
MessageDigest = createObject("java", "java.security.MessageDigest").getInstance("SHA-1");
MessageDigest.update(dataBytes);
theBase64Hash = binaryEncode(MessageDigest.digest(), "base64");
WriteOutput("theBase64Hash= "& theBase64Hash &"<br/>");
</cfscript>
Demo of Differences:
<cfscript>
theEncoding = "UTF-16LE";
thePassword = "DT!#12";
base64Salt = "+muo6gAmjvvyy5doTdjyaA==";
// extract the bytes SEPARATELY
saltBytes = binaryDecode(base64Salt, "base64");
passBytes = charsetDecode(thePassword, theEncoding );
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
separateBytes = ArrayUtils.addAll( saltBytes, passBytes );
// concatenate first, THEN extract the bytes
theSalt = charsetEncode( binaryDecode(base64Salt, "base64"), theEncoding );
concatenatedBytes = charsetDecode( theSalt & thePassword, theEncoding );
// these are the raw bytes BEFORE hashing
WriteOutput("separateBytes= "& arrayToList(separateBytes, "|") &"<br>");
WriteOutput("concatenatedBytes"& arrayToList(concatenatedBytes, "|") );
</cfscript>
Results:
separateBytes = -6|107|-88|-22|0|38|-114|-5|-14|-53|-105|104|77|-40|-14|104|68|0|84|0|33|0|64|0|49|0|50|0
concatenatedBytes = -6|107|-88|-22|0|38|-114|-5|-14|-53|-105|104|-3|-1|68|0|84|0|33|0|64|0|49|0|50|0
Most likely the password is not encrypted, it is hashed. Hashing is different from encrypting, because it is not reversible.
You would not use ColdFusion's encrypt() function for this, you would use its hash() function.
So the questions you'll need to answer to figure out how to hash the passwords in CF to be able to auth against the DNN users are:
What algorithm is DNN using to hash the passwords?
How is the salt being used with the password prior to hashing?
Is DNN iterating over the hash X number of times to improve security?
All of those questions must be answered to determine how CF must use the hash() function in combination with the salt and user-submitted passwords.
I'll make some assumptions to provide an answer.
If we assume that noiteration is being done and that the salt is simply being appended to the password prior to using SHA1 to hash the password, then you'd be able to reproduce the hash digest like this:
<cfset hashDigest = hash(FORM.usersubmittedPassword & saltFromDB, "SHA1") />
(Posting a new response to keep the "encrypted" process separate from "hashing")
For "encrypted" keys, the DNN side uses the standard algorithms ie DES, 3DES or AES - depending on your machineKey settings. But with a few differences you need to match in your CF code. Without knowing your actual settings, I will assume you are using the default 3DES for now.
Data To Encrypt
The encrypted value is a combination of the salt and password. But as with hashing, DNN uses UTF-16LE. Unfortunately, ColdFusion's Encrypt() function always assumes UTF-8, which will produce a very different result. So you need to use the EncryptBinary function instead.
// sample valus
plainPassword = "password12345";
base64Salt = "x7le6CBSEvsFeqklvLbMUw==";
hexDecryptKey = "303132333435363738393031323334353637383930313233";
// first extract the bytes of the salt and password
saltBytes = binaryDecode(base64Salt, "base64");
passBytes = charsetDecode(plainPassword, "UTF-16LE" );
// next combine the bytes. note, the returned arrays are immutable,
// so we cannot use the standard CF tricks to merge them
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils");
dataBytes = ArrayUtils.addAll( saltBytes, passBytes );
Encryption Algorithm
With block ciphers, ColdFusion defaults to ECB mode. (See Strong Encryption in ColdFusion) Whereas .NET defaults to CBC mode, which requires an additional IV value. So you must adjust your CF code to match.
// convert DNN hex key to base64 for ColdFusion
base64Key = binaryEncode(binaryDecode( hexDecryptKey, "hex"), "base64");
// create an IV and intialize it with all zeroes
// block size: 16 => AES, 8=> DES or TripleDES
blockSize = 8;
iv = javacast("byte[]", listToArray(repeatString("0,", blocksize)));
// encrypt using CBC mode
bytes = encryptBinary(dataBytes, base64Key, "DESede/CBC/PKCS5Padding", iv);
// result: WBAnoV+7cLVI95LwVQhtysHb5/pjqVG35nP5Zdu7T/Cn94Sd8v1Vk9zpjQSFGSkv
WriteOutput("encrypted password="& binaryEncode( bytes, "base64" ));