OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.webapk.lib.client; |
| 6 |
| 7 import static org.junit.Assert.assertArrayEquals; |
| 8 import static org.junit.Assert.assertEquals; |
| 9 import static org.junit.Assert.assertTrue; |
| 10 |
| 11 import org.junit.Test; |
| 12 import org.junit.runner.RunWith; |
| 13 import org.robolectric.annotation.Config; |
| 14 |
| 15 import org.chromium.testing.local.LocalRobolectricTestRunner; |
| 16 import org.chromium.testing.local.TestDir; |
| 17 |
| 18 import java.io.RandomAccessFile; |
| 19 import java.nio.MappedByteBuffer; |
| 20 import java.nio.channels.FileChannel; |
| 21 import java.nio.file.Files; |
| 22 import java.nio.file.Paths; |
| 23 import java.security.KeyFactory; |
| 24 import java.security.PublicKey; |
| 25 import java.security.spec.X509EncodedKeySpec; |
| 26 |
| 27 /** Unit tests for WebApkVerifySignature for Android. */ |
| 28 @RunWith(LocalRobolectricTestRunner.class) |
| 29 @Config(manifest = Config.NONE) |
| 30 public class WebApkVerifySignatureTest { |
| 31 /** Elliptical Curves, Digital Signature Algorithm */ |
| 32 private static final String KEY_FACTORY = "EC"; |
| 33 |
| 34 private static final String TEST_DATA_DIR = "/webapks/"; |
| 35 |
| 36 static PublicKey readPublicKey(String publicDER) throws Exception { |
| 37 return createPublicKey(Files.readAllBytes(Paths.get(publicDER))); |
| 38 } |
| 39 |
| 40 private static PublicKey createPublicKey(byte[] bytes) throws Exception { |
| 41 return KeyFactory.getInstance(KEY_FACTORY).generatePublic(new X509Encode
dKeySpec(bytes)); |
| 42 } |
| 43 |
| 44 @Test |
| 45 public void testHexToBytes() throws Exception { |
| 46 byte[] empty = {}; |
| 47 assertArrayEquals(empty, WebApkVerifySignature.hexToBytes("")); |
| 48 byte[] test = {(byte) 0xFF, (byte) 0xFE, 0x00, 0x01}; |
| 49 assertArrayEquals(test, WebApkVerifySignature.hexToBytes("fffe0001")); |
| 50 assertArrayEquals(test, WebApkVerifySignature.hexToBytes("FFFE0001")); |
| 51 assertEquals(null, WebApkVerifySignature.hexToBytes("f")); // Odd number
of nibbles. |
| 52 } |
| 53 |
| 54 @Test |
| 55 public void testCommentHash() throws Exception { |
| 56 byte[] bytes = {(byte) 0xde, (byte) 0xca, (byte) 0xfb, (byte) 0xad}; |
| 57 assertEquals(null, WebApkVerifySignature.parseCommentSignature("weapk:de
cafbad")); |
| 58 assertEquals(null, WebApkVerifySignature.parseCommentSignature("webapk:"
)); |
| 59 assertEquals(null, WebApkVerifySignature.parseCommentSignature("webapk:d
ecafbad")); |
| 60 assertArrayEquals( |
| 61 bytes, WebApkVerifySignature.parseCommentSignature("webapk:12345
:decafbad")); |
| 62 assertArrayEquals( |
| 63 bytes, WebApkVerifySignature.parseCommentSignature("XXXwebapk:00
00:decafbadXXX")); |
| 64 assertArrayEquals( |
| 65 bytes, WebApkVerifySignature.parseCommentSignature("\n\nwebapk:0
000:decafbad\n\n")); |
| 66 assertArrayEquals(bytes, |
| 67 WebApkVerifySignature.parseCommentSignature("chrome-webapk:000:d
ecafbad\n\n")); |
| 68 assertArrayEquals(bytes, |
| 69 WebApkVerifySignature.parseCommentSignature( |
| 70 "prefixed: chrome-webapk:000:decafbad :suffixed")); |
| 71 } |
| 72 |
| 73 public static String testFilePath(String fname) { |
| 74 return TestDir.getTestFilePath(TEST_DATA_DIR + fname); |
| 75 } |
| 76 |
| 77 @Test |
| 78 public void testVerifyFiles() throws Exception { |
| 79 PublicKey pub = readPublicKey(testFilePath("public.der")); |
| 80 String[] filenames = {"example.apk", "java-example.apk"}; |
| 81 for (String filename : filenames) { |
| 82 RandomAccessFile file = new RandomAccessFile(testFilePath(filename),
"r"); |
| 83 FileChannel inChannel = file.getChannel(); |
| 84 MappedByteBuffer buf = |
| 85 inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.si
ze()); |
| 86 buf.load(); |
| 87 WebApkVerifySignature v = new WebApkVerifySignature(buf); |
| 88 assertEquals("for file " + filename, WebApkVerifySignature.ERROR_OK,
v.read()); |
| 89 assertEquals( |
| 90 "for file " + filename, WebApkVerifySignature.ERROR_OK, v.ve
rifySignature(pub)); |
| 91 buf.clear(); |
| 92 inChannel.close(); |
| 93 file.close(); |
| 94 } |
| 95 } |
| 96 |
| 97 @Test |
| 98 public void testBadVerifyFiles() throws Exception { |
| 99 PublicKey pub = readPublicKey(testFilePath("public.der")); |
| 100 String[] filenames = { |
| 101 "bad-sig.apk", "bad-utf8-fname.apk", "empty.apk", "extra-len-too
-large.apk", |
| 102 "fcomment-too-large.apk", "no-cd.apk", "no-comment.apk", "no-eoc
d.apk", |
| 103 "no-lfh.apk", "not-an.apk", "too-many-metainf.apk", "truncated.a
pk", "zeros.apk", |
| 104 "zeros-at-end.apk", |
| 105 }; |
| 106 for (String filename : filenames) { |
| 107 RandomAccessFile file = new RandomAccessFile(testFilePath(filename),
"r"); |
| 108 FileChannel inChannel = file.getChannel(); |
| 109 MappedByteBuffer buf = |
| 110 inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.si
ze()); |
| 111 buf.load(); |
| 112 WebApkVerifySignature v = new WebApkVerifySignature(buf); |
| 113 try { |
| 114 if (v.read() == WebApkVerifySignature.ERROR_OK) { |
| 115 assertTrue(v.verifySignature(pub) != WebApkVerifySignature.E
RROR_OK); |
| 116 } |
| 117 } catch (Exception e) { |
| 118 // expected |
| 119 } |
| 120 buf.clear(); |
| 121 inChannel.close(); |
| 122 file.close(); |
| 123 } |
| 124 } |
| 125 } |
OLD | NEW |