1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/browserid/ASNUtils.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,82 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +package org.mozilla.gecko.browserid; 1.9 + 1.10 + 1.11 +/** 1.12 + * Java produces signature in ASN.1 format. Here's some hard-coded encoding and decoding 1.13 + * code, courtesy of a comment in 1.14 + * <a href="http://stackoverflow.com/questions/10921733/how-sign-method-of-the-digital-signature-combines-the-r-s-values-in-to-array">http://stackoverflow.com/questions/10921733/how-sign-method-of-the-digital-signature-combines-the-r-s-values-in-to-array</a>. 1.15 + */ 1.16 +public class ASNUtils { 1.17 + /** 1.18 + * Decode two short arrays from ASN.1 bytes. 1.19 + * @param input to extract. 1.20 + * @return length 2 array of byte arrays. 1.21 + */ 1.22 + public static byte[][] decodeTwoArraysFromASN1(byte[] input) throws IllegalArgumentException { 1.23 + if (input == null) { 1.24 + throw new IllegalArgumentException("input must not be null"); 1.25 + } 1.26 + if (input.length <= 3) 1.27 + throw new IllegalArgumentException("bad length"); 1.28 + if (input[0] != 0x30) 1.29 + throw new IllegalArgumentException("bad encoding"); 1.30 + if ((input[1] & ((byte) 0x80)) != 0) 1.31 + throw new IllegalArgumentException("bad length encoding"); 1.32 + if (input[2] != 0x02) 1.33 + throw new IllegalArgumentException("bad encoding"); 1.34 + if ((input[3] & ((byte) 0x80)) != 0) 1.35 + throw new IllegalArgumentException("bad length encoding"); 1.36 + byte rLength = input[3]; 1.37 + if (input.length <= 5 + rLength) 1.38 + throw new IllegalArgumentException("bad length"); 1.39 + if (input[4 + rLength] != 0x02) 1.40 + throw new IllegalArgumentException("bad encoding"); 1.41 + if ((input[5 + rLength] & (byte) 0x80) !=0) 1.42 + throw new IllegalArgumentException("bad length encoding"); 1.43 + byte sLength = input[5 + rLength]; 1.44 + if (input.length != 6 + sLength + rLength) 1.45 + throw new IllegalArgumentException("bad length"); 1.46 + byte[] rArr = new byte[rLength]; 1.47 + byte[] sArr = new byte[sLength]; 1.48 + System.arraycopy(input, 4, rArr, 0, rLength); 1.49 + System.arraycopy(input, 6 + rLength, sArr, 0, sLength); 1.50 + return new byte[][] { rArr, sArr }; 1.51 + } 1.52 + 1.53 + /** 1.54 + * Encode two short arrays into ASN.1 bytes. 1.55 + * @param first array to encode. 1.56 + * @param second array to encode. 1.57 + * @return array. 1.58 + */ 1.59 + public static byte[] encodeTwoArraysToASN1(byte[] first, byte[] second) throws IllegalArgumentException { 1.60 + if (first == null) { 1.61 + throw new IllegalArgumentException("first must not be null"); 1.62 + } 1.63 + if (second == null) { 1.64 + throw new IllegalArgumentException("second must not be null"); 1.65 + } 1.66 + byte[] output = new byte[6 + first.length + second.length]; 1.67 + output[0] = 0x30; 1.68 + if (4 + first.length + second.length > 255) 1.69 + throw new IllegalArgumentException("bad length"); 1.70 + output[1] = (byte) (4 + first.length + second.length); 1.71 + if ((output[1] & ((byte) 0x80)) != 0) 1.72 + throw new IllegalArgumentException("bad length encoding"); 1.73 + output[2] = 0x02; 1.74 + output[3] = (byte) first.length; 1.75 + if ((output[3] & ((byte) 0x80)) != 0) 1.76 + throw new IllegalArgumentException("bad length encoding"); 1.77 + System.arraycopy(first, 0, output, 4, first.length); 1.78 + output[4 + first.length] = 0x02; 1.79 + output[5 + first.length] = (byte) second.length; 1.80 + if ((output[5 + first.length] & ((byte) 0x80)) != 0) 1.81 + throw new IllegalArgumentException("bad length encoding"); 1.82 + System.arraycopy(second, 0, output, 6 + first.length, second.length); 1.83 + return output; 1.84 + } 1.85 +}