Itextsharp Encryption without password is not working properly - vb.net

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...

Related

Compare hashed password vs searching for user with hashed value

Technically speaking is there any difference to these two login flows
The first:
Find user by email/username/etc.
Use a library like bcrypt to compare plain text password to hashed one
Return user if comparison true / return invalid credentials if comparison false
The second:
Hash the plain text password sent by user
Search for user by both the email and hashed password
If user found return him to the client / if user not found return invalid credentials

change password functionality in ATG

I am working on ATG11.2 , my requirement is as below:
User will click on forgot password button, a link with encoded user id and a temporary password will be sent to email. User will click on the link sent in email and will be redirected to ResetPassword.jsp where he will get an option to fill temporary password which is sent in email, new password and confirm password respectively
I am using ForgotPasswordHandler for this implementation. I have read that forgotpasswordhandler method replaces the password property with the new generated password. Therefore m storing the input box value of temporary password in ProfileFormHandler.value.oldpassword
The values are as below:
Temporary Password :
New Password:
ConfirmPassword
But , when I am debugging handleChangePassword method in ProfileForm it is not able to compare the passwords properly. Please suggest if my approach is correct , or what do I need to override in gmethod if any required.
ATG stores passwords in encrypted format.
You need to store your oldPassword in encrypted format too. The passwords will not be equal unless both the passwords are hashed and are same.

Webapplication log in system

I am using revel to build my webapplication and trying to write authentication module.
I finished with sign up part and now heading to write sign in part.
I read about security part on The definitive guide to form-based website authentication and will use this recommendation.
What I am really do not know is, how sign in works. I am imaging that the process works like this:
User write username and password into the html form and press sign in
Server receive request and the controller will check, if user information match with data on database.
If yes, how continue.
The third point is where I am staying. But I have some idea how could works and not sure, if is the right way.
So when sign in information match with the database, I would set in session object(hash datatype) key value pair signed_in: true. Everytime when the user make a request to the webapplication, that need to be authenticated, I would look in the session object, if signed_in is true or not.
This is the way I would do, but as I mentioned above, I do not know if it is the right way.
Yes like #twotwotwo mentioned, give it the user id and also a role.
So server side rendered flow: Step 1
user sends username (or other identifier) and secret.
using scrypt or bcrypt the secret is checked against the stored salted hash in the database
if it matches you create a struct or a map
serialize struct or map into string (json, msgpack, gob)
encrypt the string with AES https://github.com/gomango/utility/blob/master/crypto.go (for instance). Set a global AES key.
create a unique cookie (or session) identifier (key)
store identifier and raw struct or map in database
send encrypted cookie out (id = encrypted_struct_or_map aka the encrypted string)
On a protected resource (or page): Step 2
read identifier from cookie
check if id exists in db
decode cookie value using AES key
compare values from cookie with stored values
if user.role == "allowed_to_access_this_resource" render page
otherwise http.ResponseWriter.WriteHeader(403) or redirect to login page
Now if you wanted you could also have an application-wide rsa key and before encrypting the cookie value sign the string with the rsa private key (in Step 1). In Step 2 decode with AES key, check if signature valid, then compare content to db stored content.
On any changes you have to update the cookie values (struct/map) and the info in the database.

Apache basic auth, mod_authn_dbd and password salt

Using Apache mod_auth_basic and mod_authn_dbd you can authenticate a user by looking up that user's password in the database. I see that working if the password is held in clear, but what if we use a random string as a salt (also stored in the database) then store the hash of the concatenation?
mod_authn_dbd requires you to specify a query to select that password not to decide if the user is authenticated of not. So you cannot use that query to concatenate the user provided password with the salt then compare with the stored hash.
AuthDBDUserRealmQuery "SELECT password FROM authn WHERE user = %s AND realm = %s"
Is there a way to make this work?
Looking at the Password Formats for Basic Auth it seemed that I could make this work if the hash is done using the apr_md5_encode function.
Found another question that relates to this and links to a Java implementation. I used that implementation with a small change to calculate the database hash inside my website normal user-creation flow. After this i could use mod_authn_dbd with this query:
AuthDBDUserRealmQuery "SELECT CONCAT('$apr1$',password_salt,'$',password_hash) FROM users WHERE user = %s AND realm = %s"

How can I generate date-dependent 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.