/* 多数決論理関数による鍵発生 鍵を2つ与え、1つをマスターとし、1つをレファレンスとして、残り2個の鍵を発生する Created by Osaka(2011/2/28) */ import java.io.* ; import java.util.* ; import java.security.* ; public class MajorityFunc2 { public final static String RANDOM_ALGORITHM = "SHA1PRNG" ; //public final static int KEY_LENGTH = 16 ; public final static int KEY_LENGTH = 4 ; public static void main( String args[ ] ) { MajorityFunc2 mf = new MajorityFunc2( ) ; BitSet bs = mf.getRandBitset( ) ; BitSet a1 = mf.getRandBitset( ) ; BitSet[ ] x = mf.generateKey( bs, a1 ) ; // 主鍵bs、副鍵a1から多数決論理関数に合致する2鍵a2、a3を求める BitSet a2 = x[ 0 ] ; BitSet a3 = x[ 1 ] ; System.out.print( "k:" ) ; mf.dispBitset( bs ) ; System.out.println( "----------------------------------" ) ; System.out.print( "x:" ) ; mf.dispBitset( a1 ) ; System.out.print( "y:" ) ; mf.dispBitset( a2 ) ; System.out.print( "z:" ) ; mf.dispBitset( a3 ) ; BitSet b123 = mf.majority( a1, a2, a3 ) ; // 多数決論理関数で、副鍵から主鍵を求める System.out.println( "----------------------------------" ) ; System.out.print( "f:" ) ; mf.dispBitset( b123 ) ; } // BitSetの多数決論理関数 majority(x, y, z) = ( (x&y) | (y&z) | (z&x) ) public BitSet majority( BitSet x, BitSet y, BitSet z ) { BitSet b12 = (BitSet)x.clone( ) ; b12.and ( y ) ; BitSet b23 = (BitSet)y.clone( ) ; b23.and ( z ) ; BitSet b31 = (BitSet)z.clone( ) ; b31.and ( x ) ; b23.or( b31 ) ; BitSet b123 = (BitSet)b12.clone( ) ; b123.or( b23 ) ; return b123 ; } // 乱数バイト数のBitSetを得る public BitSet getRandBitset( ) { byte[ ] bb = getRandom( ) ; BitSet bs = bytesToBitSet( bb ) ; bb = toByteArray( bs ) ; return bs ; } // 乱数の発生 public byte[ ] getRandom( ) { byte[ ] b = new byte[ KEY_LENGTH ] ; try { SecureRandom random = SecureRandom.getInstance( RANDOM_ALGORITHM ) ; byte[ ] seed = random.generateSeed( KEY_LENGTH ) ; random.setSeed( seed ) ; random.nextBytes( b ) ; } catch ( Exception e ) { e.printStackTrace( ) ; } return b ; } // bitsetの表示 public void dispBitset( BitSet bitset ) { for ( int i = 0; i < KEY_LENGTH * 8; i++ ) { if ( bitset.get( i ) ) System.out.print( "1" ) ; else System.out.print( "0" ) ; } System.out.print( "\n" ) ; } // 2つの鍵b1(主鍵)、b2(副鍵)から多数決論理関数に合致する2つの副鍵a2、a3を生成 public BitSet[ ] generateKey( BitSet b1, BitSet b2 ) { BitSet a2 = new BitSet( ) ; BitSet a3 = new BitSet( ) ; for ( int i = 0; i < KEY_LENGTH * 8; i++ ) { //b1(0) = majority(b2(1),a2(0),a3(0)) if ( !b1.get( i ) && b2.get( i ) ) { a2.set( i, false ) ; a3.set( i, false ) ; } //b1(1) = majority(b2(0),a2(1),a3(1)) else if ( b1.get( i ) && !b2.get( i ) ) { a2.set( i, true ) ; a3.set( i, true ) ; } //b1(0) = majority(b2(0),a2(0),a3(0)), majority(b2(0),a2(0),a3(1)), majority(b2(0),a2(1),a3(0)) else if ( !b1.get( i ) && !b2.get( i ) ) { int v = (int)( Math.floor( Math.random( ) * 3 ) ) ; switch ( v ) { case 0 : a2.set( i, false ) ; a3.set( i, false ) ; break ; case 1 : a2.set( i, false ) ; a3.set( i, true ) ; break ; case 2 : a2.set( i, true ) ; a3.set( i, false ) ; break ; } } //b1(1) = majority(b2(1),a2(0),a3(1)), majority(b2(1),a2(1),a3(0)), majority(b2(1),a2(1),a3(1)) else if ( b1.get( i ) && b2.get( i ) ) { int v = (int)( Math.floor( Math.random( ) * 3 ) ) ; switch ( v ) { case 0 : a2.set( i, false ) ; a3.set( i, true ) ; break ; case 1 : a2.set( i, true ) ; a3.set( i, false ) ; break ; case 2 : a2.set( i, true ) ; a3.set( i, true ) ; break ; } } } BitSet x[ ] = new BitSet[ 2 ] ; x[ 0 ] = a2 ; x[ 1 ] = a3 ; return x ; } public BitSet bytesToBitSet( byte[ ] bytes ) { BitSet bits = new BitSet( bytes.length ) ; int i = 0, j, k ; bits.clear( ) ; if ( bytes.length > KEY_LENGTH ) i = 1 ; for ( k = 0; i < bytes.length; i++ ) { for ( j = 0x80; j != 0; j >>>= 1, k++ ) { if ( ( bytes[ i ] & j ) != 0 ) bits.set( k ) ; } } //System.out.println( "bytesToBitSet : " + bytes.length + " " + bits.size( ) ) ; return bits ; } // Returns a byte array of at least length 1. // The most significant bit in the result is guaranteed not to be a 1 // (since BitSet does not support sign extension). // The byte-ordering of the result is big-endian which means the most significant bit is in element 0. // The bit at index 0 of the bit set is assumed to be the least significant bit. public byte[ ] toByteArray( BitSet bits ) { byte[ ] bytes = new byte[ bits.length( ) / 8 + 1 ] ; for ( int i = 0; i < KEY_LENGTH * 8; i++ ) { if ( bits.get( i ) ) bytes[ bytes.length - i / 8 - 1 ] |= 1 << ( i % 8 ) ; } bytes = checkByte( bytes ) ; return bytes ; } // なぜか1バイト0x00が入るため、これを削除 private byte[ ] checkByte( byte[ ] a ) { byte[ ] b = new byte[ KEY_LENGTH ] ; if ( a.length > KEY_LENGTH ) { for ( int i = 1; i < a.length; i++ ) b[ i - 1 ] = a[ i ] ; } else b = a ; return b ; } }