com.licel.jcardsim.crypto.SymmetricSignatureImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.licel.jcardsim.crypto.SymmetricSignatureImpl.java

Source

/*
 * Copyright 2011 Licel LLC.
 *
 * 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 com.licel.jcardsim.crypto;

import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.Key;
import javacard.security.Signature;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.macs.ISO9797Alg3Mac;
import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.ParametersWithIV;

/**
 * Implementation
 * <code>Signature</code> with symmetric keys based
 * on BouncyCastle CryptoAPI.
 * @see Signature
 */
public class SymmetricSignatureImpl extends Signature {

    Mac engine;
    byte algorithm;
    boolean isInitialized;

    public SymmetricSignatureImpl(byte algorithm) {
        this.algorithm = algorithm;
    }

    public void init(Key theKey, byte theMode) throws CryptoException {
        init(theKey, theMode, null, (short) 0, (short) 0);
    }

    public void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException {
        if (theKey == null) {
            CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
        }
        if (!theKey.isInitialized()) {
            CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
        }
        if (!(theKey instanceof SymmetricKeyImpl)) {
            CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
        }
        CipherParameters cipherParams = null;
        BlockCipher cipher = ((SymmetricKeyImpl) theKey).getCipher();
        if (bArray == null) {
            cipherParams = ((SymmetricKeyImpl) theKey).getParameters();
        } else {
            if (bLen != cipher.getBlockSize()) {
                CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
            }
            cipherParams = new ParametersWithIV(((SymmetricKeyImpl) theKey).getParameters(), bArray, bOff, bLen);
        }
        switch (algorithm) {
        case ALG_DES_MAC4_NOPAD:
            engine = new CBCBlockCipherMac(cipher, 32, null);
            break;
        case ALG_DES_MAC8_NOPAD:
            engine = new CBCBlockCipherMac(cipher, 64, null);
            break;
        case ALG_DES_MAC4_ISO9797_M1:
            engine = new CBCBlockCipherMac(cipher, 32, new ZeroBytePadding());
            break;
        case ALG_DES_MAC8_ISO9797_M1:
            engine = new CBCBlockCipherMac(cipher, 64, new ZeroBytePadding());
            break;
        case ALG_DES_MAC4_ISO9797_M2:
            engine = new CBCBlockCipherMac(cipher, 32, new ISO7816d4Padding());
            break;
        case ALG_DES_MAC8_ISO9797_M2:
            engine = new CBCBlockCipherMac(cipher, 64, new ISO7816d4Padding());
            break;
        case ALG_DES_MAC8_ISO9797_1_M2_ALG3:
            engine = new ISO9797Alg3Mac(new DESEngine(), 64, new ISO7816d4Padding());
            break;
        case ALG_DES_MAC4_PKCS5:
            engine = new CBCBlockCipherMac(cipher, 32, new PKCS7Padding());
            break;
        case ALG_DES_MAC8_PKCS5:
            engine = new CBCBlockCipherMac(cipher, 64, new PKCS7Padding());
            break;
        case ALG_AES_MAC_128_NOPAD:
            engine = new CBCBlockCipherMac(cipher, 128, null);
            break;
        case ALG_HMAC_SHA1:
            engine = new HMac(new SHA1Digest());
            break;
        case ALG_HMAC_SHA_256:
            engine = new HMac(new SHA256Digest());
            break;
        case ALG_HMAC_SHA_384:
            engine = new HMac(new SHA384Digest());
            break;
        case ALG_HMAC_SHA_512:
            engine = new HMac(new SHA512Digest());
            break;
        case ALG_HMAC_MD5:
            engine = new HMac(new MD5Digest());
            break;
        case ALG_HMAC_RIPEMD160:
            engine = new HMac(new RIPEMD160Digest());
            break;
        default:
            CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
            break;
        }
        engine.init(cipherParams);
        isInitialized = true;
    }

    public short getLength() throws CryptoException {
        if (!isInitialized) {
            CryptoException.throwIt(CryptoException.INVALID_INIT);
        }
        return (short) engine.getMacSize();
    }

    public byte getAlgorithm() {
        return algorithm;
    }

    public void update(byte[] inBuff, short inOffset, short inLength) throws CryptoException {
        if (!isInitialized) {
            CryptoException.throwIt(CryptoException.INVALID_INIT);
        }
        engine.update(inBuff, inOffset, inLength);
    }

    public short sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset)
            throws CryptoException {
        if (!isInitialized) {
            CryptoException.throwIt(CryptoException.INVALID_INIT);
        }
        if ((algorithm == ALG_DES_MAC8_NOPAD || algorithm == ALG_DES_MAC4_NOPAD) && ((inLength % 8) != 0)) {
            CryptoException.throwIt(CryptoException.ILLEGAL_USE);
        }
        engine.update(inBuff, inOffset, inLength);
        short processedBytes = (short) engine.doFinal(sigBuff, sigOffset);
        engine.reset();
        return processedBytes;
    }

    public boolean verify(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset,
            short sigLength) throws CryptoException {
        if (!isInitialized) {
            CryptoException.throwIt(CryptoException.INVALID_INIT);
        }
        if ((algorithm == ALG_DES_MAC8_NOPAD || algorithm == ALG_DES_MAC4_NOPAD) && ((inLength % 8) != 0)) {
            CryptoException.throwIt(CryptoException.ILLEGAL_USE);
        }
        engine.update(inBuff, inOffset, inLength);
        byte[] sig = new byte[getLength()];
        engine.doFinal(sig, (short) 0);
        engine.reset();
        return Util.arrayCompare(sig, (short) 0, sigBuff, sigOffset, (short) sig.length) == 0;
    }

    public void setInitialDigest(byte[] bytes, short s, short s1, byte[] bytes1, short s2, short s3)
            throws CryptoException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public short signPreComputedHash(byte[] bytes, short s, short s1, byte[] bytes1, short s2)
            throws CryptoException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}