1 package org.eclipse.aether.util.repository;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Arrays;
23 import java.util.Map;
24
25 import org.eclipse.aether.repository.Authentication;
26 import org.eclipse.aether.repository.AuthenticationContext;
27 import org.eclipse.aether.repository.AuthenticationDigest;
28
29
30
31
32
33
34 final class SecretAuthentication
35 implements Authentication
36 {
37
38 private static final Object[] KEYS;
39
40 static
41 {
42 KEYS = new Object[16];
43 for ( int i = 0; i < KEYS.length; i++ )
44 {
45 KEYS[i] = new Object();
46 }
47 }
48
49 private final String key;
50
51 private final char[] value;
52
53 private final int secretHash;
54
55 public SecretAuthentication( String key, String value )
56 {
57 this( ( value != null ) ? value.toCharArray() : null, key );
58 }
59
60 public SecretAuthentication( String key, char[] value )
61 {
62 this( copy( value ), key );
63 }
64
65 private SecretAuthentication( char[] value, String key )
66 {
67 if ( key == null )
68 {
69 throw new IllegalArgumentException( "authentication key missing" );
70 }
71 this.key = key;
72 this.secretHash = Arrays.hashCode( value ) ^ KEYS[0].hashCode();
73 this.value = xor( value );
74 }
75
76 private static char[] copy( char[] chars )
77 {
78 return ( chars != null ) ? chars.clone() : null;
79 }
80
81 private char[] xor( char[] chars )
82 {
83 if ( chars != null )
84 {
85 int mask = System.identityHashCode( this );
86 for ( int i = 0; i < chars.length; i++ )
87 {
88 int key = KEYS[( i >> 1 ) % KEYS.length].hashCode();
89 key ^= mask;
90 chars[i] ^= ( ( i & 1 ) == 0 ) ? ( key & 0xFFFF ) : ( key >>> 16 );
91 }
92 }
93 return chars;
94 }
95
96 private static void clear( char[] chars )
97 {
98 if ( chars != null )
99 {
100 for ( int i = 0; i < chars.length; i++ )
101 {
102 chars[i] = '\0';
103 }
104 }
105 }
106
107 public void fill( AuthenticationContext context, String key, Map<String, String> data )
108 {
109 char[] secret = copy( value );
110 xor( secret );
111 context.put( this.key, secret );
112
113 }
114
115 public void digest( AuthenticationDigest digest )
116 {
117 char[] secret = copy( value );
118 try
119 {
120 xor( secret );
121 digest.update( key );
122 digest.update( secret );
123 }
124 finally
125 {
126 clear( secret );
127 }
128 }
129
130 @Override
131 public boolean equals( Object obj )
132 {
133 if ( this == obj )
134 {
135 return true;
136 }
137 if ( obj == null || !getClass().equals( obj.getClass() ) )
138 {
139 return false;
140 }
141 SecretAuthentication that = (SecretAuthentication) obj;
142 if ( !eq( key, that.key ) || secretHash != that.secretHash )
143 {
144 return false;
145 }
146 char[] secret = copy( value );
147 char[] thatSecret = copy( that.value );
148 try
149 {
150 xor( secret );
151 that.xor( thatSecret );
152 return Arrays.equals( secret, thatSecret );
153 }
154 finally
155 {
156 clear( secret );
157 clear( thatSecret );
158 }
159 }
160
161 private static <T> boolean eq( T s1, T s2 )
162 {
163 return s1 != null ? s1.equals( s2 ) : s2 == null;
164 }
165
166 @Override
167 public int hashCode()
168 {
169 int hash = 17;
170 hash = hash * 31 + key.hashCode();
171 hash = hash * 31 + secretHash;
172 return hash;
173 }
174
175 @Override
176 public String toString()
177 {
178 return key + "=" + ( ( value != null ) ? "***" : "null" );
179 }
180
181 }