Revision f9b84add

View differences:

src/info/guardianproject/trustedintents/CertificatePin.java
1

  
2
package info.guardianproject.trustedintents;
3

  
4
import android.content.pm.Signature;
5

  
6
import java.math.BigInteger;
7
import java.security.MessageDigest;
8
import java.security.NoSuchAlgorithmException;
9

  
10
public abstract class CertificatePin {
11

  
12
    protected byte[] certificate = null;
13
    private Signature[] signatures;
14

  
15
    public byte[] getEncoded() {
16
        return certificate; // DER-encoded X.509 Certificate
17
    }
18

  
19
    public Signature[] getSignatures() {
20
        // TODO this needs to handle multiple Signature instances
21
        if (signatures == null) {
22
            signatures = new Signature[1];
23
            signatures[0] = new Signature(certificate);
24
        }
25
        return signatures;
26
    }
27

  
28
    public String getFingerprint(String algorithm) {
29
        try {
30
            MessageDigest md = MessageDigest.getInstance(algorithm);
31
            byte[] hashBytes = md.digest(certificate);
32
            BigInteger bi = new BigInteger(1, hashBytes);
33
            md.reset();
34
            return String.format("%0" + (hashBytes.length << 1) + "x", bi);
35
        } catch (NoSuchAlgorithmException e) {
36
            e.printStackTrace();
37
        }
38
        return null;
39
    }
40

  
41
    public String getMD5Fingerprint() {
42
        return getFingerprint("MD5");
43
    }
44

  
45
    public String getSHA1Fingerprint() {
46
        return getFingerprint("SHA1");
47
    }
48

  
49
    public String getSHA256Fingerprint(byte[] input) {
50
        return getFingerprint("SHA-256");
51
    }
52
}
src/info/guardianproject/trustedintents/TrustedIntents.java
1

  
2
package info.guardianproject.trustedintents;
3

  
4
import android.content.pm.PackageManager.NameNotFoundException;
5
import android.content.pm.Signature;
6
import android.text.TextUtils;
7

  
8
import java.security.cert.CertificateException;
9
import java.util.LinkedHashMap;
10

  
11
public class TrustedIntents {
12

  
13
    private static TrustedIntents instance;
14

  
15
    private LinkedHashMap<String, Signature[]> map = new LinkedHashMap<String, Signature[]>();
16

  
17
    private TrustedIntents() {
18
    }
19

  
20
    public static TrustedIntents get() {
21
        if (instance == null)
22
            instance = new TrustedIntents();
23
        return instance;
24
    }
25

  
26
    public void addPin(String packageName, Signature[] pin) {
27
        map.put(packageName, pin);
28
    }
29

  
30
    public void checkPin(String packageName, Signature[] signatures)
31
            throws NameNotFoundException, CertificateException {
32
        if (TextUtils.isEmpty(packageName))
33
            throw new NameNotFoundException("packageName cannot be null or empty!");
34
        if (signatures == null || signatures.length == 0)
35
            throw new CertificateException("signatures cannot be null or empty!");
36
        for (int i = 0; i < signatures.length; i++)
37
            if (signatures[i] == null || signatures[i].toByteArray().length == 0)
38
                throw new CertificateException("Certificates cannot be null or empty!");
39
        if (!map.containsKey(packageName))
40
            throw new NameNotFoundException(packageName);
41
        if (!areSignaturesEqual(signatures, map.get(packageName)))
42
            throw new CertificateException("Signature not equal to pin for " + packageName);
43
    }
44

  
45
    public boolean areSignaturesEqual(Signature[] sigs0, Signature[] sigs1) {
46
        // TODO where is Android's implementation of this that I can just call?
47
        if (sigs0 == null || sigs1 == null)
48
            return false;
49
        if (sigs0.length == 0 || sigs1.length == 0)
50
            return false;
51
        if (sigs0.length != sigs1.length)
52
            return false;
53
        for (int i = 0; i < sigs0.length; i++)
54
            if (!sigs0[i].equals(sigs1[i]))
55
                return false;
56
        return true;
57
    }
58
}

Also available in: Unified diff