You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2011/07/28 12:54:24 UTC
svn commit: r1151787 - in /webservices/wss4j/branches/1_5_x-fixes: keys/
src/org/apache/ws/security/components/crypto/ test/ test/wssec/
Author: coheigea
Date: Thu Jul 28 10:54:23 2011
New Revision: 1151787
URL: http://svn.apache.org/viewvc?rev=1151787&view=rev
Log:
[WSS-300] - SubjectKeyIidentifier (SKI) incorrectly calculated for 2048-bit RSA key
- Backported to 1.5.x branch
Added:
webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.crt
webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.jks
webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.pem
webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/DERDecoder.java
webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/X509SubjectPublicKeyInfo.java
webservices/wss4j/branches/1_5_x-fixes/test/rsa2048.properties
webservices/wss4j/branches/1_5_x-fixes/test/wssec/TestWSSecuritySKI.java
Modified:
webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/CryptoBase.java
webservices/wss4j/branches/1_5_x-fixes/test/wssec/PackageTests.java
Added: webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.crt
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.crt?rev=1151787&view=auto
==============================================================================
Files webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.crt (added) and webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.crt Thu Jul 28 10:54:23 2011 differ
Added: webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.jks
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.jks?rev=1151787&view=auto
==============================================================================
Files webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.jks (added) and webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.jks Thu Jul 28 10:54:23 2011 differ
Added: webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.pem
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.pem?rev=1151787&view=auto
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.pem (added)
+++ webservices/wss4j/branches/1_5_x-fixes/keys/rsa2048.pem Thu Jul 28 10:54:23 2011
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEGzCCAwOgAwIBAgIJANl1lmfiF98pMA0GCSqGSIb3DQEBBQUAMGYxCzAJBgNV
+BAYTAklFMQ8wDQYDVQQIEwZEdWJsaW4xDzANBgNVBAcTBkR1YmxpbjEPMA0GA1UE
+ChMGVGFsZW5kMRUwEwYDVQQLEwxBcGFjaGUgV1NTNEoxDTALBgNVBAMTBENvbG0w
+HhcNMTEwNzI4MDk0OTQ5WhcNMjEwNzI1MDk0OTQ5WjBmMQswCQYDVQQGEwJJRTEP
+MA0GA1UECBMGRHVibGluMQ8wDQYDVQQHEwZEdWJsaW4xDzANBgNVBAoTBlRhbGVu
+ZDEVMBMGA1UECxMMQXBhY2hlIFdTUzRKMQ0wCwYDVQQDEwRDb2xtMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1UYfw24LPY4keBfH5PQewsZx0+uz8+A+
+WK4pP08l7lrmf295vmIY7XFjjh0MCXUkCqLzvYg0mkgMiNgLgB3jaaLrfhu8pyf5
+wUpaUBMeLaO39VZ7OtVVp83oExZ7QjKvFj8LIOGQFJcpGNgisG+ZS/Om3RsvwcmC
+YfHy79pudmDCekrzPSjzefLVYU76nbEhSY1gg7XwBrdcf9NxJ7kXaiksjusK0ghJ
+z1jeHTa3hqOx9PrEjZIbFg50OK4ryNea9cEXRkymQYwtWWYy1PIdsW5/vbvk0EY0
+c7rJyxwE8IwSDcq0qt5ycv4+IN0vy9u5W/F8ZL2FW6kOU96CgzvgjwIDAQABo4HL
+MIHIMB0GA1UdDgQWBBTf2sElFwaxKfu7TtX5rmGGzj7hXTCBmAYDVR0jBIGQMIGN
+gBTf2sElFwaxKfu7TtX5rmGGzj7hXaFqpGgwZjELMAkGA1UEBhMCSUUxDzANBgNV
+BAgTBkR1YmxpbjEPMA0GA1UEBxMGRHVibGluMQ8wDQYDVQQKEwZUYWxlbmQxFTAT
+BgNVBAsTDEFwYWNoZSBXU1M0SjENMAsGA1UEAxMEQ29sbYIJANl1lmfiF98pMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJ2yaxEIxVSqmu+Q8E775cMM
+VVoQ2Z9wBoUK6L4h61Tq8EOQ7ixk9VzzNS2Ck4T7Y3ogSOtXInh6J27UDhtgnxlY
+LfZ1//SN52R/4llKRPFaS4cUYzEjI3eAul7c38zjqY0V0Zq/nSqF+3WKExSY5P3o
+D0JyuoalOKDUH0sNyK6uR5ItDYBLZvQ4La3fqx+UVEpndzyPeeYbBy13lxa0UYiM
+GXiyogX3FbNMfduJGpoD4nz/bNPjqR5DQOdNpLzsGarsA1QEGmXS5jMrdvRvyq37
+UjwzqpmuQY0VBBo6w9pBW2zYnJColy+LUKC90omFAml3PO1J9COEgRbODS+fjBI=
+-----END CERTIFICATE-----
Modified: webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/CryptoBase.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/CryptoBase.java?rev=1151787&r1=1151786&r2=1151787&view=diff
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/CryptoBase.java (original)
+++ webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/CryptoBase.java Thu Jul 28 10:54:23 2011
@@ -597,17 +597,8 @@ public abstract class CryptoBase impleme
byte[] derEncodedValue = cert.getExtensionValue(SKI_OID);
if (cert.getVersion() < 3 || derEncodedValue == null) {
- PublicKey key = cert.getPublicKey();
- if (!(key instanceof RSAPublicKey)) {
- throw new WSSecurityException(
- 1,
- "noSKIHandling",
- new Object[]{"Support for RSA key only"});
- }
- byte[] encoded = key.getEncoded();
- // remove 22-byte algorithm ID and header
- byte[] value = new byte[encoded.length - 22];
- System.arraycopy(encoded, 22, value, 0, value.length);
+ X509SubjectPublicKeyInfo spki = new X509SubjectPublicKeyInfo(cert.getPublicKey());
+ byte[] value = spki.getSubjectPublicKey();
MessageDigest sha;
try {
sha = MessageDigest.getInstance("SHA-1");
@@ -624,13 +615,15 @@ public abstract class CryptoBase impleme
}
//
- // Strip away first four bytes from the DerValue (tag and length of
+ // Strip away first (four) bytes from the DerValue (tag and length of
// ExtensionValue OCTET STRING and KeyIdentifier OCTET STRING)
//
- byte abyte0[] = new byte[derEncodedValue.length - 4];
-
- System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
- return abyte0;
+ DERDecoder extVal = new DERDecoder(derEncodedValue);
+ extVal.expect(DERDecoder.TYPE_OCTET_STRING); // ExtensionValue OCTET STRING
+ extVal.getLength();
+ extVal.expect(DERDecoder.TYPE_OCTET_STRING); // KeyIdentifier OCTET STRING
+ int keyIDLen = extVal.getLength();
+ return extVal.getBytes(keyIDLen);
}
public KeyStore getKeyStore() {
Added: webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/DERDecoder.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/DERDecoder.java?rev=1151787&view=auto
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/DERDecoder.java (added)
+++ webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/DERDecoder.java Thu Jul 28 10:54:23 2011
@@ -0,0 +1,226 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ws.security.components.crypto;
+
+import java.math.BigInteger;
+import org.apache.ws.security.WSSecurityException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides the means to navigate through a DER-encoded byte array, to help
+ * in decoding the contents.
+ * <p>
+ * It maintains a "current position" in the array that advances with each
+ * operation, providing a simple means to handle the type-length-value
+ * encoding of DER. For example
+ * <pre>
+ * decoder.expect(TYPE);
+ * int length = decoder.getLength();
+ * byte[] value = decoder.getBytes(len);
+ * </pre>
+ */
+public class DERDecoder {
+ private static Log log = LogFactory.getLog(DERDecoder.class);
+
+ /** DER type identifier for a bit string value */
+ public static final byte TYPE_BIT_STRING = 0x03;
+ /** DER type identifier for a octet string value */
+ public static final byte TYPE_OCTET_STRING = 0x04;
+ /** DER type identifier for a sequence value */
+ public static final byte TYPE_SEQUENCE = 0x30;
+
+ private byte[] arr;
+ private int pos;
+
+ /**
+ * Construct a DERDecoder for the given byte array.
+ *
+ * @param derEncoded the DER-encoded array to decode.
+ * @throws WSSecurityException if the given array is null.
+ */
+ public DERDecoder(byte[] derEncoded) throws WSSecurityException {
+ if (derEncoded == null) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid DER string" }
+ );
+ }
+ arr = derEncoded;
+ reset();
+ }
+
+
+ /**
+ * Reset the current position to the start of the array.
+ */
+ public void reset() {
+ pos = 0;
+ }
+
+ /**
+ * Advance the current position by the given number of bytes.
+ *
+ * @param length the number of bytes to skip.
+ * @throws WSSecurityException if length is negative.
+ */
+ public void skip(int length) throws WSSecurityException {
+ if (length < 0) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Unsupported DER format" }
+ );
+ }
+ pos += length;
+ }
+
+ /**
+ * Confirm that the byte at the current position matches the given value.
+ *
+ * @param val the expected next byte.
+ * @throws WSSecurityException
+ * if the current position is at the end of the array, or if the
+ * byte at the current position doesn't match the expected value.
+ */
+ public void expect(int val) throws WSSecurityException {
+ expect((byte)(val & 0xFF));
+ }
+
+ /**
+ * Confirm that the byte at the current position matches the given value.
+ *
+ * @param val the expected next byte.
+ * @throws WSSecurityException
+ * if the current position is at the end of the array, or if the
+ * byte at the current position doesn't match the expected value.
+ */
+ public void expect(byte val) throws WSSecurityException {
+ if (!test(val)) {
+ log.debug("DER mismatch: expected " + val + ", got " + arr[pos]);
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid DER format" }
+ );
+ }
+ pos++;
+ }
+
+ /**
+ * Test if the byte at the current position matches the given value.
+ *
+ * @param val the value to test for a match with the current byte.
+ * @return true if the byte at the current position matches the given value.
+ * @throws WSSecurityException if the current position is at the end of
+ * the array.
+ */
+ public boolean test(byte val) throws WSSecurityException {
+ if (pos >= arr.length) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid DER format" }
+ );
+ }
+ return (arr[pos] == val);
+ }
+
+ /**
+ * Get the DER length at the current position.
+ * <p>
+ * DER length is encoded as
+ * <ul>
+ * <li>If the first byte is 0x00 to 0x7F, it describes the actual length.
+ * <li>If the first byte is 0x80 + n with 0<n<0x7F, the actual length is
+ * described in the following 'n' bytes.
+ * <li>The length value 0x80, used only in constructed types, is
+ * defined as "indefinite length".
+ * </ul>
+ *
+ * @return the length, -1 for indefinite length.
+ * @throws WSSecurityException
+ * if the current position is at the end of the array or there is
+ * an incomplete length specification.
+ */
+ public int getLength() throws WSSecurityException {
+ if (pos >= arr.length) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid DER format" }
+ );
+ }
+ int len;
+ if ((arr[pos] & 0xFF) <= 0x7F) {
+ len = arr[pos++];
+ } else if (arr[pos] == 0x80) {
+ len = -1;
+ pos++;
+ } else {
+ int nbytes = arr[pos++] & 0x7F;
+ if (pos + nbytes > arr.length) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid DER format" }
+ );
+ }
+ byte[] lenBytes = new byte[nbytes];
+ System.arraycopy(arr, pos, lenBytes, 0, lenBytes.length);
+ len = new BigInteger(1, lenBytes).intValue();
+ pos += nbytes;
+ }
+ return len;
+ }
+
+ /**
+ * Return an array of bytes from the current position.
+ *
+ * @param length the number of bytes to return.
+ * @return an array of the requested number of bytes from the current
+ * position.
+ * @throws WSSecurityException
+ * if the current position is at the end of the array, or the
+ * length is negative.
+ */
+ public byte[] getBytes(int length) throws WSSecurityException {
+ if (pos + length > arr.length) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid DER format" }
+ );
+ } else if (length < 0) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Unsupported DER format" }
+ );
+ }
+ byte[] value = new byte[length];
+ System.arraycopy(arr, pos, value, 0, length);
+ pos += length;
+ return value;
+ }
+
+}
Added: webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/X509SubjectPublicKeyInfo.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/X509SubjectPublicKeyInfo.java?rev=1151787&view=auto
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/X509SubjectPublicKeyInfo.java (added)
+++ webservices/wss4j/branches/1_5_x-fixes/src/org/apache/ws/security/components/crypto/X509SubjectPublicKeyInfo.java Thu Jul 28 10:54:23 2011
@@ -0,0 +1,107 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ws.security.components.crypto;
+
+import java.security.PublicKey;
+import org.apache.ws.security.WSSecurityException;
+
+/**
+ * Represents the X.509 SubjectPublicKeyInfo for a public key, as specified
+ * in RFC3280/5280:
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * </pre>
+ */
+public class X509SubjectPublicKeyInfo extends DERDecoder {
+
+ /**
+ * Construct a SubjectPublicKeyInfo for the given public key.
+ *
+ * @param key the public key.
+ * @throws WSSecurityException if the public key encoding format is
+ * not X.509 or the encoding is null.
+ */
+ public X509SubjectPublicKeyInfo(PublicKey key) throws WSSecurityException {
+ super(key.getEncoded());
+ if (!("X.509".equalsIgnoreCase(key.getFormat())
+ || "X509".equalsIgnoreCase(key.getFormat()))) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Support for X.509-encoded public keys only" }
+ );
+ }
+ }
+
+ /**
+ * Construct a SubjectPublicKeyInfo for the given X.509-encoded public key.
+ *
+ * @param x509EncodedPublicKey the public key, in X.509 DER-encoding.
+ * @throws WSSecurityException if the encoded public key is null.
+ */
+ public X509SubjectPublicKeyInfo(byte[] x509EncodedPublicKey) throws WSSecurityException {
+ super(x509EncodedPublicKey);
+ }
+
+ /**
+ * Get the subjectPublicKey element of the SubjectPublicKeyInfo.
+ *
+ * @return the X.509-encoded subjectPublicKey bit string.
+ * @throws WSSecurityException the DER-encoding is invalid.
+ */
+ public byte[] getSubjectPublicKey() throws WSSecurityException {
+ reset();
+ expect(TYPE_SEQUENCE); // SubjectPublicKeyInfo SEQUENCE
+ getLength();
+ // Could enforce the max length of this sequence, but not actually
+ // necessary for our purposes, so be forgiving and simply ignore.
+ expect(TYPE_SEQUENCE); // algorithm AlgorithmIdentifier SEQUENCE
+ int algIDlen = getLength();
+ if (algIDlen < 0) {
+ // Unsupported indefinite-length
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Unsupported X.509 public key format" }
+ );
+ }
+ skip(algIDlen); // AlgorithmIdentifier contents
+ expect(TYPE_BIT_STRING); // subjectPublicKey BIT STRING
+ int keyLen = getLength()-1;
+ if (keyLen < 0) {
+ // Invalid BIT STRING length
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "noSKIHandling",
+ new Object[] { "Invalid X.509 public key format" }
+ );
+ }
+ skip(1); // number unused bits
+ // DER-encoding guarantees unused bits should be 0
+
+ return getBytes(keyLen);
+ }
+}
Added: webservices/wss4j/branches/1_5_x-fixes/test/rsa2048.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/test/rsa2048.properties?rev=1151787&view=auto
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/test/rsa2048.properties (added)
+++ webservices/wss4j/branches/1_5_x-fixes/test/rsa2048.properties Thu Jul 28 10:54:23 2011
@@ -0,0 +1,5 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=security
+org.apache.ws.security.crypto.merlin.keystore.alias=rsa2048
+org.apache.ws.security.crypto.merlin.file=keys/rsa2048.jks
Modified: webservices/wss4j/branches/1_5_x-fixes/test/wssec/PackageTests.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/test/wssec/PackageTests.java?rev=1151787&r1=1151786&r2=1151787&view=diff
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/test/wssec/PackageTests.java (original)
+++ webservices/wss4j/branches/1_5_x-fixes/test/wssec/PackageTests.java Thu Jul 28 10:54:23 2011
@@ -76,6 +76,7 @@ public class PackageTests extends TestCa
suite.addTestSuite(TestWSSecurityWSS199.class);
suite.addTestSuite(TestWSSecurityWSS234.class);
suite.addTestSuite(TestWSSecurityWSS245.class);
+ suite.addTestSuite(TestWSSecuritySKI.class);
return suite;
}
Added: webservices/wss4j/branches/1_5_x-fixes/test/wssec/TestWSSecuritySKI.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/1_5_x-fixes/test/wssec/TestWSSecuritySKI.java?rev=1151787&view=auto
==============================================================================
--- webservices/wss4j/branches/1_5_x-fixes/test/wssec/TestWSSecuritySKI.java (added)
+++ webservices/wss4j/branches/1_5_x-fixes/test/wssec/TestWSSecuritySKI.java Thu Jul 28 10:54:23 2011
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.io.InputStream;
+import java.security.cert.X509Certificate;
+
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.util.Base64;
+
+
+/**
+ * This is a test for WSS-300 - "SubjectKeyIdentifier (SKI) incorrectly calculated for 2048-bit RSA key".
+ * The SKI value WSS4J generates for various key sizes is tested against the output from openssl, e.g.:
+ *
+ * openssl x509 -inform der -ocspid -in wss40_server.crt | grep 'Public key OCSP hash'
+ * | perl -ne 'split; print pack("H*",$_[4])' | base64
+ */
+public class TestWSSecuritySKI extends TestCase {
+
+ /**
+ * TestWSSecurity constructor
+ * <p/>
+ *
+ * @param name name of the test
+ */
+ public TestWSSecuritySKI(String name) {
+ super(name);
+ }
+
+ /**
+ * JUnit suite
+ * <p/>
+ *
+ * @return a junit test suite
+ */
+ public static Test suite() {
+ return new TestSuite(TestWSSecuritySKI.class);
+ }
+
+ public void testRSA2048() throws Exception {
+ // Load the keystore
+ Crypto crypto = CryptoFactory.getInstance("rsa2048.properties");
+ X509Certificate[] certs = crypto.getCertificates("rsa2048");
+ assertTrue(certs != null && certs.length > 0);
+
+ byte[] skiBytes = crypto.getSKIBytesFromCert(certs[0]);
+ String knownBase64Encoding = "39rBJRcGsSn7u07V+a5hhs4+4V0=";
+ assertTrue(knownBase64Encoding.equals(Base64.encode(skiBytes)));
+ }
+
+}