So i look for simple answer, how to generate hash and salt for word protection option with docx4j library?
I got this method :
public static void setUpReadOnlyDocumentWithPassword(DocumentSettingsPart documentSettingsPart, String password) {
final CTSettings settings = Context.getWmlObjectFactory().createCTSettings();
final CTDocProtect protection = Context.getWmlObjectFactory().createCTDocProtect();
protection.setEdit(STDocProtect.READ_ONLY);
protection.setFormatting(true);
protection.setEnforcement(true);
protection.setCryptProviderType(STCryptProv.RSA_FULL);
protection.setCryptAlgorithmClass(STAlgClass.HASH);
protection.setCryptAlgorithmType(STAlgType.TYPE_ANY);
protection.setCryptAlgorithmSid(new BigInteger("4"));
protection.setCryptSpinCount(new BigInteger("100000"));
protection.setHash(?????);
protection.setSalt(?????);
settings.setDocumentProtection(protection);
documentSettingsPart.setJaxbElement(settings);
}
I really try everything, even translate C# code from http://social.msdn.microsoft.com/Forums/vstudio/en-US/63588f50-354f-43ba-b080-e0e6c51a0fb5/hash-and-saltdocumentprotection .
I want to full automate setting password to docx files.
These days, see https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/openpackaging/parts/WordprocessingML/DocumentSettingsPart.java#L333
Usually this is driven by https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/openpackaging/packages/ProtectDocument.java
Related
I want to make register page in php and make the password hashed with bcrypt and put in database.
I also want to make a login system in Java, and get the password in the same password, using jbcrypt.
How can I make jbcrypt and bcrypt in php compatible, with the same salt.
you can check out this:
https://github.com/ircmaxell/password_compat/issues/49
that's worked for me:
public static void main(String[] args) {
//Laravel bcrypt out
String hash_php = "$2y$10$ss9kwE8iSIqcJOAPhZR0Y.2XdYXJTFJ1/wGq6SUv74vULE7uhKUIO".replaceFirst("2y", "2a");
System.out.println("hash php " + hash_php);
//String a_hash = BCrypt.hashpw("123456", BCrypt.gensalt());
//System.out.println("Encrypt " + a_hash);
if (BCrypt.checkpw("123456", hash_php)) {
System.out.println("It matches");
} else {
System.out.println("It does not match");
}
//mtPruebaRecuperarClave();
}
Console - OutPut
I hope that's help You.
The problem is that PHP with it's password_hash() has it's own version scheme due to the fact that previous implementations had breaking bugs and it should be possible to recognize the old hashes.
So the version used by OpenBSD is $2a$ (will be $2b$ in future releases) and password_hash() uses $2y$ (previously $2x$), so of course the has will not match e.g.
$2y$10$ss9kwE8iSIqcJOAPhZR0Y.2XdYXJTFJ1/wGq6SUv74vULE7uhKUIO
vs
$2a$10$ss9kwE8iSIqcJOAPhZR0Y.2XdYXJTFJ1/wGq6SUv74vULE7uhKUIO
(see the wikipedia article about more info on the versions)
Currently jBcrypt (0.4) only supports $2a$.
There are 2 possibilities:
1. Replace the version identifier manually before passing it to jBcrypt (hack)
String hash_php = "$2y$10$ss9kwE8iSIqcJOAPhZR0Y.2XdYXJTFJ1/wGq6SUv74vULE7uhKUIO".replaceFirst("$2y$", "$2a$");
2. Using a different implemention supporting custom version identifier
This is the reason I implemented a new library for bcrypt (based on jBcrypt). https://github.com/patrickfav/bcrypt
Just use it like this (it does not verify for version per default, you can use verifyStrict() in that case)
BCrypt.Result result = BCrypt.verifyer().verify(password.toCharArray(), "$2y$10$ss9kwE8iSIqcJOAPhZR0Y.2XdYXJTFJ1/wGq6SUv74vULE7uhKUIO")
if(result.verified) {...}
If you want bcrypt to create $2y$ hashes:
String bcryptHash = BCrypt.with(BCrypt.Version.VERSION_2Y).hashToString(6, password.toCharArray());
// $2y$10$ss9kwE8iSIqcJOAPhZR0Y.2XdYXJTFJ1/wGq6SUv74vULE7uhKUIO
Full Disclaimer: Im the author of bcrypt
If you remove the first 7 chars from the hashes ($2y$10$ / $2a$10$) the rest should be the same regardless of the programming language you have used. The first characters of the generated hash is a prefix that tells more about the hash algorithm.
In your example, the $2y$ and $a2$ are defining the algorithm of the hash, and the 10$ is the "cost" of the hash generation (how many times the hash algorithm was repeatedly applied or something like this).
If you want to learn more about the prefixes in the bcrypt generated hashes, read this article.
I have a MySQL database where one column is used to store password.
It is implemented in PHP, using password_hash() to salt and hash the original password on registering, and retrieving the MySQL row of the logging-in user and then password_verify() its password.
But I need to move it in Java. So are there Java equivalents for password_hash() and password_verify()?
You can use the implementation by mindrot:
https://www.mindrot.org/projects/jBCrypt/
To replicate the password_hash you can use:
String hash = BCrypt.hashpw("password");
And to replicate password_verify use:
boolean s = BCrypt.checkpw("password", hash);
This works great with my Laravel project.
I made a few tweaks to the lib, to allow the use of a random salt, instead of passing a new one each time you call hashpw method, and to support multiple versions of salt.
You can find it here: https://github.com/promatik/jBCrypt
Use this:
https://mvnrepository.com/artifact/at.favre.lib/bcrypt
Code example:
import at.favre.lib.crypto.bcrypt.*;
import at.favre.lib.bytes.Bytes;
import java.nio.charset.StandardCharsets;
...
String pw = "candidate_password";
String hash = "<hash from users table>";
BCrypt.Result result = BCrypt.verifyer(BCrypt.Version.VERSION_2Y)
.verifyStrict(pw.getBytes(StandardCharsets.UTF_8), hash.getBytes(StandardCharsets.UTF_8));
if (result.verified) {
System.out.println(" It matches");
} else {
System.out.println(" It does not match");
}
...
I thought about repurposing org.eclipse.jface.bindings.Scheme to store key bindings on a per user base:
String userName = "Bob";
BindingManager bindingManager = ((BindingService) PlatformUI.getWorkbench().getService(IBindingService.class)).getBindingManager();
Scheme scheme = bindingManager.getScheme(userName);
scheme.define(userName, "Scheme for user " + userName, DEFAULT_SCHEME);
bindingManager.setActiveScheme(scheme);
Which works well for some moments, but whenever the schemes get loaded from the preferences (e.g. via CommandPersistence#reRead) only the schemes defined in the plugin.xml will be read and everything else gets discarded.
Especially this method of the class BindingService is a problem:
public final void savePreferences(final Scheme activeScheme,
final Binding[] bindings) throws IOException {
// store everything in preferences, then read everything
// -> custom schemes get removed
BindingPersistence.write(activeScheme, bindings);
// now the removed (undefined) scheme gets set
bindingManager.setActiveScheme(activeScheme);
bindingManager.setBindings(bindings);
}
Since I can't really register all users via plugin.xml, how can I register schemes programmatically?
As a "solution", I just re-implemented the scheme for our use case:
String userName = "Bob";
String keyBindings = MyPlugin.getDefault().getPreferenceStore().getString("keyBindings." + userName);
PlatformUI.getPreferenceStore().setValue(PlatformUI.PLUGIN_ID + ".commands", keyBindings);
This triggers CommandPersistence#reRead as well, but since I don't have my custom scheme this time, it doesn't fail. Now the management of our different schemes is our problem, but at least that way it works.
I'm developing a web app that let users reset their own passwords in Active Directory. I've been doing it by binding as an administrator and it works fine, but the directory policies (reuse history, characters, etc) are not being enforced. I can't bind as a user because I don't have the current password.
I read about the LDAP_SERVER_POLICY_HINTS control introduced in Windows 2008 R2 SP1 for doing that in Active Directory and even found someone who made it using Spring LDAP
Since I'm using UnboundID and there is no standard control shipped for that, I figured that I had to create my own control class. The documented OID is 1.2.840.113556.1.4.2239 and the value {48, 3, 2, 1, 1}
public class PolicyHintsControl extends Control {
private static final long serialVersionUID = 1L;
public final static String LDAP_SERVER_POLICY_HINTS_OID = "1.2.840.113556.1.4.2066";
public final static byte[] LDAP_SERVER_POLICY_HINTS_DATA = { 48,
(byte) 132, 0, 0, 0, 3, 2, 1, 1 };
public PolicyHintsControl() {
super(LDAP_SERVER_POLICY_HINTS_OID, false, new ASN1OctetString(
LDAP_SERVER_POLICY_HINTS_DATA));
}
#Override
public String getControlName() {
return "LDAP Server Policy Hints Control";
}
#Override
public void toString(StringBuilder buffer) {
buffer.append("LDAPServerPolicyHints(isCritical=");
buffer.append(isCritical());
buffer.append(')');
}
}
So I added this new control in the modify request like this:
public static void main(String[] args) throws Exception {
final String host = "ldap.example.com";
final int port = 636;
String adminDn = "admin#example.com";
String adminPassword = "passwd";
String userDn = "CN=user,ou=people,dc=example,dc=com";
String userPassword = "passwd";
String keystoreFile = "/path/to/keystore.jks";
String keystorePassword = "passwd";
String passwordAttribute = "unicodePwd";
//Password change requires SSL
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keystoreFile), keystorePassword.toCharArray());
TrustManagerFactory factory = TrustManagerFactory.getInstance("x509");
factory.init(keyStore);
final SSLUtil sslUtil = new SSLUtil(factory.getTrustManagers());
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
Debug.setEnabled(true);
// Connect as the configured administrator
LDAPConnection ldapConnection = new LDAPConnection(socketFactory, host,
port, adminDn, adminPassword);
// Set password in AD format
final String newQuotedPassword = "\"" + userPassword + "\"";
final byte[] newPasswordBytes = newQuotedPassword.getBytes("UTF-16LE");
String encryptedNewPwd = new String(newPasswordBytes);
//Build modifications array and request
final ArrayList<Modification> modifications = new ArrayList<Modification>();
modifications.add(new Modification(ModificationType.REPLACE,
passwordAttribute, encryptedNewPwd));
ModifyRequest modifyRequest = new ModifyRequest(userDn, modifications);
//Add the policy hints control
modifyRequest.addControl(new PolicyHintsControl());
//Modify already
ldapConnection.modify(modifyRequest);
ldapConnection.close();
}
I get the following exception:
Exception in thread "main" LDAPException(resultCode=53 (unwilling to perform), errorMessage='0000052D: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
', diagnosticMessage='0000052D: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
')
After researching a bit more I found that there was another update in Windows 2012 for the same control which changed the OID to 1.2.840.113556.1.4.2066 and deprecated the old OID.
Since this app can be configured with any version of AD I'd like to handle gracefully every scenario (Windows 2012, Windows 2008 R2 SP1, others). My questions are:
Does anyone have successfully done this with UnboundID?
Is there anyway to know if the controls are available before the modification request?
What would be the best way to handle different OID's for different versions of AD for the same control? Same class or different classes?
I'm not all that familiar with Microsoft-specific controls so I can't provide a lot of help there, but it looks like you're already on the right track with that. In this case, it actually looks like the control is working as expected and the server is rejecting the password because it's not strong enough.
Active Directory is really awful with how hard it makes it to figure things like this out, but the secret lies in the "0000052D" given in the diagnostic message. That is a reference to Active Directory system error code 0x52D, which is decimal 1325. System error codes are documented at http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx, and in this case you need to follow the "System Error Codes (1300-1699)" link (http://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx) and find the description for value 1325. The text for that error code says "Unable to update the password. The value provided for the new password does not meet the length, complexity, or history requirements of the domain." Since the point of the control you're trying to use seems to be to cause the server to perform quality checking on the new password, it looks like it's working as expected. If you use a stronger password (e.g., make it longer, include uppercase/numeric/symbol characters, etc.) then perhaps the server will accept it.
With regard to your question about figuring out what controls the server supports, the way to do that is to retrieve the server root DSE and look at the OIDs reported in the supportedControls attribute. The UnboundID LDAP SDK for Java makes this pretty easy because you can use the LDAPConnection.getRootDSE method to retrieve the root DSE, and then the RootDSE.supportsControl method to determine whether the server supports the specified control.
With regard to your question about whether to handle different OIDs with the same class or different classes, that's more a matter of style than anything else. If the control with the newer OID also uses a different encoding for the value, then that would definitely suggest making a separate class. If the value encoding is the same for both OIDs, then it's probably a matter of personal preference but even if you make them separate classes then it would be good to keep the majority of the code common rather than having the same code in two different places.
I am using Jasypt for encryption. This is my code:
public class Encryptor {
private final static StandardPBEStringEncryptor pbeEncryptor = new StandardPBEStringEncryptor();
private final static String PASSWORD = "FBL";
private final static String ALGORITHM = "PBEWithMD5AndTripleDES";
static{
pbeEncryptor.setPassword( PASSWORD );
//pbeEncryptor.setAlgorithm( ALGORITHM );
}
public static String getEncryptedValue( String text ){
return pbeEncryptor.encrypt( text );
}
public static String getDecryptedValue( String text ){
return pbeEncryptor.decrypt( text );
}
}
Uncomment the setAlgorithm line and it will throw an exception
org.jasypt.exceptions.EncryptionOperationNotPossibleException:
Encryption raised an excep tion. A
possible cause is you are using strong
encryption algorithms and you have not
installed the Java Cryptography Ex
tension (JCE) Unlimited Strength
Jurisdiction Policy Files in this Java
Virtual Machine
api says:
Sets the algorithm to be used for
encryption Sets the algorithm to be
used for encryption, like
PBEWithMD5AndDES.
This algorithm has to be supported by
your JCE provider (if you specify one,
or the default JVM provider if you
don't) and, if it is supported, you
can also specify mode and padding for
it, like ALGORITHM/MODE/PADDING.
refer: http://www.jasypt.org/api/jasypt/apidocs/org/jasypt/encryption/pbe/StandardPBEStringEncryptor.html#setAlgorithm%28java.lang.String%29
Now, when you comment 'setAlgorithm' it will use the default Algorithm [ i guess it is md5 ], and it will work fine. That means md5 is supported by my JVM. Now, how to find out what other encryption algorithms are supported by my JVM.
Thanks,
The following will list all the providers and the algorithms supporter. What version of Java are you using? Unless you're on an old version JCE should be included as standard.
import java.security.Provider;
import java.security.Security;
public class SecurityListings {
public static void main(String[] args) {
for (Provider provider : Security.getProviders()) {
System.out.println("Provider: " + provider.getName());
for (Provider.Service service : provider.getServices()) {
System.out.println(" Algorithm: " + service.getAlgorithm());
}
}
}
}
Edit:
Any reason why you don't use the standard stuff from the javax.crypto package?
1) Generate a Key using
Key key = SecretKeyFactory.getInstance(algorithm).generateSecret(new PBEKeySpec(password.toCharArray()));
2) Create a Cipher using
cipher = Cipher.getInstance(algorithm);
3) Init your cipher with the key
cipher.init(Cipher.ENCRYPT_MODE, key);
4) Do the encrypting with
byte[] encrypted = cipher.doFinal(data)
The Jasypt command line tool now comes with a script for doing this called listAlgorithms.bat for windows and listAlgorithms.sh for Linux.
You can find instructions on how to download and use it here: http://www.jasypt.org/cli.html#Listing_algorithms
If you don't have it installed already, then you need to install the JCE (Java Cryptography Extension) which provides support for the algorithms.
You can see how to install here:
http://download.oracle.com/javase/1.4.2/docs/guide/security/CryptoSpec.html#ProviderInstalling
The library can be found here:
http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html
I tried the code posted by #Qwerky, but it's not very helpful. I had added the latest BouncyCastle provider, and the results I got were very confusing. This shows in better detail who's the provider, version, and the algorithm type and name.
for (Provider provider : Security.getProviders()) {
System.out.println("Provider: " + provider.getName() + " version: " + provider.getVersion());
for (Provider.Service service : provider.getServices()) {
System.out.printf(" Type : %-30s Algorithm: %-30s\n", service.getType(), service.getAlgorithm());
}
}
There is still a 'pending' question asked by Qwerky: why using Jasypt instead of using javax.crypto?
Well, I would recommend using Jasypt as it is a simple way to crypto for beginners and highly configurable for experienced users.
With Jasypt, you can start taking benefit of javax.crypto quickly with a little knowledge of JCE and the cryptography. Whether you want to manage user passwords or encrypt/decrypt data, the framework provides a simple abstraction to the question.
In the same time, the framework exposes all the possibilities of the JCE specification to allow experienced users to be in full control.
In addition to this, Jasypt provides many more features out-of-the-box for well known questions (dealing with sensitive data stored in the database, ...)
Using Java 8 and above,
Stream.of(Security.getProviders()).flatMap(mapper -> Stream.of(mapper.getServices())).flatMap(Set::stream)
.map(Provider.Service::getAlgorithm).distinct().sorted().forEach(System.out::println);