1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/samples/messagedigest/src/META-INF/services/org.apidesign.impl.security.friendapi.DigestProvider Sat Jun 14 09:52:22 2008 +0200
1.3 @@ -0,0 +1,7 @@
1.4 +# this is a provider for the SPI, shall be in the same module as the api & spi
1.5 +org.apidesign.impl.security.spi.DigestorProvider
1.6 +
1.7 +
1.8 +# this shall be in a separate module that provides the "bridge"
1.9 +org.apidesign.impl.security.extension.BridgeToOldAlgorithmsProvider
1.10 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/samples/messagedigest/src/org/apidesign/api/security/Digest.java Sat Jun 14 09:52:22 2008 +0200
2.3 @@ -0,0 +1,42 @@
2.4 +
2.5 +package org.apidesign.api.security;
2.6 +
2.7 +import java.nio.ByteBuffer;
2.8 +import org.apidesign.impl.security.friendapi.DigestImplementation;
2.9 +import org.apidesign.impl.security.friendapi.DigestProvider;
2.10 +import java.util.ServiceLoader;
2.11 +
2.12 +/** MessageDigest extends MessageDigestSpi, that means the javadoc
2.13 + *
2.14 + * @author Jaroslav Tulach
2.15 + */
2.16 +public final class Digest {
2.17 + private final DigestImplementation impl;
2.18 +
2.19 + /** Factory method is better than constructor */
2.20 + private Digest(DigestImplementation impl) {
2.21 + this.impl = impl;
2.22 + }
2.23 +
2.24 + /** Factory method to create digest for an algorithm.
2.25 + */
2.26 + public static Digest getInstance(String algorithm) {
2.27 + for (DigestProvider dp : ServiceLoader.load(DigestProvider.class)) {
2.28 + DigestImplementation impl = dp.create(algorithm);
2.29 + if (impl != null) {
2.30 + return new Digest(impl);
2.31 + }
2.32 + }
2.33 + throw new IllegalArgumentException(algorithm);
2.34 + }
2.35 +
2.36 + //
2.37 + // these methods are kept the same as in original MessageDigest,
2.38 + // but for simplicity choose just some from the original API
2.39 + //
2.40 +
2.41 + public byte[] digest(ByteBuffer bb) {
2.42 + impl.update(bb);
2.43 + return impl.digest();
2.44 + }
2.45 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/samples/messagedigest/src/org/apidesign/impl/security/extension/BridgeToOld.java Sat Jun 14 09:52:22 2008 +0200
3.3 @@ -0,0 +1,82 @@
3.4 +/*
3.5 + * To change this template, choose Tools | Templates
3.6 + * and open the template in the editor.
3.7 + */
3.8 +
3.9 +package org.apidesign.impl.security.extension;
3.10 +
3.11 +import org.apidesign.api.security.Digest;
3.12 +import java.nio.ByteBuffer;
3.13 +import java.security.MessageDigest;
3.14 +import java.security.NoSuchAlgorithmException;
3.15 +import java.security.Provider;
3.16 +import java.security.Security;
3.17 +import java.util.Collections;
3.18 +import java.util.List;
3.19 +import java.util.Map;
3.20 +
3.21 +/**
3.22 + *
3.23 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.24 + */
3.25 +public class BridgeToOld extends Provider {
3.26 +
3.27 + public BridgeToOld() {
3.28 + super("spi.Digestor", 1.0, "");
3.29 + Security.addProvider(this);
3.30 + }
3.31 +
3.32 + @Override
3.33 + public synchronized Service getService(String type, String algorithm) {
3.34 + if ("MessageDigest".equals(type)) {
3.35 + Digest dig = Digest.getInstance(algorithm);
3.36 + if (dig != null) {
3.37 + return new ServiceImpl(dig, this, type, algorithm, "", Collections.<String>emptyList(), Collections.<String,String>emptyMap());
3.38 + }
3.39 + }
3.40 + return null;
3.41 + }
3.42 +
3.43 + private static class ServiceImpl<Data> extends Service {
3.44 + Digest dig;
3.45 +
3.46 + public ServiceImpl(Digest dig, Provider provider, String type, String algorithm, String className, List<String> aliases, Map<String, String> attributes) {
3.47 + super(provider, type, algorithm, className, aliases, attributes);
3.48 + this.dig = dig;
3.49 + }
3.50 +
3.51 + @Override
3.52 + public Object newInstance(Object constructorParameter) throws NoSuchAlgorithmException {
3.53 + return new MessageDigest(getAlgorithm()) {
3.54 + private byte[] res;
3.55 +
3.56 + @Override
3.57 + protected void engineUpdate(byte input) {
3.58 + ByteBuffer bb = ByteBuffer.wrap(new byte[] { input });
3.59 + res = dig.digest(bb);
3.60 + }
3.61 +
3.62 + @Override
3.63 + protected void engineUpdate(byte[] input, int offset, int len) {
3.64 + ByteBuffer bb = ByteBuffer.wrap(input);
3.65 + bb.position(offset);
3.66 + bb.limit(offset + len);
3.67 + res = dig.digest(bb);
3.68 + }
3.69 +
3.70 + @Override
3.71 + protected byte[] engineDigest() {
3.72 + return res;
3.73 + }
3.74 +
3.75 + @Override
3.76 + protected void engineReset() {
3.77 + dig = Digest.getInstance(getAlgorithm());
3.78 + }
3.79 + };
3.80 + }
3.81 +
3.82 +
3.83 + }
3.84 +
3.85 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/samples/messagedigest/src/org/apidesign/impl/security/extension/BridgeToOldAlgorithmsProvider.java Sat Jun 14 09:52:22 2008 +0200
4.3 @@ -0,0 +1,46 @@
4.4 +/*
4.5 + * To change this template, choose Tools | Templates
4.6 + * and open the template in the editor.
4.7 + */
4.8 +
4.9 +package org.apidesign.impl.security.extension;
4.10 +
4.11 +import org.apidesign.impl.security.friendapi.DigestImplementation;
4.12 +import org.apidesign.impl.security.friendapi.DigestProvider;
4.13 +import java.nio.ByteBuffer;
4.14 +import java.security.MessageDigest;
4.15 +import java.security.NoSuchAlgorithmException;
4.16 +import java.util.logging.Level;
4.17 +import java.util.logging.Logger;
4.18 +
4.19 +/**
4.20 + *
4.21 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.22 + */
4.23 +public class BridgeToOldAlgorithmsProvider implements DigestProvider {
4.24 +
4.25 + public DigestImplementation create(String algorithm) {
4.26 + try {
4.27 + final MessageDigest md = MessageDigest.getInstance(algorithm);
4.28 + return new DigestImplementation(algorithm) {
4.29 +
4.30 + @Override
4.31 + public void update(ByteBuffer bb) {
4.32 + md.update(bb);
4.33 + }
4.34 +
4.35 + @Override
4.36 + public byte[] digest() {
4.37 + return md.digest();
4.38 + }
4.39 + };
4.40 + } catch (NoSuchAlgorithmException ex) {
4.41 + Logger.getLogger(BridgeToOldAlgorithmsProvider.class.getName()).log(Level.INFO, null, ex);
4.42 + return null;
4.43 + }
4.44 + }
4.45 +
4.46 + static {
4.47 + new BridgeToOld();
4.48 + }
4.49 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/samples/messagedigest/src/org/apidesign/impl/security/friendapi/DigestImplementation.java Sat Jun 14 09:52:22 2008 +0200
5.3 @@ -0,0 +1,23 @@
5.4 +/*
5.5 + * To change this template, choose Tools | Templates
5.6 + * and open the template in the editor.
5.7 + */
5.8 +
5.9 +package org.apidesign.impl.security.friendapi;
5.10 +
5.11 +import java.nio.ByteBuffer;
5.12 +
5.13 +/**
5.14 + *
5.15 + * @author Jaroslav Tulach
5.16 + */
5.17 +public abstract class DigestImplementation {
5.18 + final String name;
5.19 +
5.20 + protected DigestImplementation(String algorithm) {
5.21 + this.name = algorithm;
5.22 + }
5.23 +
5.24 + public abstract void update(ByteBuffer bb);
5.25 + public abstract byte[] digest();
5.26 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/samples/messagedigest/src/org/apidesign/impl/security/friendapi/DigestProvider.java Sat Jun 14 09:52:22 2008 +0200
6.3 @@ -0,0 +1,14 @@
6.4 +/*
6.5 + * To change this template, choose Tools | Templates
6.6 + * and open the template in the editor.
6.7 + */
6.8 +
6.9 +package org.apidesign.impl.security.friendapi;
6.10 +
6.11 +/**
6.12 + *
6.13 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
6.14 + */
6.15 +public interface DigestProvider {
6.16 + public abstract DigestImplementation create(String algorithm);
6.17 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/samples/messagedigest/src/org/apidesign/impl/security/spi/DigestorAccessor.java Sat Jun 14 09:52:22 2008 +0200
7.3 @@ -0,0 +1,35 @@
7.4 +/*
7.5 + * To change this template, choose Tools | Templates
7.6 + * and open the template in the editor.
7.7 + */
7.8 +
7.9 +package org.apidesign.impl.security.spi;
7.10 +
7.11 +import java.nio.ByteBuffer;
7.12 +import org.apidesign.spi.security.Digestor;
7.13 +
7.14 +/**
7.15 + *
7.16 + * @author jarda
7.17 + */
7.18 +public abstract class DigestorAccessor {
7.19 + private static DigestorAccessor INSTANCE;
7.20 +
7.21 + protected DigestorAccessor() {
7.22 + assert INSTANCE == null;
7.23 + INSTANCE = this;
7.24 + }
7.25 +
7.26 + public static DigestorAccessor getDefault() {
7.27 + try {
7.28 + Class.forName(Digestor.class.getName(), true, DigestorAccessor.class.getClassLoader());
7.29 + return INSTANCE;
7.30 + } catch (ClassNotFoundException ex) {
7.31 + throw new IllegalStateException(ex);
7.32 + }
7.33 + }
7.34 +
7.35 + protected abstract <Data> byte[] digest(Digestor<Data> dig, Data data);
7.36 + protected abstract <Data> Data create(Digestor<Data> dig, String algorithm);
7.37 + protected abstract <Data> void update(Digestor<Data> dig, Data data, ByteBuffer input);
7.38 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/samples/messagedigest/src/org/apidesign/impl/security/spi/DigestorProvider.java Sat Jun 14 09:52:22 2008 +0200
8.3 @@ -0,0 +1,61 @@
8.4 +/*
8.5 + * To change this template, choose Tools | Templates
8.6 + * and open the template in the editor.
8.7 + */
8.8 +
8.9 +package org.apidesign.impl.security.spi;
8.10 +
8.11 +import org.apidesign.impl.security.friendapi.DigestImplementation;
8.12 +import org.apidesign.impl.security.friendapi.DigestProvider;
8.13 +import java.nio.ByteBuffer;
8.14 +import java.util.ServiceLoader;
8.15 +import org.apidesign.spi.security.Digestor;
8.16 +
8.17 +/**
8.18 + *
8.19 + * @author Jaroslav Tulach
8.20 + */
8.21 +public class DigestorProvider implements DigestProvider {
8.22 +
8.23 + public DigestImplementation create(String algorithm) {
8.24 + for (Digestor<?> d : ServiceLoader.load(Digestor.class)) {
8.25 + Handler<?> h = create(d, algorithm);
8.26 + if (h != null) {
8.27 + return h;
8.28 + }
8.29 + }
8.30 + return null;
8.31 + }
8.32 +
8.33 + private static <Data> Handler<Data> create(Digestor<Data> dig, String algorithm) {
8.34 + Data d = DigestorAccessor.getDefault().create(dig, algorithm);
8.35 + if (d == null) {
8.36 + return null;
8.37 + } else {
8.38 + return new Handler<Data>(algorithm, dig, d);
8.39 + }
8.40 + }
8.41 +
8.42 + private static final class Handler<Data> extends DigestImplementation {
8.43 + private final Digestor dig;
8.44 + private final Data data;
8.45 +
8.46 + public Handler(String algorithm, Digestor dig, Data data) {
8.47 + super(algorithm);
8.48 + this.dig = dig;
8.49 + this.data = data;
8.50 + }
8.51 +
8.52 +
8.53 + @Override
8.54 + public void update(ByteBuffer bb) {
8.55 + DigestorAccessor.getDefault().update(dig, data, bb);
8.56 + }
8.57 +
8.58 + @Override
8.59 + public byte[] digest() {
8.60 + return DigestorAccessor.getDefault().digest(dig, data);
8.61 + }
8.62 +
8.63 + }
8.64 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/samples/messagedigest/src/org/apidesign/spi/security/Digestor.java Sat Jun 14 09:52:22 2008 +0200
9.3 @@ -0,0 +1,39 @@
9.4 +/*
9.5 + * To change this template, choose Tools | Templates
9.6 + * and open the template in the editor.
9.7 + */
9.8 +
9.9 +package org.apidesign.spi.security;
9.10 +
9.11 +import org.apidesign.impl.security.spi.DigestorAccessor;
9.12 +import java.nio.ByteBuffer;
9.13 +
9.14 +/**
9.15 + *
9.16 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
9.17 + */
9.18 +public abstract class Digestor<Data> {
9.19 + protected abstract byte[] digest(Data data);
9.20 + protected abstract Data create(String algorithm);
9.21 + protected abstract void update(Data data, ByteBuffer input);
9.22 +
9.23 +
9.24 + static {
9.25 + new DigestorAccessor() {
9.26 + @Override
9.27 + protected <Data> byte[] digest(Digestor<Data> dig, Data data) {
9.28 + return dig.digest(data);
9.29 + }
9.30 +
9.31 + @Override
9.32 + protected <Data> Data create(Digestor<Data> dig, String algorithm) {
9.33 + return dig.create(algorithm);
9.34 + }
9.35 +
9.36 + @Override
9.37 + protected <Data> void update(Digestor<Data> dig, Data data, ByteBuffer input) {
9.38 + dig.update(data, input);
9.39 + }
9.40 + };
9.41 + }
9.42 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/samples/messagedigest/test/META-INF/services/org.apidesign.spi.security.Digestor Sat Jun 14 09:52:22 2008 +0200
10.3 @@ -0,0 +1,3 @@
10.4 +# the provider registered from tests
10.5 +test.CountingDigestor
10.6 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/samples/messagedigest/test/test/CountingDigestor.java Sat Jun 14 09:52:22 2008 +0200
11.3 @@ -0,0 +1,35 @@
11.4 +/*
11.5 + * To change this template, choose Tools | Templates
11.6 + * and open the template in the editor.
11.7 + */
11.8 +
11.9 +package test;
11.10 +
11.11 +import java.nio.ByteBuffer;
11.12 +import org.apidesign.spi.security.Digestor;
11.13 +
11.14 +/**
11.15 + *
11.16 + * @author jarda
11.17 + */
11.18 +public final class CountingDigestor extends Digestor<int[]> {
11.19 +
11.20 + @Override
11.21 + protected byte[] digest(int[] data) {
11.22 + int i = data[0];
11.23 + byte[] arr = { (byte) (i & 255), (byte) ((i >> 8) & 255), (byte) ((i >> 16) & 255), (byte) ((i >> 24) & 255) };
11.24 + return arr;
11.25 + }
11.26 +
11.27 + @Override
11.28 + protected int[] create(String algorithm) {
11.29 + return "cnt".equals(algorithm) ? new int[1] : null; // NOI18N
11.30 + }
11.31 +
11.32 + @Override
11.33 + protected void update(int[] data, ByteBuffer input) {
11.34 + data[0] += input.remaining();
11.35 + input.position(input.position() + input.remaining());
11.36 + }
11.37 +
11.38 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/samples/messagedigest/test/test/NewAPIToOldAPITest.java Sat Jun 14 09:52:22 2008 +0200
12.3 @@ -0,0 +1,65 @@
12.4 +/*
12.5 + * To change this template, choose Tools | Templates
12.6 + * and open the template in the editor.
12.7 + */
12.8 +
12.9 +package test;
12.10 +
12.11 +import java.nio.ByteBuffer;
12.12 +import java.security.MessageDigest;
12.13 +import java.util.Arrays;
12.14 +import java.util.Random;
12.15 +import org.apidesign.api.security.Digest;
12.16 +import org.junit.After;
12.17 +import org.junit.BeforeClass;
12.18 +import org.junit.Test;
12.19 +import static org.junit.Assert.*;
12.20 +
12.21 +/** Compares that the MessageDigest and Digest yield the same results for
12.22 + * default provider.
12.23 + *
12.24 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
12.25 + */
12.26 +public class NewAPIToOldAPITest {
12.27 + private static byte[] arr;
12.28 + private static long time;
12.29 + private static byte[] resOld;
12.30 + private static byte[] resNew;
12.31 +
12.32 + public NewAPIToOldAPITest() {
12.33 + }
12.34 +
12.35 + @BeforeClass
12.36 + public static void setUp() {
12.37 + time = System.currentTimeMillis();
12.38 + Random r = new Random(time);
12.39 + arr = new byte[r.nextInt(1024)];
12.40 + r.nextBytes(arr);
12.41 + }
12.42 +
12.43 + @After
12.44 + public void tearDown() {
12.45 + }
12.46 +
12.47 + @Test
12.48 + public void generateHashUsingMessageDigest() throws Exception {
12.49 + MessageDigest md = MessageDigest.getInstance("MD5");
12.50 + byte[] res = md.digest(arr);
12.51 + resOld = res;
12.52 + }
12.53 +
12.54 + @Test
12.55 + public void generateHashUsingNewDigest() throws Exception {
12.56 + Digest d = Digest.getInstance("MD5");
12.57 + ByteBuffer bb = ByteBuffer.wrap(arr);
12.58 + byte[] res = d.digest(bb);
12.59 + resNew = res;
12.60 + }
12.61 +
12.62 + @Test
12.63 + public void compareTheHashes() throws Exception {
12.64 + if (!Arrays.equals(resOld, resNew)) {
12.65 + fail("Arrays are different:\n" + Arrays.toString(resOld) + "\n" + Arrays.toString(resNew));
12.66 + }
12.67 + }
12.68 +}
12.69 \ No newline at end of file
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/samples/messagedigest/test/test/OldAPIToNewAPITest.java Sat Jun 14 09:52:22 2008 +0200
13.3 @@ -0,0 +1,78 @@
13.4 +/*
13.5 + * To change this template, choose Tools | Templates
13.6 + * and open the template in the editor.
13.7 + */
13.8 +
13.9 +package test;
13.10 +
13.11 +import org.apidesign.api.security.*;
13.12 +import org.apidesign.impl.security.extension.BridgeToOld;
13.13 +import java.nio.ByteBuffer;
13.14 +import java.security.MessageDigest;
13.15 +import java.util.Arrays;
13.16 +import java.util.Random;
13.17 +import org.junit.After;
13.18 +import org.junit.BeforeClass;
13.19 +import org.junit.Test;
13.20 +import static org.junit.Assert.*;
13.21 +
13.22 +/** Compares that the MessageDigest and Digest yield the same results for
13.23 + * default provider.
13.24 + *
13.25 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
13.26 + */
13.27 +public class OldAPIToNewAPITest {
13.28 + private static byte[] arr;
13.29 + private static long time;
13.30 + private static byte[] resOld;
13.31 + private static byte[] resNew;
13.32 +
13.33 + public OldAPIToNewAPITest() {
13.34 + }
13.35 +
13.36 + @BeforeClass
13.37 + public static void setUp() {
13.38 + time = System.currentTimeMillis();
13.39 + Random r = new Random(time);
13.40 + arr = new byte[r.nextInt(1024)];
13.41 + r.nextBytes(arr);
13.42 + }
13.43 +
13.44 + @After
13.45 + public void tearDown() {
13.46 + }
13.47 +
13.48 + @Test
13.49 + public void generateHashUsingMessageDigest() throws Exception {
13.50 + // The java.security.Providers cannot be registered in META-INF/services
13.51 + // that is why one needs to either configure various properties or
13.52 + // make some dummy call that will initialize our bridge class.
13.53 + // Then the bridge class registers itself as a MessageDigest provider
13.54 + // in its constructor.
13.55 + //
13.56 + // This is the call:
13.57 + Digest initialize = Digest.getInstance("MD5");
13.58 +
13.59 + MessageDigest md = MessageDigest.getInstance("cnt");
13.60 + byte[] res = md.digest(arr);
13.61 + resOld = res;
13.62 + }
13.63 +
13.64 +
13.65 + @Test
13.66 + public void generateHashUsingNewDigest() throws Exception {
13.67 + Digest d = Digest.getInstance("cnt");
13.68 + ByteBuffer bb = ByteBuffer.wrap(arr);
13.69 + byte[] res = d.digest(bb);
13.70 + resNew = res;
13.71 + }
13.72 +
13.73 +
13.74 +
13.75 + @Test
13.76 + public void compareTheHashes() throws Exception {
13.77 + if (!Arrays.equals(resOld, resNew)) {
13.78 + fail("Arrays are different:\n" + Arrays.toString(resOld) + "\n" + Arrays.toString(resNew));
13.79 + }
13.80 + }
13.81 +}
13.82 \ No newline at end of file