Java 1.7 Subject Hash of X.509 Certificate OpenSSL 1.0+ Compatible

前端 未结 4 1676
無奈伤痛
無奈伤痛 2021-02-11 01:53

I\'ve been struggling with this for a couple of days. I\'m working on a Java 1.7 app running in an embedded Linux environment. OpenSSL is not available and I don\'t have control

4条回答
  •  甜味超标
    2021-02-11 02:29

    Thanks for your code dude. I've improved it for supporting certificates that contains extended ASCII characters in the subject (éËÁñç for example).

    public static int X509_NAME_hash(X509Certificate x509Cert) throws IOException, NoSuchAlgorithmException {
        // get the subject principal
        X500Principal x500Princ = x509Cert.getSubjectX500Principal();
        byte[] newPrincEnc = x500Princ.getEncoded();
        final ASN1Sequence asn1Sequence = (ASN1Sequence) ASN1Primitive.fromByteArray(newPrincEnc);
    
        Debugger.log(asn1Sequence);
    
        List terms = new ArrayList<>();
        int finalLen = 0;
    
        // hash the encodables for each term individually and accumulate them in a list
        for (ASN1Encodable asn1Set : asn1Sequence.toArray()) {
            byte[] term = ((ASN1Set) asn1Set).getEncoded();
            term[9] = 0x0c; // change tag from 0x13 (printable string) to 0x0c
    
            for (int i = 11; i < term.length; i++) {
                byte actual = term[i];
                //lowercase only if the character is not ASCCI Extended (below 126)
                if (actual < 127) {
                    term[i] = (byte) Character.toLowerCase((char) actual);
                }
            }
    
            terms.add(term);
            finalLen += term.length;
        }
    
        // hash all terms together in order of appearance
        int j = 0;
        byte[] finalEncForw = new byte[finalLen];
        for (byte[] term : terms)
            for (byte b : term)
                finalEncForw[j++] = b;
    
        return peekInt(MessageDigest.getInstance("SHA1").digest(finalEncForw), 0, ByteOrder.LITTLE_ENDIAN);
    }
    
    public static X509Certificate readCertificate(File rootFile) throws CertificateException, IOException {
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
        FileInputStream is = new FileInputStream(rootFile);
        return (X509Certificate) fact.generateCertificate(is);
    }
    
    public static int peekInt(byte[] src, int offset, ByteOrder order) {
        if (order == ByteOrder.BIG_ENDIAN) {
            return (((src[offset++] & 0xff) << 24) | ((src[offset++] & 0xff) << 16) | ((src[offset++] & 0xff) << 8)
                    | ((src[offset] & 0xff) << 0));
        } else {
            return (((src[offset++] & 0xff) << 0) | ((src[offset++] & 0xff) << 8) | ((src[offset++] & 0xff) << 16)
                    | ((src[offset] & 0xff) << 24));
        }
    }
    

提交回复
热议问题