use of sun.security.x509.KeyUsageExtension in project j2objc by google.
the class SignerInfo method verify.
/* Returns null if verify fails, this signerInfo if
verify succeeds. */
SignerInfo verify(PKCS7 block, InputStream inputStream) throws NoSuchAlgorithmException, SignatureException, IOException {
try {
ContentInfo content = block.getContentInfo();
if (inputStream == null) {
inputStream = new ByteArrayInputStream(content.getContentBytes());
}
String digestAlgname = getDigestAlgorithmId().getName();
InputStream dataSigned;
// digest and compare it with the digest of data
if (authenticatedAttributes == null) {
dataSigned = inputStream;
} else {
// first, check content type
ObjectIdentifier contentType = (ObjectIdentifier) authenticatedAttributes.getAttributeValue(PKCS9Attribute.CONTENT_TYPE_OID);
if (contentType == null || !contentType.equals(content.contentType))
// contentType does not match, bad SignerInfo
return null;
// now, check message digest
byte[] messageDigest = (byte[]) authenticatedAttributes.getAttributeValue(PKCS9Attribute.MESSAGE_DIGEST_OID);
if (// fail if there is no message digest
messageDigest == null)
return null;
MessageDigest md = MessageDigest.getInstance(convertToStandardName(digestAlgname));
byte[] buffer = new byte[4096];
int read = 0;
while ((read = inputStream.read(buffer)) != -1) {
md.update(buffer, 0, read);
}
byte[] computedMessageDigest = md.digest();
if (messageDigest.length != computedMessageDigest.length)
return null;
for (int i = 0; i < messageDigest.length; i++) {
if (messageDigest[i] != computedMessageDigest[i])
return null;
}
// message digest attribute matched
// digest of original data
// the data actually signed is the DER encoding of
// the authenticated attributes (tagged with
// the "SET OF" tag, not 0xA0).
dataSigned = new ByteArrayInputStream(authenticatedAttributes.getDerEncoding());
}
// put together digest algorithm and encryption algorithm
// to form signing algorithm
String encryptionAlgname = getDigestEncryptionAlgorithmId().getName();
// Workaround: sometimes the encryptionAlgname is actually
// a signature name
String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
if (tmp != null)
encryptionAlgname = tmp;
String algname = AlgorithmId.makeSigAlg(digestAlgname, encryptionAlgname);
Signature sig = Signature.getInstance(algname);
X509Certificate cert = getCertificate(block);
if (cert == null) {
return null;
}
if (cert.hasUnsupportedCriticalExtension()) {
throw new SignatureException("Certificate has unsupported " + "critical extension(s)");
}
// Make sure that if the usage of the key in the certificate is
// restricted, it can be used for digital signatures.
// XXX We may want to check for additional extensions in the
// future.
boolean[] keyUsageBits = cert.getKeyUsage();
if (keyUsageBits != null) {
KeyUsageExtension keyUsage;
try {
// We don't care whether or not this extension was marked
// critical in the certificate.
// We're interested only in its value (i.e., the bits set)
// and treat the extension as critical.
keyUsage = new KeyUsageExtension(keyUsageBits);
} catch (IOException ioe) {
throw new SignatureException("Failed to parse keyUsage " + "extension");
}
boolean digSigAllowed = ((Boolean) keyUsage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue();
boolean nonRepuAllowed = ((Boolean) keyUsage.get(KeyUsageExtension.NON_REPUDIATION)).booleanValue();
if (!digSigAllowed && !nonRepuAllowed) {
throw new SignatureException("Key usage restricted: " + "cannot be used for " + "digital signatures");
}
}
PublicKey key = cert.getPublicKey();
sig.initVerify(key);
byte[] buffer = new byte[4096];
int read = 0;
while ((read = dataSigned.read(buffer)) != -1) {
sig.update(buffer, 0, read);
}
if (sig.verify(encryptedDigest)) {
return this;
}
} catch (IOException e) {
throw new SignatureException("IO error verifying signature:\n" + e.getMessage());
} catch (InvalidKeyException e) {
throw new SignatureException("InvalidKey: " + e.getMessage());
}
return null;
}
Aggregations