How can I generate date-dependent passwords? - passwords

I'm looking for a simple way to generate passwords that will only work once for a limited amount of time, e.g. 1 day, 1 week, 1 month. This has to be implemented in an application that has no connectivity so a server isn't possible. The use case is something like:
1. Generate password for a specific date and length of time.
2. Send to user (email, phone, etc).
3. User enters in application.
4. Application is enabled for a specific time.
5. Password cannot be reused, even on another PC.
I'm assuming the only way to do this is to generate passwords that only work between a specific set of dates. Can anyone recommend an algorithm that can do this? It doesn't have to be incredibly secure, and I know you can crack this by resetting the time on the PC!
Thanks.

I know I'm late but I'll provide my advice anyway in case someone else who needs it found their way here.
To prevent it being used on another PC, you could probably use the MAC address or hardware address. However, this is subject to the network hardware being still available when checking the password. Please make sure you use the hardware address of the machine where the password will be checked.
private string GetBase64Mac()
{
System.Net.NetworkInformation.NetworkInterface[] interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
if (interfaces.Length == 0)
{
System.Net.NetworkInformation.PhysicalAddress add = interfaces[0].GetPhysicalAddress();
if (add != null)
return System.Convert.ToBase64String(add.GetAddressBytes());
}
return "";
}
To limit it by some expiry date simply use the text string of the expiry date.
private string GetExpiryDate(DateTime expiryDate)
{
return expiryDate.ToString("yyyyMMdd");
}
Simply use a hash function to hash the combine expiry date, hardware address and a secret key. Prefix or suffix the hash output with the expiry date.
private void GeneratePassword(string prefix)
{
string secretKey = "MySecretKey";
System.Security.Cryptography.SHA1 sha = System.Security.Cryptography.SHA1.Create();
byte[] preHash = System.Text.Encoding.UTF32.GetBytes(prefix + secretKey + GetBase64Mac());
byte[] hash = sha.ComputeHash(preHash);
string password = prefix + System.Convert.ToBase64String(hash);
return password;
}
In the case above, i prefix the hash with the expiry date. So, when we check the password, we simply extract the expiry date from the password, use the same function to generate the same password. If the generated password match the provided password, then you have green light.
private void TestPassword()
{
int duration = 15; // in days
string prefix = GetExpiryDate(DateTime.Today.AddDays(duration));
string generated = GeneratePassword(prefix);
// Positive test
string testPrefix = generated.Substring(0, 8);
string testPassword = GeneratePassword(testPrefix);
if (generated != TestPassword)
return false;
// Negative test
generated[2] = '2';
generated[12] = 'b';
testPrefix = generated.Substring(0, 8);
testPassword = GeneratePassword(testPrefix);
if (generated != TestPassword)
return true;
return false;
}
Sample output password:
20110318k3X3GEDvP0LkBN6zCrkijIE+sNc=
If you can't get the hardware address, then simply use the customer's name. It won't prevent the password from being used in multiple machines, but it will ensure that the same person is using it.

Your application should have a attribute like validity for the password something like this
username password_hash validity_from Validity_end
xyz a73839$56 11-Nov-2010 12-Nov-2010
and then in your application you can validate that your password has expired or not

Generate passwords by any method you'd like (a word list, random letters, etc). Put them into some data structure, like an associative array, where you can associate a date with each password. Then you consult this data structure in the program that hands out passwords to give one out with the proper expiration date. The client program has the same list of passwords and dates, so when it gets a password, it just looks up the associated expiration date there.

Related

Itextsharp Encryption without password is not working properly

I am trying to use itextsharp writer.setEncryption method with nothing to encrypt file without password but it is setting password for some random pdf even if I have passed nothing to encrypt it.
pdf.SetEncryption(Nothing, Nothing, PdfWriter.AllowScreenReaders, PdfWriter.STRENGTH40BITS)
It is working properly.
Please have a look at the documentation of the method you used:
/** Sets the encryption options for this document. The userPassword and the
* ownerPassword can be null or have zero length. In this case the ownerPassword
* is replaced by a random string. The open permissions for the document can be
* AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
* AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
* The permissions can be combined by ORing them.
* #param userPassword the user password. Can be null or empty
* #param ownerPassword the owner password. Can be null or empty
* #param permissions the user permissions
* #param strength128Bits <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
* #throws DocumentException if the document is already open
*/
virtual public void SetEncryption(byte[] userPassword, byte[] ownerPassword, int permissions, bool strength128Bits)
So if you don't give a value for the owner password, the documented behavior is that a random string is used, exactly as you observed.
Apparently you try to set the permissions of the PDF to only PdfWriter.AllowScreenReaders, but setting this permission selection is only possible for encrypted files, and for encryption a non-empty owner password is required, so iText chooses one for you.
An empty user password on the other hand is possible because in the course of its use during encryption and decryption a "default password string" is appended to the user password value anyways.
Addendum
In answer to questions in comments...
What does "is replaced by a random string" mean exactly? And in what format would that password be?
if (ownerPassword == null || ownerPassword.Length == 0)
ownerPassword = DigestAlgorithms.Digest("MD5", CreateDocumentId());
(PdfEncryption method SetupAllKeys)
where CreateDocumentId is defined like this:
public static byte[] CreateDocumentId() {
long time = DateTime.Now.Ticks + Environment.TickCount;
long mem = GC.GetTotalMemory(false);
String s = time + "+" + mem + "+" + (seq++);
byte[] b = Encoding.ASCII.GetBytes(s);
return DigestAlgorithms.Digest("MD5", b);
}
Can you still retrieve the password somehow?
The password is not explicitly stored anywhere for later retrieval. In this situation, i.e. a call for encryption using an empty owner password, it is assumed that the caller is not interested in knowing the password.
If this sounds weird to you, please be aware that for the actual encryption of document data the user password is used, not the owner password. (More exactly a value derived from the user password.) The owner password during document encryption only is used to encrypt the user password (more exactly, a value derived from it) and store that value in the PDF.
When the PDF is opened again and the user provides a password, it is tested whether it can immediately be used for document data decryption (i.e. it is the user password) or whether it can be used to decrypt the above mentioned value to the user password which then can decrypt the document (i.e. it is the owner password).
In either case the user has access to the PDF but if it was only the user password, not the owner password, the PDF processor is expected to restrict the allowed operations according to a given permissions value.
Thus, a caller not giving an owner password here is interpreted to be not interested in anyone having full access to the PDF in a specification conforming PDF processor, for restricted access the user password suffices. This has nothing to do with making the document undecryptable due to a lost password...
Would it use one of the indicated key strengths?
Well, MD5 returns a 128 bit hash but as the structure of the hashed data is well known, the password is by far not as strong as a truly random 128 bis value. On the other hand an eight character string usually also is by far not as strong as that...

password History for Identity Core

is there any default implementation for password history? i'm trying to implement that feature on my project with identity so i have added password history table which contain password hashes. when user change password usermanager generate hash for password.
var passwordHash = _userManager.PasswordHasher.HashPassword(user, newPassword);
if this hash does not inserted in password history table it allow to change password otherwise return error
but the problem is each time when generating hash for the specific password it generate random hashes which cannot be compare also
var passwordHash = _userManager.PasswordHasher.HashPassword(user, newPassword);
hash differ from
_userManager.ResetPasswordAsync(user, request.Token, password);
generated password hash.
May be i'm trying to do this in wrong way. what was the mistake i have done implementing password history?
thanks
Different hashes every time - it's how default implementation IPasswordHasher works. Look at this answer for more details: https://stackoverflow.com/a/20622428/6104621.
So, for your implementation password history, you can either implement IPasswordHasher or just verify a new password with all stored passwords hashes using method
PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword);
Just for example:
var passAlreadyExist = user.UserHistory
.Select(h => h.PasswordHash)
.Distinct()
.Any(hash =>
{
var res = manager.PasswordHasher.VerifyHashedPassword(user, hash, password);
return res == PasswordVerificationResult.Success;
});
where UserHistory - it's custom table with some user info like password, email, name...

AspNet Identity UserManager Find with Select (optimal sql query)

I have wcf fulRest service with AspNet Identity. My android app use this web service to communicate with database - I use ssl to make connection secure (my app is a mini game so it doesn't contain so important data, I belive that ssl is enough protection in this case).
I have function LoginUser(string userName, string unHashedPassword), if user exsists it returns user's id. In all other functions this id is used if action need information of curUser - for example I have function addComment(string userId, string msg) (this kind of methods still use ssl to protection of unwanted handle userId).
In LoginUser I get id (and a little more information like e-mail, gameLogin) by use:
using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(_context)))
{
ApplicationUser user = userManager.Find(userName, password);
if (user != null)
{
result = new LogInBaseData()
{
Id = user.Id,
Email = user.Email,
Login = user.ApplicationLogin
};
}
}
But function Find generate huge query with select many unneeded data for me. Is any way to optimalizace it? I prefer do it by context.User.Where().Select() but I can't hash user's password.

Docebo Api Integration

I am facing an issue with implementing the API to authorize the user and make a session and launch a course.
All the full steps like making a token and passing it with REST API has been done and in the response I am receiving the success in the response token.
Now the issue is that when I am trying opening a course link, it redirects me to the login page despite landing on course. Can you please help set up a session and let me know which API is to be used to make a session so that it doesn't redirects me to the login page.
For those still looking for an answer, I'll show you how to generate a temporary link that will authorize a user and direct them to the desired location in Docebo.
Things you need:
The username.
The SSO secret for the token hash.
-In Docebo: Click APPS and Features on left-hand side. Click Third party integrations. Activate API and SSO, if not already activated. After API and SSO is active, click on its gear icon. Click the check box that starts with "Enable SSO with...". Enter a SSO secret in the box below the checkbox. Save.
Now, for the implementation. I myself used C# for this but hopefully it will be easily translatable to your language of choice (or lack of choice).
The basic idea is this:
1) Create an MD5 hash of three values:
(NOTE: Include commas between the values when generating the hash. Example further below...)
username(lowercase!!!)
time = Seconds since the Unix Epoch in utc.
SSO secret (the one you typed yourself).
2) Get the hex value of the hash.
3) Combine the destination url with the username, time, and hex. Like so:
http[s]://[yourdomain]/lms/index.php?r=site/sso&login_user=[username]&time=[utc
time]&token=[token]{&id_course=[id_course]}{&destination=[destination]}
For my example, I didn't specify a course or a destination.
Here is the above gibberish, in C#:
public string GenerateDoceboSSOLink()
{
string userName = "johnsmith"; //Note the lowercase!!
string domain = "http://my-test.docebosaas.com";
string ssoSecret = "MySSOSecret";
//Getting the seconds since the Unix Epoch
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
int time = (int)t.TotalSeconds;
//Creating the hash...
MD5 md5 = System.Security.Cryptography.MD5.Create();
//Note the inclusion of the commas!
string input = userName + "," + time + "," + ssoSecret;
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
//Getting the hex value of the hash.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
string token = sb.ToString(); //the hex value, which we will call token
//The sso link.
string link = String.Format("{0}/lms/index.php?r=site/sso&login_user={1}&time={2}&token={3}", domain, userName, time, token);
return link;
}
So, I followed this
impossible-to-find documentation that led me to what you see above (I couldn't find the url so I just shared it).

Can I uniquely identify a device in Windows 10/Windows 8/WinRT

Is there any mechanism to identify a device uniquely (even if it is anonymous)?
To be clear, by "device" I mean the computer/slate/pc.
Windows 8.x
http://codepaste.net/ybt893
string HardwareId()
{
var token = Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null);
var hardwareId = token.Id;
var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);
var bytes = new byte[hardwareId.Length];
dataReader.ReadBytes(bytes);
return BitConverter.ToString(bytes);
}
Windows 10
You must add the Mobile and/or Desktop extension SDK.
string HardwareId()
{
var token = HardwareIdentification.GetPackageSpecificToken(null);
var hardwareId = token.Id;
var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);
var bytes = new byte[hardwareId.Length];
dataReader.ReadBytes(bytes);
return BitConverter.ToString(bytes);
}
Such an ability has just been added in Windows 8 RTM:
Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null)
There doesn't seem to be a convenient way for Metro Style apps in Windows 8 to obtain a system-maintained unique identifier, like Windows Phone 7 provided with its Microsoft.Phone.Info.DeviceExtendedProperties.GetValue( "DeviceUniqueId" )
http://social.msdn.microsoft.com/Forums/en-HK/winappswithcsharp/thread/62ac2a48-be60-465c-b3b7-bbb736a67a60
http://social.msdn.microsoft.com/Forums/en-NZ/winappswithcsharp/thread/2ca0d5de-9db5-4349-839c-e01ff614ec6e
The best solution I've found so far is to simply generate a new guid in application local storage and use that identifier to identify the computer for the current and future launches of your app.
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Object value = localSettings.Values["uniqueDeviceId"];
if (!value)
{
value = Guid.NewGuid();
localSettings.Values["uniqueDeviceId"] = value;
}
Keep in mind that the user could delete the local storage and cause your app to forget and regenerate that value (or potentially even modify/spoof the value), so don't depend on it for any critical security purposes. Since I'm only using this technique for rough statistics and usage reporting, this is fine for my needs.
Could this be used as a consistent ID for the logged in user?
http://msdn.microsoft.com/en-us/library/windows/apps/windows.security.exchangeactivesyncprovisioning.easclientdeviceinformation.id.aspx
EasClientDeviceInformation.Id | id property
Returns the identifier of the local computer. The Id property represents the DeviceId using the GUID truncated from the first 16 bytes of the SHA256 hash of MachineID, User SID, and App ID where the MachineID uses the SID of the local users group. Each component of the GUID is returned in network byte order.