Java tutorial
/* * Copyright 2013 Thomas Bocek * * Licensed 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 net.tomp2p.connection; import io.netty.buffer.ByteBuf; import java.io.IOException; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import net.tomp2p.message.SHA1Signature; import net.tomp2p.p2p.PeerMaker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The default signature is done with SHA1withDSA. * * @author Thomas Bocek * */ public class DefaultSignatureFactory implements SignatureFactory { private static final Logger LOG = LoggerFactory.getLogger(DefaultSignatureFactory.class); //TODO: check if needed @Override public Signature signatureInstance() { try { return Signature.getInstance("SHA1withDSA"); } catch (NoSuchAlgorithmException e) { LOG.error("could not find algorithm", e); return null; } } @Override public PublicKey decodePublicKey(final byte[] me) { X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(me); try { KeyFactory keyFactory = KeyFactory.getInstance("DSA"); return keyFactory.generatePublic(pubKeySpec); } catch (NoSuchAlgorithmException e) { LOG.error("could not find algorithm", e); return null; } catch (InvalidKeySpecException e) { LOG.error("wrong keyspec", e); return null; } } //decodes with header @Override public PublicKey decodePublicKey(ByteBuf buf) { if (buf.readableBytes() < 2) { return null; } int len = buf.getUnsignedShort(buf.readerIndex()); if (buf.readableBytes() - 2 < len) { return null; } buf.skipBytes(2); if (len <= 0) { return PeerMaker.EMPTY_PUBLICKEY; } byte me[] = new byte[len]; buf.readBytes(me); return decodePublicKey(me); } @Override public void encodePublicKey(PublicKey publicKey, ByteBuf buf) { byte[] data = publicKey.getEncoded(); buf.writeShort(data.length); buf.writeBytes(data); } @Override public SHA1Signature sign(PrivateKey privateKey, ByteBuf buf) throws InvalidKeyException, SignatureException, IOException { Signature signature = signatureInstance(); signature.initSign(privateKey); ByteBuffer[] byteBuffers = buf.nioBuffers(); int len = byteBuffers.length; for (int i = 0; i < len; i++) { ByteBuffer buffer = byteBuffers[i]; signature.update(buffer); } byte[] signatureData = signature.sign(); SHA1Signature decodedSignature = new SHA1Signature(); decodedSignature.decode(signatureData); return decodedSignature; } @Override public boolean verify(PublicKey publicKey, ByteBuf buf, SHA1Signature signatureEncoded) throws SignatureException, InvalidKeyException, IOException { Signature signature = signatureInstance(); signature.initVerify(publicKey); ByteBuffer[] byteBuffers = buf.nioBuffers(); int len = byteBuffers.length; for (int i = 0; i < len; i++) { ByteBuffer buffer = byteBuffers[i]; signature.update(buffer); } byte[] signatureReceived = signatureEncoded.encode(); return signature.verify(signatureReceived); } }