2121import com .fasterxml .jackson .core .type .TypeReference ;
2222import com .fasterxml .jackson .databind .ObjectMapper ;
2323import java .io .File ;
24+ import java .io .FileInputStream ;
2425import java .io .IOException ;
2526import java .nio .file .Files ;
2627import java .nio .file .Paths ;
28+ import java .security .MessageDigest ;
29+ import java .security .NoSuchAlgorithmException ;
2730import java .util .ArrayList ;
2831import java .util .HashMap ;
32+ import java .util .HexFormat ;
2933import java .util .List ;
3034import java .util .Map ;
3135import java .util .Objects ;
@@ -147,9 +151,10 @@ public static <T> List<String> extractLibraries(Class<T> clazz, String resourceN
147151 var platform = platformPath .getName (0 ).toString ();
148152 var arch = platformPath .getName (1 ).toString ();
149153
150- var platformMap = (Map <String , List < String >>) map .get (platform );
154+ var platformMap = (Map <String , Map < String , String >>) map .get (platform );
151155
152- var fileList = platformMap .get (arch );
156+ // This is a list of all the native files, along with their corresponding MD5 hashes
157+ Map <String , String > fileHashMap = platformMap .get (arch );
153158
154159 var extractionPathString = getExtractionDirectory ();
155160
@@ -167,14 +172,22 @@ public static <T> List<String> extractLibraries(Class<T> clazz, String resourceN
167172
168173 byte [] buffer = new byte [0x10000 ]; // 64K copy buffer
169174
170- for (var file : fileList ) {
175+ for (String file : fileHashMap . keySet () ) {
171176 try (var stream = clazz .getResourceAsStream (file )) {
172177 Objects .requireNonNull (stream );
173178
174179 var outputFile = Paths .get (extractionPathString , new File (file ).getName ());
180+
181+ String hash = fileHashMap .get (file );
182+
175183 extractedFiles .add (outputFile .toString ());
176184 if (outputFile .toFile ().exists ()) {
177- continue ;
185+ if (hashEm (outputFile .toFile ()).equals (hash )) {
186+ // Hashes don't match, delete and re-extract
187+ outputFile .toFile ().delete ();
188+ } else {
189+ continue ;
190+ }
178191 }
179192 var parent = outputFile .getParent ();
180193 if (parent == null ) {
@@ -188,12 +201,31 @@ public static <T> List<String> extractLibraries(Class<T> clazz, String resourceN
188201 os .write (buffer , 0 , readBytes );
189202 }
190203 }
204+
205+ if (!hashEm (outputFile .toFile ()).equals (hash )) {
206+ throw new IOException ("Hash of extracted file does not match expected hash" );
207+ }
191208 }
192209 }
193210
194211 return extractedFiles ;
195212 }
196213
214+ private static String hashEm (File f ) throws IOException {
215+ int readBytes = 0 ;
216+ byte [] buffer = new byte [0x10000 ]; // 64K copy buffer
217+
218+ try (FileInputStream is = new FileInputStream (f )) {
219+ MessageDigest fileHash = MessageDigest .getInstance ("MD5" );
220+ while ((readBytes = is .read (buffer )) != -1 ) {
221+ fileHash .update (buffer , 0 , readBytes );
222+ }
223+ return HexFormat .of ().formatHex (fileHash .digest ());
224+ } catch (NoSuchAlgorithmException e ) {
225+ throw new IOException ("Unable to verify extracted native files" , e );
226+ }
227+ }
228+
197229 /**
198230 * Load a single library from a list of extracted files.
199231 *
0 commit comments