1313import javax .security .sasl .SaslException ;
1414import java .io .IOException ;
1515import java .io .UnsupportedEncodingException ;
16- import java .security .MessageDigest ;
17- import java .security .NoSuchAlgorithmException ;
1816import java .util .Arrays ;
1917
2018/**
19+ Provides equivalent security to PLAIN but demos use of Connection.Secure(Ok)
2120 START-OK: Username
22- SECURE: {Salt1, Salt2} (where Salt1 is the salt from the db and
23- Salt2 differs every time)
24- SECURE-OK: md5(Salt2 ++ md5(Salt1 ++ Password))
25-
26- The second salt is there to defend against replay attacks. The
27- first is needed since the passwords are salted in the db.
28-
29- This is only somewhat improved security over PLAIN (if you can
30- break MD5 you can still replay attack) but it's better than nothing
31- and mostly there to prove the use of SECURE / SECURE-OK frames.
21+ SECURE: "Please tell me your password"
22+ SECURE-OK: Password
3223*/
3324
34- public class ScramMD5SaslClient implements SaslClient {
35- private static final String NAME = "RABBIT-SCRAM-MD5 " ;
25+ public class CRDemoSaslClient implements SaslClient {
26+ private static final String NAME = "RABBIT-CR-DEMO " ;
3627
3728 private CallbackHandler handler ;
3829 private int round = 0 ;
3930
40- public ScramMD5SaslClient (CallbackHandler handler ) {
31+ public CRDemoSaslClient (CallbackHandler handler ) {
4132 this .handler = handler ;
4233 }
4334
@@ -57,12 +48,9 @@ public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
5748 handler .handle (new Callback []{nc });
5849 resp = nc .getName ().getBytes ("utf-8" );
5950 } else {
60- byte [] salt1 = Arrays .copyOfRange (challenge , 0 , 4 );
61- byte [] salt2 = Arrays .copyOfRange (challenge , 4 , 8 );
6251 PasswordCallback pc = new PasswordCallback ("Password:" , false );
6352 handler .handle (new Callback []{pc });
64- byte [] pw = new String (pc .getPassword ()).getBytes ("utf-8" );
65- resp = digest (salt2 , digest (salt1 , pw ));
53+ resp = new String (pc .getPassword ()).getBytes ("utf-8" );
6654 }
6755 } catch (UnsupportedEncodingException e ) {
6856 throw new RuntimeException (e );
@@ -96,32 +84,16 @@ public void dispose() throws SaslException {
9684 // NOOP
9785 }
9886
99- private static byte [] digest (byte [] arr1 , byte [] arr2 ) {
100- try {
101- MessageDigest digest = MessageDigest .getInstance ("MD5" );
102- return digest .digest (concat (arr1 , arr2 ));
103-
104- } catch (NoSuchAlgorithmException e ) {
105- throw new RuntimeException (e );
106- }
107- }
108-
109- private static byte [] concat (byte [] first , byte [] second ) {
110- byte [] result = Arrays .copyOf (first , first .length + second .length );
111- System .arraycopy (second , 0 , result , first .length , second .length );
112- return result ;
113- }
114-
115- public static class ScramMD5SaslConfig implements SaslConfig {
87+ public static class CRDemoSaslConfig implements SaslConfig {
11688 private ConnectionFactory factory ;
11789
118- public ScramMD5SaslConfig (ConnectionFactory factory ) {
90+ public CRDemoSaslConfig (ConnectionFactory factory ) {
11991 this .factory = factory ;
12092 }
12193
12294 public SaslClient getSaslClient (String [] mechanisms ) throws SaslException {
12395 if (Arrays .asList (mechanisms ).contains (NAME )) {
124- return new ScramMD5SaslClient (new UsernamePasswordCallbackHandler (factory ));
96+ return new CRDemoSaslClient (new UsernamePasswordCallbackHandler (factory ));
12597 }
12698 else {
12799 return null ;
0 commit comments