summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
blob: 6cc1eaa7cdec854110706d3f0b7effb03fb68c3d (plain) (tree)
1
2
3
4
5
6
7





                                               
                               





                                                   







                                                            
                                                                      

                                                    












                                                            
                               



                                                          
                               



                                            
                               

































































                                                                                        











                                                                                        


                                                                                               
 







                                                                                                                    
                                         








                                                                                                                                
                 

                                      


                                                                                                                    




                                                                                         


                                                                                                   
                      
                                                                                                                           


                                                                                    
                                          




                                                                                    
                                            
                                                                         
                                 
                                                                               
                          









                                                                                    

                                                                            

























                                                                                        
                                                                  
























                                                                                                                                        





                                                                         






























                                                                                    











                                                                                        







                                                                                                                                            

                                                                   

                 












                                                                                                                                            
         
                                                                                  


                                                                                         
                                                                





                                                                             

                                                                                                                                                         




                             

         
package org.uic.barcode.dynamicFrame;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
import org.uic.barcode.asn1.datatypes.FieldOrder;
import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.OctetString;
import org.uic.barcode.asn1.uper.UperEncoder;
import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
import org.uic.barcode.utils.AlgorithmNameResolver;


/**
 * The DynamicHeader for bar codes 
 * 
 * Implementation of the Draft under discussion, not final.
 */
@Sequence
@HasExtensionMarker
public class DynamicFrame extends Object{
	
	public DynamicFrame() {}

	/** The format. */
	@FieldOrder(order = 0)
	@RestrictedString(CharacterRestriction.IA5String)
	public String format;
	
	/*level 2 data*/
	@FieldOrder(order = 1)
	Level2DataType level2SignedData;
	
	
	/** The signature of level 2 data*/
	@FieldOrder(order = 2)
	@Asn1Optional public OctetString level2Signature;
	
	/**
	 * Gets the format.
	 *
	 * @return the format
	 */
	public String getFormat() {
		return format;
	}

	/**
	 * Sets the format.
	 *
	 * @param format the new format
	 */
	public void setFormat(String format) {
		this.format = format;
	}
	
	public Level2DataType getLevel2SignedData() {
		return level2SignedData;
	}

	public void setLevel2SignedData(Level2DataType level2SignedData) {
		this.level2SignedData = level2SignedData;
	}

	public OctetString getLevel2Signature() {
		return level2Signature;
	}

	public void setLevel2Signature(OctetString level2Signature) {
		this.level2Signature = level2Signature;
	}

	/**
	 * Encode.
	 * 
	 * Encode the header as ASN.1 PER UNALIGNED byte array
	 *
	 * @return the byte[]
	 */
	public byte[] encode() {
		return UperEncoder.encode(this);
	}
	
	/**
	 * Decode.
	 *
	 * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
	 *
	 * @param bytes the bytes
	 * @return the dynamic header
	 */
	public static DynamicFrame decode(byte[] bytes) {
		return UperEncoder.decode(bytes, DynamicFrame.class);	
	}
	
	/**
	 * Verify the level 2 signature
	 * 
	 * Note:  an appropriate security provider (e.g. BC) must be registered before 
	 *
	 */	
	public int validateLevel2() {

		return validateLevel2(null);
	
	}
	
	/**
	 * Verify the level 2 signature
	 * 
	 * Note:  an appropriate security provider (e.g. BC) must be registered before 
	 *
	 */	
	public int validateLevel2(Provider prov) {
		
		
		String level2KeyAlg = this.getLevel2SignedData().getLevel1Data().level2KeyAlg;

	 
		if (level2KeyAlg == null || level2KeyAlg.length() == 0) {
			return Constants.LEVEL2_VALIDATION_NO_KEY;
		}
		
		if (this.level2Signature.toByteArray() == null || this.level2Signature.toByteArray().length == 0) {
			return Constants.LEVEL2_VALIDATION_NO_SIGNATURE;
		}
					
		String keyAlgName = null;
		try {
			keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg);
		} catch (Exception e1) {
			return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;	
		}
		if (keyAlgName == null || keyAlgName.length() == 0) {
			return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;	
		}
		
		PublicKey key = null;
		try {
			byte[] keyBytes = this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray();
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
			key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
		} catch (InvalidKeySpecException | NoSuchAlgorithmException e1) {
			return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;	
		}
		
		//find the algorithm name for the signature OID
		String level2SigAlg = this.getLevel2SignedData().getLevel1Data().level2SigningAlg;

		String sigAlgName = null;
		try {
			sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg);
		} catch (Exception e1) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		if (sigAlgName == null) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		
		Signature sig;
		try {
			if (prov == null) {
				sig = Signature.getInstance(sigAlgName);
			} else {
				sig = Signature.getInstance(sigAlgName, prov);
			}
		} catch (NoSuchAlgorithmException e) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		try {
			sig.initVerify(key);
		} catch (InvalidKeyException e) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		
		try {
			byte[] data = UperEncoder.encode(level2SignedData);
			sig.update(data);
		} catch (SignatureException e) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		} catch (IllegalArgumentException e) {
			return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
		} catch (UnsupportedOperationException e) {
			return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
		}
		
		byte[] signature = level2Signature.toByteArray();
		try {
			if (sig.verify(signature)){
				return Constants.LEVEL2_VALIDATION_OK;
			} else {
				return Constants.LEVEL2_VALIDATION_FRAUD;
			}
		} catch (SignatureException e) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
  	}
	
	/**
	 * Verify the level 1 signature
	 * 
	 * Note:  an appropriate security provider (e.g. BC) must be registered before 
	 *
	 */
	public int validateLevel1(PublicKey key, Provider prov) {
		
		if (this.level2SignedData == null) {
			return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
		}
		
	
		if (this.level2SignedData.level1Signature == null || this.level2SignedData.level1Signature.toByteArray().length == 0) {
			return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
		}
		
		byte[] signature = this.getLevel2SignedData().level1Signature.toByteArray();
				
		//find the algorithm name for the signature OID
		String algo = null;
		try {
			algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2SignedData().getLevel1Data().level1SigningAlg);
		} catch (Exception e1) {
			return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}	
		if (algo == null) {
			return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		
		Signature sig;
		try {
			if (prov != null) {
				sig = Signature.getInstance(algo, prov);
			} else {
				sig = Signature.getInstance(algo);

			}
		} catch (NoSuchAlgorithmException e) {
			return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		try {
			sig.initVerify(key);
		} catch (InvalidKeyException e) {
			return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
		
		try {
			sig.update(this.level2SignedData.level1Data.encode());
		} catch (SignatureException e) {
			return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		} catch (IllegalArgumentException e) {
			return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
		} catch (UnsupportedOperationException e) {
			return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
		}
		

		try {
			if (sig.verify(signature)){
				return Constants.LEVEL2_VALIDATION_OK;
			} else {
				return Constants.LEVEL2_VALIDATION_FRAUD;
			}
		} catch (SignatureException e) {
			return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
		}
  	}
	
	/**
	 * Verify the level 1 signature
	 * 
	 * Note:  an appropriate security provider (e.g. BC) must be registered before 
	 *
	 */
	public int validateLevel1(PublicKey key) {
		
		return validateLevel1(key, null);

  	}
	
	public void signLevel2(PrivateKey key) throws Exception {
		
		//find the algorithm name for the signature OID
		String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
		Signature sig = Signature.getInstance(algo);
		sig.initSign(key);
		byte[] data = level2SignedData.encode();
		sig.update(data);
		byte[] signature = sig.sign();
		this.level2Signature = new OctetString(signature);
		
	}

	public void signLevel2(PrivateKey key, Provider prov) throws Exception {
		
		//find the algorithm name for the signature OID
		String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
		Signature sig = Signature.getInstance(algo,prov);
		sig.initSign(key);
		byte[] data = level2SignedData.encode();
		sig.update(data);
		this.level2Signature = new OctetString(sig.sign());
		
	}

	
	public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
		this.getLevel2SignedData().setLevel2Data( dynamicData.getDataType());	
	}
	
	public UicDynamicContentDataFDC1 getDynamicDataFDC1() {
		
		if (this.getLevel2SignedData() == null || 
			this.getLevel2SignedData().getLevel2Data() == null){
			return null;
		}
		
		if ( UicDynamicContentDataFDC1.getFormat().equals(this.getLevel2SignedData().getLevel2Data().getFormat())) {
			return UperEncoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData(), UicDynamicContentDataFDC1.class);		
		}
		return null;
		
	}
	
	
}