Friday, March 13, 2015

HMAC then BCrypt Passwords for a little extra security

HMAC then BCrypt (also known as Peppering) of user passwords can help in the following scenarios:

Scenario 1: Hacker steals your user database, but does not compromise your web server

Scenario 2: Hacker can run SQL Injection on your web server, but can otherwise not gain access to the web server process

Scenario 3: You can keep your HMAC key in a Hardware Security Module

How it works:

1. "Sign" user's password using HMAC and a key known only to the web server (do NOT store this key in the database)

2. BCrypt the signed user's password

This also has the advantage of allowing longer passwords (BCrypt has a limit of around 70 chars).

See https://blog.mozilla.org/webdev/2012/06/08/lets-talk-about-password-storage/ 

A HMAC then BCrypt password encoder for Spring Security:



public class PepperingPasswordEncoder implements PasswordEncoder {

    private final PasswordEncoder actualEncoder;

    private final Mac mac;

    public PepperingPasswordEncoder(final PasswordEncoder actualEncoder, final String key) throws InvalidKeyException, NoSuchAlgorithmException {
        this(actualEncoder, key, "HMacSha1");
    }

    public PepperingPasswordEncoder(final PasswordEncoder actualEncoder, final String key, final String algorithm) throws InvalidKeyException, NoSuchAlgorithmException {
        this.actualEncoder = actualEncoder;

        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);
        mac = Mac.getInstance(algorithm);
        mac.init(keySpec);
    }

    @Override
    public String encode(final CharSequence charSequence) {
        return actualEncoder.encode(hmac(charSequence));
    }

    public String hmac(final CharSequence value) {
        return hmac(value.toString());
    }

    public String hmac(final String value) {
        return new String(Base64.encode(mac.doFinal(value.getBytes())));
    }

    @Override
    public boolean matches(final CharSequence rawPassword, final String encodedPassword) {
        return actualEncoder.matches(hmac(rawPassword), encodedPassword);
    }
}


In applicationContext-security.xml:

    <beans:bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="bCryptPasswordEncoder" />

    <beans:bean class="com.databasepatterns.spring.security.PepperingPasswordEncoder" id="passwordEncoder">
        <beans:constructor-arg ref="bCryptPasswordEncoder"/>
        <beans:constructor-arg value="mykey"/>
    </beans:bean>

    <authentication-manager>
        <authentication-provider>
            <password-encoder ref="passwordEncoder"/>
            ...
        </authentication-provider>
    </authentication-manager>

1 comment:

Sam Maron said...

Virtual data room has an in-built file encryption system that prevents data getting leaked while being transferred. Besides all this, the VDR will even scan your files and documents for viruses.
data room providers comparison