001package org.apache.commons.ssl.org.bouncycastle.asn1.x9; 002 003import java.math.BigInteger; 004 005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1ObjectIdentifier; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 012import org.apache.commons.ssl.org.bouncycastle.asn1.DERBitString; 013import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 014import org.bouncycastle.math.ec.ECAlgorithms; 015import org.bouncycastle.math.ec.ECCurve; 016 017/** 018 * ASN.1 def for Elliptic-Curve Curve structure. See 019 * X9.62, for further details. 020 */ 021public class X9Curve 022 extends ASN1Object 023 implements X9ObjectIdentifiers 024{ 025 private ECCurve curve; 026 private byte[] seed; 027 private ASN1ObjectIdentifier fieldIdentifier = null; 028 029 public X9Curve( 030 ECCurve curve) 031 { 032 this.curve = curve; 033 this.seed = null; 034 setFieldIdentifier(); 035 } 036 037 public X9Curve( 038 ECCurve curve, 039 byte[] seed) 040 { 041 this.curve = curve; 042 this.seed = seed; 043 setFieldIdentifier(); 044 } 045 046 public X9Curve( 047 X9FieldID fieldID, 048 ASN1Sequence seq) 049 { 050 // TODO Is it possible to get the order(n) and cofactor(h) too? 051 052 fieldIdentifier = fieldID.getIdentifier(); 053 if (fieldIdentifier.equals(prime_field)) 054 { 055 BigInteger p = ((ASN1Integer)fieldID.getParameters()).getValue(); 056 X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0)); 057 X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1)); 058 curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); 059 } 060 else if (fieldIdentifier.equals(characteristic_two_field)) 061 { 062 // Characteristic two field 063 ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters()); 064 int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue(). 065 intValue(); 066 ASN1ObjectIdentifier representation 067 = (ASN1ObjectIdentifier)parameters.getObjectAt(1); 068 069 int k1 = 0; 070 int k2 = 0; 071 int k3 = 0; 072 073 if (representation.equals(tpBasis)) 074 { 075 // Trinomial basis representation 076 k1 = ASN1Integer.getInstance(parameters.getObjectAt(2)).getValue().intValue(); 077 } 078 else if (representation.equals(ppBasis)) 079 { 080 // Pentanomial basis representation 081 ASN1Sequence pentanomial = ASN1Sequence.getInstance(parameters.getObjectAt(2)); 082 k1 = ASN1Integer.getInstance(pentanomial.getObjectAt(0)).getValue().intValue(); 083 k2 = ASN1Integer.getInstance(pentanomial.getObjectAt(1)).getValue().intValue(); 084 k3 = ASN1Integer.getInstance(pentanomial.getObjectAt(2)).getValue().intValue(); 085 } 086 else 087 { 088 throw new IllegalArgumentException("This type of EC basis is not implemented"); 089 } 090 X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0)); 091 X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1)); 092 curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); 093 } 094 else 095 { 096 throw new IllegalArgumentException("This type of ECCurve is not implemented"); 097 } 098 099 if (seq.size() == 3) 100 { 101 seed = ((DERBitString)seq.getObjectAt(2)).getBytes(); 102 } 103 } 104 105 private void setFieldIdentifier() 106 { 107 if (ECAlgorithms.isFpCurve(curve)) 108 { 109 fieldIdentifier = prime_field; 110 } 111 else if (ECAlgorithms.isF2mCurve(curve)) 112 { 113 fieldIdentifier = characteristic_two_field; 114 } 115 else 116 { 117 throw new IllegalArgumentException("This type of ECCurve is not implemented"); 118 } 119 } 120 121 public ECCurve getCurve() 122 { 123 return curve; 124 } 125 126 public byte[] getSeed() 127 { 128 return seed; 129 } 130 131 /** 132 * Produce an object suitable for an ASN1OutputStream. 133 * <pre> 134 * Curve ::= SEQUENCE { 135 * a FieldElement, 136 * b FieldElement, 137 * seed BIT STRING OPTIONAL 138 * } 139 * </pre> 140 */ 141 public ASN1Primitive toASN1Primitive() 142 { 143 ASN1EncodableVector v = new ASN1EncodableVector(); 144 145 if (fieldIdentifier.equals(prime_field)) 146 { 147 v.add(new X9FieldElement(curve.getA()).toASN1Primitive()); 148 v.add(new X9FieldElement(curve.getB()).toASN1Primitive()); 149 } 150 else if (fieldIdentifier.equals(characteristic_two_field)) 151 { 152 v.add(new X9FieldElement(curve.getA()).toASN1Primitive()); 153 v.add(new X9FieldElement(curve.getB()).toASN1Primitive()); 154 } 155 156 if (seed != null) 157 { 158 v.add(new DERBitString(seed)); 159 } 160 161 return new DERSequence(v); 162 } 163}