http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/AES.go ---------------------------------------------------------------------- diff --git a/version22/go/AES.go b/version22/go/AES.go new file mode 100644 index 0000000..1aeb6d7 --- /dev/null +++ b/version22/go/AES.go @@ -0,0 +1,634 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +/* AES Encryption */ + +package main + +//import "fmt" + +const aes_ECB int=0 +const aes_CBC int=1 +const aes_CFB1 int=2 +const aes_CFB2 int=3 +const aes_CFB4 int=5 +const aes_OFB1 int=14 +const aes_OFB2 int=15 +const aes_OFB4 int=17 +const aes_OFB8 int=21 +const aes_OFB16 int=29 +const aes_CTR1 int=30 +const aes_CTR2 int=31 +const aes_CTR4 int=33 +const aes_CTR8 int=37 +const aes_CTR16 int=45 + +var aes_InCo = [...]byte {0xB,0xD,0x9,0xE} /* Inverse Coefficients */ + +var aes_ptab = [...]byte { + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, + 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, + 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, + 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, + 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, + 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, + 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, + 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, + 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, + 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, + 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, + 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, + 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, + 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1} + +var aes_ltab = [...]byte { + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, + 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, + 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, + 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, + 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, + 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, + 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, + 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, + 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, + 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, + 127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, + 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, + 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, + 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, + 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7} + + +var aes_fbsub = [...]byte { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22} + +var aes_rbsub = [...]byte { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, + 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, + 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, + 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, + 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, + 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, + 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125} + + +var aes_rco = [...]byte {1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47} + +var aes_ftable = [...]uint32 { + 0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6, + 0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56, + 0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f, + 0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb, + 0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453, + 0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c, + 0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551, + 0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a, + 0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637, + 0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df, + 0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d, + 0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b, + 0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd, + 0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1, + 0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d, + 0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85, + 0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a, + 0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe, + 0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d, + 0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1, + 0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5, + 0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3, + 0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755, + 0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6, + 0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54, + 0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428, + 0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264, + 0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8, + 0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531, + 0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda, + 0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac, + 0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810, + 0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657, + 0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e, + 0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c, + 0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c, + 0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199, + 0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122, + 0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c, + 0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5, + 0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7, + 0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e, + 0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c} + +var aes_rtable = [...]uint32 { + 0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f, + 0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5, + 0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25, + 0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b, + 0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458, + 0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927, + 0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5, + 0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9, + 0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72, + 0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3, + 0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7, + 0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4, + 0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040, + 0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d, + 0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6, + 0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879, + 0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32, + 0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36, + 0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793, + 0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c, + 0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2, + 0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3, + 0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb, + 0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684, + 0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc, + 0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947, + 0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9, + 0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f, + 0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890, + 0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf, + 0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e, + 0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef, + 0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a, + 0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733, + 0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43, + 0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546, + 0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92, + 0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb, + 0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255, + 0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478, + 0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc, + 0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664, + 0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0} + +type AES struct { + Nk int + Nr int + mode int + fkey [60]uint32 + rkey [60]uint32 + f [16]byte +} + +/* Rotates 32-bit word left by 1, 2 or 3 byte */ + +func aes_ROTL8(x uint32) uint32 { + return (((x)<<8)|((x)>>24)) +} + +func aes_ROTL16(x uint32) uint32 { + return (((x)<<16)|((x)>>16)) +} + +func aes_ROTL24(x uint32) uint32 { + return (((x)<<24)|((x)>>8)) +} + +func aes_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */ + return ((uint32(b[3])&0xff)<<24)|((uint32(b[2])&0xff)<<16)|((uint32(b[1])&0xff)<<8)|(uint32(b[0])&0xff) +} + +func aes_unpack(a uint32) [4]byte { /* unpack bytes from a word */ + var b=[4]byte{byte(a&0xff),byte((a>>8)&0xff),byte((a>>16)&0xff),byte((a>>24)&0xff)} + return b; +} + +func aes_bmul(x byte,y byte) byte { /* x.y= AntiLog(Log(x) + Log(y)) */ + + ix:=int(x)&0xff + iy:=int(y)&0xff + lx:=int(aes_ltab[ix])&0xff + ly:=int(aes_ltab[iy])&0xff + + if x != 0 && y != 0 { + return aes_ptab[(lx+ly)%255] + } else {return byte(0)} +} + +func aes_SubByte(a uint32) uint32 { + b:=aes_unpack(a) + b[0]=aes_fbsub[int(b[0])] + b[1]=aes_fbsub[int(b[1])] + b[2]=aes_fbsub[int(b[2])] + b[3]=aes_fbsub[int(b[3])] + return aes_pack(b); +} + +func aes_product(x uint32,y uint32) byte { /* dot product of two 4-byte arrays */ + xb:=aes_unpack(x) + yb:=aes_unpack(y) + + return (aes_bmul(xb[0],yb[0])^aes_bmul(xb[1],yb[1])^aes_bmul(xb[2],yb[2])^aes_bmul(xb[3],yb[3])) +} + +func aes_InvMixCol(x uint32) uint32 { /* matrix Multiplication */ + var b [4]byte + m:=aes_pack(aes_InCo) + b[3]=aes_product(m,x) + m=aes_ROTL24(m) + b[2]=aes_product(m,x) + m=aes_ROTL24(m) + b[1]=aes_product(m,x) + m=aes_ROTL24(m) + b[0]=aes_product(m,x) + var y=aes_pack(b) + return y +} + +func aes_increment(f []byte) { + for i:=0;i<16;i++ { + f[i]++ + if f[i]!=0 {break} + } +} + +/* reset cipher */ +func (A *AES) Reset(m int,iv []byte) { /* reset mode, or reset iv */ + A.mode=m; + for i:=0;i<16;i++ {A.f[i]=0} + if (A.mode != aes_ECB) && (iv != nil) { + for i:=0;i<16;i++ {A.f[i]=iv[i]} + } +} + +func (A *AES) Init(m int,nk int,key []byte,iv []byte) bool { +/* Key Scheduler. Create expanded encryption key */ + var CipherKey [8]uint32 + var b [4]byte + nk/=4 + if nk!=4 && nk!=6 && nk!=8 {return false} + nr:=6+nk + A.Nk=nk + A.Nr=nr + A.Reset(m,iv); + N:=4*(nr+1) + + j:=0 + for i:=0;i<nk;i++ { + for k:=0;k<4;k++ {b[k]=key[j+k]} + CipherKey[i]=aes_pack(b); + j+=4; + } + for i:=0;i<nk;i++ {A.fkey[i]=CipherKey[i]} + j=nk + for k:=0;j<N;k++ { + A.fkey[j]=A.fkey[j-nk]^aes_SubByte(aes_ROTL24(A.fkey[j-1]))^uint32(aes_rco[k]) + for i:=1;i<nk && (i+j)<N;i++ { + A.fkey[i+j]=A.fkey[i+j-nk]^A.fkey[i+j-1] + } + j+=nk + } + + /* now for the expanded decrypt key in reverse order */ + + for j:=0;j<4;j++ {A.rkey[j+N-4]=A.fkey[j]} + for i:=4;i<N-4;i+=4 { + k:=N-4-i; + for j:=0;j<4;j++ {A.rkey[k+j]=aes_InvMixCol(A.fkey[i+j])} + } + for j:=N-4;j<N;j++ {A.rkey[j-N+4]=A.fkey[j]} + return true +} + +func NewAES() *AES { + var A=new(AES) + return A +} + +func (A *AES) Getreg() [16]byte { + var ir [16]byte + for i:=0;i<16;i++ {ir[i]=A.f[i]} + return ir +} + + /* Encrypt a single block */ +func (A *AES) ecb_encrypt(buff []byte) { + var b [4]byte + var p [4]uint32 + var q [4]uint32 + + j:=0 + for i:=0;i<4;i++ { + for k:=0;k<4;k++ {b[k]=buff[j+k]} + p[i]=aes_pack(b) + p[i]^=A.fkey[i] + j+=4 + } + + k:=4 + + /* State alternates between p and q */ + for i:=1;i<A.Nr;i++ { + q[0]=A.fkey[k]^aes_ftable[int(p[0]&0xff)]^aes_ROTL8(aes_ftable[int((p[1]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[2]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[3]>>24)&0xff)]) + + q[1]=A.fkey[k+1]^aes_ftable[int(p[1]&0xff)]^aes_ROTL8(aes_ftable[int((p[2]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[3]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[0]>>24)&0xff)]) + + q[2]=A.fkey[k+2]^aes_ftable[int(p[2]&0xff)]^aes_ROTL8(aes_ftable[int((p[3]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[0]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[1]>>24)&0xff)]) + + q[3]=A.fkey[k+3]^aes_ftable[int(p[3]&0xff)]^aes_ROTL8(aes_ftable[int((p[0]>>8)&0xff)])^aes_ROTL16(aes_ftable[int((p[1]>>16)&0xff)])^aes_ROTL24(aes_ftable[int((p[2]>>24)&0xff)]) + + k+=4; + for j=0;j<4;j++ { + t:=p[j]; p[j]=q[j]; q[j]=t + } + } + + /* Last Round */ + + q[0]=A.fkey[k]^uint32(aes_fbsub[int(p[0]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[1]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[2]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[3]>>24)&0xff)])) + + q[1]=A.fkey[k+1]^uint32(aes_fbsub[int(p[1]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[2]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[3]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[0]>>24)&0xff)])) + + q[2]=A.fkey[k+2]^uint32(aes_fbsub[int(p[2]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[3]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[0]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[1]>>24)&0xff)])) + + q[3]=A.fkey[k+3]^uint32(aes_fbsub[int(p[3]&0xff)])^aes_ROTL8(uint32(aes_fbsub[int((p[0]>>8)&0xff)]))^aes_ROTL16(uint32(aes_fbsub[int((p[1]>>16)&0xff)]))^aes_ROTL24(uint32(aes_fbsub[int((p[2]>>24)&0xff)])) + + j=0 + for i:=0;i<4;i++ { + b=aes_unpack(q[i]) + for k=0;k<4;k++ {buff[j+k]=b[k]} + j+=4 + } +} + + /* Decrypt a single block */ +func (A *AES) ecb_decrypt(buff []byte) { + var b [4]byte + var p [4]uint32 + var q [4]uint32 + + j:=0 + for i:=0;i<4;i++ { + for k:=0;k<4;k++ {b[k]=buff[j+k]} + p[i]=aes_pack(b) + p[i]^=A.rkey[i] + j+=4 + } + + k:=4 + + /* State alternates between p and q */ + for i:=1;i<A.Nr;i++ { + + q[0]=A.rkey[k]^aes_rtable[int(p[0]&0xff)]^aes_ROTL8(aes_rtable[int((p[3]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[2]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[1]>>24)&0xff)]) + + q[1]=A.rkey[k+1]^aes_rtable[int(p[1]&0xff)]^aes_ROTL8(aes_rtable[int((p[0]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[3]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[2]>>24)&0xff)]) + + + q[2]=A.rkey[k+2]^aes_rtable[int(p[2]&0xff)]^aes_ROTL8(aes_rtable[int((p[1]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[0]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[3]>>24)&0xff)]) + + q[3]=A.rkey[k+3]^aes_rtable[int(p[3]&0xff)]^aes_ROTL8(aes_rtable[int((p[2]>>8)&0xff)])^aes_ROTL16(aes_rtable[int((p[1]>>16)&0xff)])^aes_ROTL24(aes_rtable[int((p[0]>>24)&0xff)]) + + + k+=4; + for j:=0;j<4;j++ { + t:=p[j]; p[j]=q[j]; q[j]=t + } + } + + /* Last Round */ + + q[0]=A.rkey[k]^uint32(aes_rbsub[int(p[0]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[3]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[2]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[1]>>24)&0xff)])) + + q[1]=A.rkey[k+1]^uint32(aes_rbsub[int(p[1]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[0]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[3]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[2]>>24)&0xff)])) + + + q[2]=A.rkey[k+2]^uint32(aes_rbsub[int(p[2]&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[1]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[0]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[3]>>24)&0xff)])) + + q[3]=A.rkey[k+3]^uint32(aes_rbsub[int((p[3])&0xff)])^aes_ROTL8(uint32(aes_rbsub[int((p[2]>>8)&0xff)]))^aes_ROTL16(uint32(aes_rbsub[int((p[1]>>16)&0xff)]))^aes_ROTL24(uint32(aes_rbsub[int((p[0]>>24)&0xff)])) + + j=0 + for i:=0;i<4;i++ { + b=aes_unpack(q[i]); + for k:=0;k<4;k++ {buff[j+k]=b[k]} + j+=4 + } +} + +/* Encrypt using selected mode of operation */ +func (A *AES) Encrypt(buff []byte) uint32 { + var st [16]byte + + // Supported Modes of Operation + + var fell_off uint32=0 + switch A.mode { + case aes_ECB: + A.ecb_encrypt(buff) + return 0 + case aes_CBC: + for j:=0;j<16;j++ {buff[j]^=A.f[j]} + A.ecb_encrypt(buff) + for j:=0;j<16;j++ {A.f[j]=buff[j]} + return 0 + + case aes_CFB1: + fallthrough + case aes_CFB2: + fallthrough + case aes_CFB4: + bytes:=A.mode-aes_CFB1+1 + for j:=0;j<bytes;j++ {fell_off=(fell_off<<8)|uint32(A.f[j])} + for j:=0;j<16;j++ {st[j]=A.f[j]} + for j:=bytes;j<16;j++ {A.f[j-bytes]=A.f[j]} + A.ecb_encrypt(st[:]) + for j:=0;j<bytes;j++ { + buff[j]^=st[j] + A.f[16-bytes+j]=buff[j] + } + return fell_off + + case aes_OFB1: + fallthrough + case aes_OFB2: + fallthrough + case aes_OFB4: + fallthrough + case aes_OFB8: + fallthrough + case aes_OFB16: + + bytes:=A.mode-aes_OFB1+1 + A.ecb_encrypt(A.f[:]) + for j:=0;j<bytes;j++ {buff[j]^=A.f[j]} + return 0; + + case aes_CTR1: + fallthrough + case aes_CTR2: + fallthrough + case aes_CTR4: + fallthrough + case aes_CTR8: + fallthrough + case aes_CTR16: + bytes:=A.mode-aes_CTR1+1 + for j:=0;j<16;j++ {st[j]=A.f[j]} + A.ecb_encrypt(st[:]) + for j:=0;j<bytes;j++ {buff[j]^=st[j]} + aes_increment(A.f[:]) + return 0 + + default: + return 0 + } +} + + /* Decrypt using selected mode of operation */ +func (A *AES) Decrypt(buff []byte) uint32 { + + var st [16]byte + + // Supported Modes of Operation + + var fell_off uint32=0 + switch A.mode { + case aes_ECB: + A.ecb_decrypt(buff); + return 0; + case aes_CBC: + for j:=0;j<16;j++ { + st[j]=A.f[j]; + A.f[j]=buff[j]; + } + A.ecb_decrypt(buff); + for j:=0;j<16;j++ { + buff[j]^=st[j]; + st[j]=0 + } + return 0 + case aes_CFB1: + fallthrough + case aes_CFB2: + fallthrough + case aes_CFB4: + bytes:=A.mode-aes_CFB1+1; + for j:=0;j<bytes;j++ {fell_off=(fell_off<<8)|uint32(A.f[j])} + for j:=0;j<16;j++ {st[j]=A.f[j]} + for j:=bytes;j<16;j++ {A.f[j-bytes]=A.f[j]} + A.ecb_encrypt(st[:]) + for j:=0;j<bytes;j++ { + A.f[16-bytes+j]=buff[j] + buff[j]^=st[j] + } + return fell_off + case aes_OFB1: + fallthrough + case aes_OFB2: + fallthrough + case aes_OFB4: + fallthrough + case aes_OFB8: + fallthrough + case aes_OFB16: + bytes:=A.mode-aes_OFB1+1 + A.ecb_encrypt(A.f[:]); + for j:=0;j<bytes;j++ {buff[j]^=A.f[j]} + return 0 + + case aes_CTR1: + fallthrough + case aes_CTR2: + fallthrough + case aes_CTR4: + fallthrough + case aes_CTR8: + fallthrough + case aes_CTR16: + bytes:=A.mode-aes_CTR1+1 + for j:=0;j<16;j++ {st[j]=A.f[j]} + A.ecb_encrypt(st[:]) + for j:=0;j<bytes;j++ {buff[j]^=st[j]} + aes_increment(A.f[:]) + return 0 + + default: + return 0; + } + } + +/* Clean up and delete left-overs */ +func (A *AES) End() { // clean up + for i:=0;i<4*(A.Nr+1);i++ {A.fkey[i]=0; A.rkey[i]=0} + for i:=0;i<16;i++ {A.f[i]=0} +} +/* +func main() { + var key [32]byte + var block [16]byte + var iv [16]byte + + for i:=0;i<32;i++ {key[i]=0} + key[0]=1 + for i:=0;i<16;i++ {iv[i]=byte(i)} + for i:=0;i<16;i++ {block[i]=byte(i)} + + a:=NewAES() + + a.Init(aes_CTR16,32,key[:],iv[:]) + fmt.Printf("Plain= \n") + for i:=0;i<16;i++ {fmt.Printf("%02X ", block[i]&0xff)} + fmt.Printf("\n") + + a.Encrypt(block[:]) + + fmt.Printf("Encrypt= \n") + for i:=0;i<16;i++ {fmt.Printf("%02X ", block[i]&0xff)} + fmt.Printf("\n") + + a.Reset(aes_CTR16,iv[:]) + a.Decrypt(block[:]) + + fmt.Printf("Decrypt= \n") + for i:=0;i<16;i++ {fmt.Printf("%02X ", block[i]&0xff)} + fmt.Printf("\n") + + a.End(); +} +*/
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/BIG.go ---------------------------------------------------------------------- diff --git a/version22/go/BIG.go b/version22/go/BIG.go new file mode 100644 index 0000000..3e0eca5 --- /dev/null +++ b/version22/go/BIG.go @@ -0,0 +1,850 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +/* AMCL BIG number class */ + +package main + +import "strconv" +//import "fmt" + + +type BIG struct { + w [NLEN]Chunk +} + +type DBIG struct { + w [2*NLEN]Chunk +} + +func (r *BIG) get(i int) Chunk { + return r.w[i] +} + +func (r *BIG) set(i int,x Chunk) { + r.w[i]=x +} + +func (r *BIG) xortop(x Chunk) { + r.w[NLEN-1]^=x +} + +/* calculate Field Excess */ +func EXCESS(a *BIG) Chunk { + return ((a.w[NLEN-1]&OMASK)>>(MODBITS%BASEBITS)) +} + +func FF_EXCESS(a* BIG) Chunk { + return ((a.w[NLEN-1]&P_OMASK)>>(P_MB)) +} + +/* normalise BIG - force all digits < 2^BASEBITS */ +func (r *BIG) norm() Chunk { + carry:=Chunk(0) + for i:=0;i<NLEN-1;i++ { + d:=r.w[i]+carry + r.w[i]=d&BMASK + carry=d>>BASEBITS + } + r.w[NLEN-1]=(r.w[NLEN-1]+carry) + return (r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) +} + +/* Shift right by less than a word */ +func (r *BIG) fshr(k uint) int { + w:=r.w[0]&((Chunk(1)<<k)-1) /* shifted out part */ + for i:=0;i<NLEN-1;i++ { + r.w[i]=(r.w[i]>>k)|((r.w[i+1]<<(BASEBITS-k))&BMASK) + } + r.w[NLEN-1]=r.w[NLEN-1]>>k + return int(w) +} + +/* Shift right by less than a word */ +func (r *BIG) fshl(k uint) int { + r.w[NLEN-1]=((r.w[NLEN-1]<<k))|(r.w[NLEN-2]>>(BASEBITS-k)) + for i:=NLEN-2;i>0;i-- { + r.w[i]=((r.w[i]<<k)&BMASK)|(r.w[i-1]>>(BASEBITS-k)) + } + r.w[0]=(r.w[0]<<k)&BMASK + return int(r.w[NLEN-1]>>((8*MODBYTES)%BASEBITS)) /* return excess - only used in ff.c */ +} + +func NewBIG() *BIG { + b:=new(BIG) + for i:=0;i<NLEN;i++ { + b.w[i]=0 + } + return b +} + +func NewBIGints(x [NLEN]Chunk) *BIG { + b:=new(BIG) + for i:=0;i<NLEN;i++ { + b.w[i]=x[i] + } + return b +} + +func NewBIGint(x int) *BIG { + b:=new(BIG) + b.w[0]=Chunk(x) + for i:=1;i<NLEN;i++ { + b.w[i]=0 + } + return b +} + +func NewBIGcopy(x *BIG) *BIG { + b:=new(BIG) + for i:=0;i<NLEN;i++ { + b.w[i]=x.w[i] + } + return b +} + +func NewBIGdcopy(x *DBIG) *BIG { + b:=new(BIG) + for i:=0;i<NLEN;i++ { + b.w[i]=x.w[i] + } + return b +} + +/* test for zero */ +func (r *BIG) iszilch() bool { + for i:=0;i<NLEN;i++ { + if r.w[i]!=0 {return false} + } + return true; +} + +/* set to zero */ +func (r *BIG) zero() { + for i:=0;i<NLEN;i++ { + r.w[i]=0 + } +} + +/* Test for equal to one */ +func (r *BIG) isunity() bool { + for i:=1;i<NLEN;i++ { + if r.w[i]!=0 {return false} + } + if r.w[0]!=1 {return false} + return true; +} + + +/* set to one */ +func (r *BIG) one() { + r.w[0]=1 + for i:=1;i<NLEN;i++ { + r.w[i]=0 + } +} + +/* Copy from another BIG */ +func (r *BIG) copy(x *BIG) { + for i:=0;i<NLEN;i++ { + r.w[i]=x.w[i] + } +} + +/* Copy from another DBIG */ +func (r *BIG) dcopy(x *DBIG) { + for i:=0;i<NLEN;i++ { + r.w[i]=x.w[i] + } +} + +/* Conditional swap of two bigs depending on d using XOR - no branches */ +func (r *BIG) cswap(b *BIG,d int) { + c:=Chunk(d) + c=^(c-1) + + for i:=0;i<NLEN;i++ { + t:=c&(r.w[i]^b.w[i]) + r.w[i]^=t + b.w[i]^=t + } +} + +func (r *BIG) cmove(g *BIG,d int){ + b:=Chunk(-d) + + for i:=0;i<NLEN;i++ { + r.w[i]^=(r.w[i]^g.w[i])&b + } +} + +/* general shift right */ +func (r *BIG) shr(k uint) { + n:=(k%BASEBITS) + m:=int(k/BASEBITS) + for i:=0;i<NLEN-m-1;i++ { + r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK) + } + r.w[NLEN-m-1]=r.w[NLEN-1]>>n; + for i:=NLEN-m;i<NLEN;i++ {r.w[i]=0} +} + + +/* general shift left */ +func (r *BIG) shl(k uint) { + n:=k%BASEBITS + m:=int(k/BASEBITS) + + r.w[NLEN-1]=((r.w[NLEN-1-m]<<n)) + if NLEN>=m+2 {r.w[NLEN-1]|=(r.w[NLEN-m-2]>>(BASEBITS-n))} + for i:=NLEN-2;i>m;i-- { + r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n)) + } + r.w[m]=(r.w[0]<<n)&BMASK; + for i:=0;i<m;i++ {r.w[i]=0} +} + +/* return number of bits */ +func (r *BIG) nbits() int { + k:=NLEN-1 + r.norm() + for (k>=0 && r.w[k]==0) {k--} + if k<0 {return 0} + bts:=int(BASEBITS)*k; + c:=r.w[k]; + for c!=0 {c/=2; bts++} + return bts +} + +/* Convert to Hex String */ +func (r *BIG) toString() string { + s:="" + len:=r.nbits() + + if len%4==0 { + len/=4 + } else { + len/=4 + len++ + + } + MB:=int(MODBYTES*2) + if len<MB {len=MB} + + for i:=len-1;i>=0;i-- { + b:=NewBIGcopy(r) + + b.shr(uint(i*4)) + s+=strconv.FormatInt(int64(b.w[0]&15),16) + } + return s +} + +func (r *BIG) add(x *BIG) { + for i:=0;i<NLEN;i++ { + r.w[i]=r.w[i]+x.w[i] + } +} + +/* return this+x */ +func (r *BIG) plus(x *BIG) *BIG { + s:=new(BIG) + for i:=0;i<NLEN;i++ { + s.w[i]=r.w[i]+x.w[i]; + } + return s; +} + +/* this+=x, where x is int */ +func (r *BIG) inc(x int) { + r.norm(); + r.w[0]+=Chunk(x); +} + +/* this*=c and catch overflow in DBIG */ +func (r *BIG) pxmul(c int) *DBIG { + m:=NewDBIG() + carry:=Chunk(0) + for j:=0;j<NLEN;j++ { + carry,m.w[j]=muladd(r.w[j],Chunk(c),carry,m.w[j]) + } + m.w[NLEN]=carry; + return m; +} + +/* return this-x */ +func (r *BIG) minus(x *BIG) *BIG { + d:=new(BIG) + for i:=0;i<NLEN;i++ { + d.w[i]=r.w[i]-x.w[i] + } + return d; +} + +/* this-=x */ +func (r *BIG) sub(x *BIG) { + for i:=0;i<NLEN;i++ { + r.w[i]=r.w[i]-x.w[i] + } +} + +/* reverse subtract this=x-this */ +func (r *BIG) rsub(x *BIG) { + for i:=0;i<NLEN;i++ { + r.w[i]=x.w[i]-r.w[i] + } +} + +/* this-=x, where x is int */ +func (r *BIG) dec(x int) { + r.norm(); + r.w[0]-=Chunk(x) +} + +/* this*=x, where x is small int<NEXCESS */ +func (r *BIG) imul(c int) { + for i:=0;i<NLEN;i++{ + r.w[i]*=Chunk(c) + } +} + +/* this*=x, where x is >NEXCESS */ +func (r *BIG) pmul(c int) Chunk { + carry:=Chunk(0) + r.norm(); + for i:=0;i<NLEN;i++ { + ak:=r.w[i] + r.w[i]=0 + carry,r.w[i]=muladd(ak,Chunk(c),carry,r.w[i]) + } + return carry +} + +/* convert this BIG to byte array */ +func (r *BIG) tobytearray(b []byte,n int) { + r.norm(); + c:=NewBIGcopy(r) + + for i:=int(MODBYTES)-1;i>=0;i-- { + b[i+n]=byte(c.w[0]) + c.fshr(8) + } +} + +/* convert from byte array to BIG */ +func frombytearray(b []byte,n int) *BIG { + m:=NewBIG(); + for i:=0;i<int(MODBYTES);i++ { + m.fshl(8); m.w[0]+=Chunk(int(b[i+n]&0xff)) + } + return m +} + +func (r *BIG) toBytes(b []byte) { + r.tobytearray(b,0) +} + +func fromBytes(b []byte) *BIG { + return frombytearray(b,0) +} + +/* divide by 3 */ +func (r *BIG) div3() int { + carry:=Chunk(0) + r.norm(); + base:=(Chunk(1)<<BASEBITS) + for i:=NLEN-1;i>=0;i-- { + ak:=(carry*base+r.w[i]) + r.w[i]=ak/3; + carry=ak%3; + } + return int(carry) +} + +/* return a*b where result fits in a BIG */ +func smul(a *BIG,b *BIG) *BIG { + carry:=Chunk(0) + c:=NewBIG() + for i:=0;i<NLEN;i++ { + carry=0; + for j:=0;j<NLEN;j++ { + if i+j<NLEN { + carry,c.w[i+j]=muladd(a.w[i],b.w[j],carry,c.w[i+j]) + //carry=c.muladd(a.w[i],b.w[j],carry,i+j) + } + } + } + return c; +} + +/* reduce a DBIG to a BIG using the appropriate form of the modulus */ +func mod(d *DBIG) *BIG { + if MODTYPE==PSEUDO_MERSENNE { + t:=d.split(MODBITS) + b:=NewBIGdcopy(d) + + v:=t.pmul(int(MConst)) + tw:=t.w[NLEN-1] + t.w[NLEN-1]&=TMASK + t.w[0]+=(MConst*((tw>>TBITS)+(v<<(BASEBITS-TBITS)))) + + b.add(t) + b.norm() + return b + } + if MODTYPE==MONTGOMERY_FRIENDLY { + for i:=0;i<NLEN;i++ { + top,bot:=muladd(d.w[i],MConst-1,d.w[i],d.w[NLEN+i-1]) + d.w[NLEN+i-1]=bot + d.w[NLEN+i]+=top + //d.w[NLEN+i]+=d.muladd(d.w[i],MConst-1,d.w[i],NLEN+i-1) + } + b:=NewBIG() + + for i:=0;i<NLEN;i++ { + b.w[i]=d.w[NLEN+i] + } + b.norm() + return b + } + + if MODTYPE==GENERALISED_MERSENNE { // GoldiLocks only + t:=d.split(MODBITS) + b:=NewBIGdcopy(d) + b.add(t); + dd:=NewDBIGscopy(t) + dd.shl(MODBITS/2) + + tt:=dd.split(MODBITS) + lo:=NewBIGdcopy(dd) + b.add(tt) + b.add(lo) + b.norm() + tt.shl(MODBITS/2) + b.add(tt) + + carry:=b.w[NLEN-1]>>TBITS + b.w[NLEN-1]&=TMASK + b.w[0]+=carry + + b.w[224/BASEBITS]+=carry<<(224%BASEBITS); + b.norm() + return b + } + + if MODTYPE==NOT_SPECIAL { + md:=NewBIGints(Modulus) + return monty(md,MConst,d) + } + return NewBIG() +} + +/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */ +func comp(a *BIG,b *BIG) int { + for i:=NLEN-1;i>=0;i-- { + if a.w[i]==b.w[i] {continue} + if a.w[i]>b.w[i] { + return 1 + } else {return -1} + } + return 0 +} + +/* return parity */ +func (r *BIG) parity() int { + return int(r.w[0]%2) +} + +/* return n-th bit */ +func (r *BIG) bit(n int) int { + if (r.w[n/int(BASEBITS)]&(Chunk(1)<<(uint(n)%BASEBITS)))>0 {return 1} + return 0; +} + +/* return n last bits */ +func (r *BIG) lastbits(n int) int { + msk:=(1<<uint(n))-1; + r.norm(); + return (int(r.w[0]))&msk +} + + +/* set x = x mod 2^m */ +func (r *BIG) mod2m(m uint) { + wd:=int(m/BASEBITS) + bt:=m%BASEBITS + msk:=(Chunk(1)<<bt)-1 + r.w[wd]&=msk + for i:=wd+1;i<NLEN;i++ {r.w[i]=0} +} + +/* Arazi and Qi inversion mod 256 */ +func invmod256(a int) int { + var t1 int=0 + c:=(a>>1)&1 + t1+=c + t1&=1 + t1=2-t1 + t1<<=1 + U:=t1+1; + +// i=2 + b:=a&3; + t1=U*b; t1>>=2 + c=(a>>2)&3 + t2:=(U*c)&3 + t1+=t2; + t1*=U; t1&=3 + t1=4-t1 + t1<<=2 + U+=t1 + +// i=4 + b=a&15 + t1=U*b; t1>>=4 + c=(a>>4)&15 + t2=(U*c)&15 + t1+=t2 + t1*=U; t1&=15 + t1=16-t1 + t1<<=4 + U+=t1 + + return U; +} + +/* a=1/a mod 2^256. This is very fast! */ +func (r *BIG) invmod2m() { + U:=NewBIG() + b:=NewBIG() + c:=NewBIG() + + U.inc(invmod256(r.lastbits(8))) + + for i:=8;i<BIGBITS;i<<=1 { + ui:=uint(i); + b.copy(r); b.mod2m(ui) + t1:=smul(U,b); t1.shr(ui) + c.copy(r); c.shr(ui); c.mod2m(ui) + + t2:=smul(U,c); t2.mod2m(ui) + t1.add(t2) + b=smul(t1,U); t1.copy(b) + t1.mod2m(ui); + + t2.one(); t2.shl(ui); t1.rsub(t2); t1.norm() + t1.shl(ui); + U.add(t1); + } + U.mod2m(8*MODBYTES) + r.copy(U) + r.norm() +} + +/* reduce this mod m */ +func (r *BIG) mod(m *BIG) { + sr:=NewBIG() + r.norm() + if comp(r,m)<0 {return} + + m.fshl(1); k:=1 + + for comp(r,m)>=0 { + m.fshl(1) + k++; + } + + for k>0 { + m.fshr(1); + + sr.copy(r) + sr.sub(m) + sr.norm() + r.cmove(sr,int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1))); +/* + if comp(r,m)>=0 { + r.sub(m) + r.norm() + } */ + k--; + } +} + +/* divide this by m */ +func (r *BIG) div(m *BIG) { + var d int + k:=0 + r.norm(); + sr:=NewBIG(); + e:=NewBIGint(1) + b:=NewBIGcopy(r) + r.zero(); + + for (comp(b,m)>=0) { + e.fshl(1) + m.fshl(1) + k++ + } + + for k>0 { + m.fshr(1) + e.fshr(1) + + sr.copy(b); + sr.sub(m); + sr.norm(); + d=int(1-((sr.w[NLEN-1]>>uint(CHUNK-1))&1)); + b.cmove(sr,d); + sr.copy(r); + sr.add(e); + sr.norm(); + r.cmove(sr,d); +/* + if comp(b,m)>=0 { + r.add(e) + r.norm() + b.sub(m) + b.norm() + } */ + k-- + } +} + +/* get 8*MODBYTES size random number */ +func random(rng *RAND) *BIG { + m:=NewBIG() + var j int=0 + var r byte=0 +/* generate random BIG */ + for i:=0;i<8*int(MODBYTES);i++ { + if j==0 { + r=rng.GetByte() + } else {r>>=1} + + b:=Chunk(int(r&1)) + m.shl(1); m.w[0]+=b// m.inc(b) + j++; j&=7; + } + return m; +} + +/* Create random BIG in portable way, one bit at a time */ +func randomnum(q *BIG,rng *RAND) *BIG { + d:=NewDBIG(); + var j int=0 + var r byte=0 + for i:=0;i<2*int(MODBITS);i++ { + if (j==0) { + r=rng.GetByte(); + } else {r>>=1} + + b:=Chunk(int(r&1)) + d.shl(1); d.w[0]+=b// m.inc(b); + j++; j&=7 + } + m:=d.mod(q) + return m; +} + + +/* return NAF value as +/- 1, 3 or 5. x and x3 should be normed. +nbs is number of bits processed, and nzs is number of trailing 0s detected */ +/* +func nafbits(x *BIG,x3 *BIG ,i int) [3]int { + var n [3]int + var j int + nb:=x3.bit(i)-x.bit(i) + + + n[1]=1 + n[0]=0 + if nb==0 {n[0]=0; return n} + if i==0 {n[0]=nb; return n} + if nb>0 { + n[0]=1; + } else {n[0]=(-1)} + + for j=i-1;j>0;j-- { + n[1]++ + n[0]*=2 + nb=x3.bit(j)-x.bit(j) + if nb>0 {n[0]+=1} + if nb<0 {n[0]-=1} + if (n[0]>5 || n[0] < -5) {break} + } + + if n[0]%2!=0 && j!=0 { // backtrack + if nb>0 {n[0]=(n[0]-1)/2} + if nb<0 {n[0]=(n[0]+1)/2} + n[1]-- + } + for n[0]%2==0 { // remove trailing zeros + n[0]/=2 + n[2]++ + n[1]-- + } + return n; +} +*/ + +/* return a*b mod m */ +func modmul(a,b,m *BIG) *BIG { + a.mod(m) + b.mod(m) + d:=mul(a,b); + return d.mod(m) +} + +/* return a^2 mod m */ +func modsqr(a,m *BIG) *BIG { + a.mod(m) + d:=sqr(a) + return d.mod(m) +} + +/* return -a mod m */ +func modneg(a,m *BIG) *BIG { + a.mod(m) + return m.minus(a) +} + +/* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ +func (r *BIG) jacobi(p *BIG) int { + m:=0; + t:=NewBIGint(0) + x:=NewBIGint(0) + n:=NewBIGint(0) + zilch:=NewBIGint(0) + one:=NewBIGint(1) + if (p.parity()==0 || comp(r,zilch)==0 || comp(p,one)<=0) {return 0} + r.norm() + x.copy(r) + n.copy(p) + x.mod(p) + + for comp(n,one)>0 { + if comp(x,zilch)==0 {return 0} + n8:=n.lastbits(3) + k:=0 + for x.parity()==0 { + k++ + x.shr(1) + } + if k%2==1 {m+=(n8*n8-1)/8} + m+=(n8-1)*(x.lastbits(2)-1)/4 + t.copy(n) + t.mod(x) + n.copy(x) + x.copy(t) + m%=2 + + } + if m==0 {return 1} + return -1 +} + +/* this=1/this mod p. Binary method */ +func (r *BIG) invmodp(p *BIG) { + r.mod(p) + u:=NewBIGcopy(r) + + v:=NewBIGcopy(p) + x1:=NewBIGint(1) + x2:=NewBIGint(0) + t:=NewBIGint(0) + one:=NewBIGint(1) + for (comp(u,one)!=0 && comp(v,one)!=0) { + for u.parity()==0 { + u.shr(1); + if x1.parity()!=0 { + x1.add(p) + x1.norm() + } + x1.shr(1) + } + for v.parity()==0 { + v.shr(1); + if x2.parity()!=0 { + x2.add(p) + x2.norm() + } + x2.shr(1) + } + if comp(u,v)>=0 { + u.sub(v) + u.norm() + if comp(x1,x2)>=0 { + x1.sub(x2) + } else { + t.copy(p) + t.sub(x2) + x1.add(t) + } + x1.norm() + } else { + v.sub(u) + v.norm() + if comp(x2,x1)>=0 { + x2.sub(x1) + } else { + t.copy(p) + t.sub(x1) + x2.add(t) + } + x2.norm() + } + } + if comp(u,one)==0 { + r.copy(x1) + } else {r.copy(x2)} +} + +/* return this^e mod m */ +func (r *BIG) powmod(e *BIG,m *BIG) *BIG { + r.norm() + e.norm() + a:=NewBIGint(1) + z:=NewBIGcopy(e) + s:=NewBIGcopy(r) + for true { + bt:=z.parity() + z.fshr(1) + if bt==1 {a=modmul(a,s,m)} + if z.iszilch() {break} + s=modsqr(s,m) + } + return a; +} +/* +func main() { + a := NewBIGint(3) + m := NewBIGints(Modulus) + + fmt.Printf("Modulus= "+m.toString()) + fmt.Printf("\n") + + + e := NewBIGcopy(m); + e.dec(1); e.norm(); + fmt.Printf("Exponent= "+e.toString()) + fmt.Printf("\n") + a=a.powmod(e,m); + fmt.Printf("Result= "+a.toString()) +} +*/ http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/BenchtestEC.go ---------------------------------------------------------------------- diff --git a/version22/go/BenchtestEC.go b/version22/go/BenchtestEC.go new file mode 100644 index 0000000..86510c0 --- /dev/null +++ b/version22/go/BenchtestEC.go @@ -0,0 +1,154 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +/* Test and benchmark elliptic curve and RSA functions */ + +package main + +import "fmt" + +import "time" + +const MIN_TIME int=10 +const MIN_ITERS int=10 + +func main() { + + var RAW [100]byte + var P [RSA_RFS]byte + var M [RSA_RFS]byte + var C [RSA_RFS]byte + + rng:=NewRAND() + + rng.Clean(); + for i:=0;i<100;i++ {RAW[i]=byte(i)} + + rng.Seed(100,RAW[:]) + + pub:=New_rsa_public_key(FFLEN) + priv:=New_rsa_private_key(HFLEN) + + if CURVETYPE==WEIERSTRASS { + fmt.Printf("Weierstrass parameterization\n") + } + if CURVETYPE==EDWARDS { + fmt.Printf("Edwards parameterization\n") + } + if CURVETYPE==MONTGOMERY { + fmt.Printf("Montgomery parameterization\n") + } + + if MODTYPE==PSEUDO_MERSENNE { + fmt.Printf("Pseudo-Mersenne Modulus\n") + } + if MODTYPE==MONTGOMERY_FRIENDLY { + fmt.Printf("Montgomery friendly Modulus\n") + } + if MODTYPE==GENERALISED_MERSENNE { + fmt.Printf("Generalised-Mersenne Modulus\n") + } + if MODTYPE==NOT_SPECIAL { + fmt.Printf("Not special Modulus\n") + } + + fmt.Printf("Modulus size %d bits\n",MODBITS) + fmt.Printf("%d bit build\n",CHUNK) + + var s *BIG + var G *ECP + + gx:=NewBIGints(CURVE_Gx) + if CURVETYPE!=MONTGOMERY { + gy:=NewBIGints(CURVE_Gy) + G=NewECPbigs(gx,gy) + } else { + G=NewECPbig(gx) + } + + r:=NewBIGints(CURVE_Order) + s=randomnum(r,rng) + + WP:=G.mul(r) + if !WP.is_infinity() { + fmt.Printf("FAILURE - rG!=O\n") + return + } + + start := time.Now() + iterations:=0 + elapsed:=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + WP=G.mul(s) + iterations++ + elapsed=time.Since(start) + } + dur:=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("EC mul - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + fmt.Printf("Generating %d-bit RSA public/private key pair\n",FFLEN*BIGBITS); + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + RSA_KEY_PAIR(rng,65537,priv,pub) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("RSA gen - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + for i:=0;i<RSA_RFS;i++ {M[i]=byte(i%128)}; + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + RSA_ENCRYPT(pub,M[:],C[:]) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("RSA enc - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + RSA_DECRYPT(priv,C[:],P[:]) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("RSA dec - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + for i:=0;i<RSA_RFS;i++ { + if (P[i]!=M[i]) { + fmt.Printf("FAILURE - RSA decryption\n") + return + } + } + + fmt.Printf("All tests pass\n") +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/BenchtestPAIR.go ---------------------------------------------------------------------- diff --git a/version22/go/BenchtestPAIR.go b/version22/go/BenchtestPAIR.go new file mode 100644 index 0000000..bb1f710 --- /dev/null +++ b/version22/go/BenchtestPAIR.go @@ -0,0 +1,206 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +/* Test and benchmark elliptic curve and RSA functions */ + +package main + +import "fmt" + +import "time" + +const MIN_TIME int=10 +const MIN_ITERS int=10 + +func main() { + var RAW [100]byte + + rng:=NewRAND() + + rng.Clean(); + for i:=0;i<100;i++ {RAW[i]=byte(i)} + + rng.Seed(100,RAW[:]) + + if CURVE_PAIRING_TYPE==BN_CURVE { + fmt.Printf("BN Pairing-Friendly Curve\n") + } + if CURVE_PAIRING_TYPE==BLS_CURVE { + fmt.Printf("BLS Pairing-Friendly Curve\n") + } + + fmt.Printf("Modulus size %d bits\n",MODBITS) + fmt.Printf("%d bit build\n",CHUNK) + + G:=NewECPbigs(NewBIGints(CURVE_Gx),NewBIGints(CURVE_Gy)) + r:=NewBIGints(CURVE_Order) + s:=randomnum(r,rng) + + P:=G1mul(G,r) + + if !P.is_infinity() { + fmt.Printf("FAILURE - rP!=O\n"); + return; + } + + start := time.Now() + iterations:=0 + elapsed:=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + P=G1mul(G,s) + iterations++ + elapsed=time.Since(start) + } + dur:=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("G1 mul - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + Q:=NewECP2fp2s(NewFP2bigs(NewBIGints(CURVE_Pxa),NewBIGints(CURVE_Pxb)),NewFP2bigs(NewBIGints(CURVE_Pya),NewBIGints(CURVE_Pyb))) + W:=G2mul(Q,r) + + if !W.is_infinity() { + fmt.Printf("FAILURE - rQ!=O\n"); + return; + } + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + W=G2mul(Q,s) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("G2 mul - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + w:=ate(Q,P) + w=fexp(w) + + g:=GTpow(w,r) + + if !g.isunity() { + fmt.Printf("FAILURE - g^r!=1\n"); + return; + } + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + g=GTpow(w,s) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("GT pow - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + f:=NewFP2bigs(NewBIGints(CURVE_Fra),NewBIGints(CURVE_Frb)) + q:=NewBIGints(Modulus) + + m:=NewBIGcopy(q) + m.mod(r) + + a:=NewBIGcopy(s) + a.mod(m) + + b:=NewBIGcopy(s) + b.div(m) + + g.copy(w) + c:=g.trace() + + g.frob(f) + cp:=g.trace() + + w.conj() + g.mul(w) + cpm1:=g.trace() + g.mul(w) + cpm2:=g.trace() + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + c=c.xtr_pow2(cp,cpm1,cpm2,a,b) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("GT pow (compressed) - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + w=ate(Q,P) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("PAIRing ATE - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + start = time.Now() + iterations=0 + elapsed=time.Since(start) + for (int(elapsed/time.Second))<MIN_TIME || iterations<MIN_ITERS { + g=fexp(w) + iterations++ + elapsed=time.Since(start) + } + dur=float64(elapsed/time.Millisecond)/float64(iterations) + fmt.Printf("PAIRing FEXP - %8d iterations ",iterations) + fmt.Printf(" %8.2f ms per iteration\n",dur) + + P.copy(G) + Q.copy(W) + + P=G1mul(P,s) + + g=ate(Q,P) + g=fexp(g) + + P.copy(G) + Q=G2mul(Q,s) + + w=ate(Q,P) + w=fexp(w) + + if !g.equals(w) { + fmt.Printf("FAILURE - e(sQ,p)!=e(Q,sP) \n") + return + } + + Q.copy(W); + g=ate(Q,P) + g=fexp(g) + g=GTpow(g,s) + + if !g.equals(w) { + fmt.Printf("FAILURE - e(sQ,p)!=e(Q,P)^s \n") + return + } + + fmt.Printf("All tests pass\n") +} http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/DBIG.go ---------------------------------------------------------------------- diff --git a/version22/go/DBIG.go b/version22/go/DBIG.go new file mode 100644 index 0000000..b58b0c0 --- /dev/null +++ b/version22/go/DBIG.go @@ -0,0 +1,256 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +/* MiotCL double length DBIG number class */ + + +package main + +import "strconv" +//import "fmt" + +func NewDBIG() *DBIG { + b:=new(DBIG) + for i:=0;i<DNLEN;i++ { + b.w[i]=0 + } + return b +} + +func NewDBIGcopy(x *DBIG) *DBIG { + b:=new(DBIG) + for i:=0;i<DNLEN;i++ { + b.w[i]=x.w[i] + } + return b +} + +func NewDBIGscopy(x *BIG) *DBIG { + b:=new(DBIG) + for i:=0;i<NLEN-1;i++ { + b.w[i]=x.w[i] + } + b.w[NLEN-1]=x.get(NLEN-1)&BMASK /* top word normalized */ + b.w[NLEN]=x.get(NLEN-1)>>BASEBITS + + for i:=NLEN+1;i<DNLEN;i++ {b.w[i]=0} + return b +} + +/* normalise this */ +func (r *DBIG) norm() { + carry:=Chunk(0) + for i:=0;i<DNLEN-1;i++ { + d:=r.w[i]+carry + r.w[i]=d&BMASK + carry=d>>BASEBITS + } + r.w[DNLEN-1]=(r.w[DNLEN-1]+carry) +} + +/* split DBIG at position n, return higher half, keep lower half */ +func (r *DBIG) split(n uint) *BIG { + t:=NewBIG() + m:=n%BASEBITS; + carry:=r.w[DNLEN-1]<<(BASEBITS-m) + + for i:=DNLEN-2;i>=NLEN-1;i-- { + nw:=(r.w[i]>>m)|carry; + carry=(r.w[i]<<(BASEBITS-m))&BMASK; + t.set(i-NLEN+1,nw); + } + r.w[NLEN-1]&=((Chunk(1)<<m)-1) + return t; +} + +func (r *DBIG) cmove(g *DBIG,d int){ + var b=Chunk(-d) + + for i:=0;i<DNLEN;i++ { + r.w[i]^=(r.w[i]^g.w[i])&b + } +} + +/* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */ +func dcomp(a *DBIG,b *DBIG) int { + for i:=DNLEN-1;i>=0;i-- { + if a.w[i]==b.w[i] {continue} + if a.w[i]>b.w[i] { + return 1 + } else {return -1} + } + return 0 +} + +/* Copy from another BIG */ +func (r *DBIG) copy(x *DBIG) { + for i:=0;i<DNLEN;i++ { + r.w[i]=x.w[i] + } +} + +func (r *DBIG) add(x *DBIG) { + for i:=0;i<DNLEN;i++ { + r.w[i]=r.w[i]+x.w[i] + } +} + +/* this-=x */ +func (r *DBIG) sub(x *DBIG) { + for i:=0;i<DNLEN;i++ { + r.w[i]=r.w[i]-x.w[i] + } +} + +/* general shift left */ +func (r *DBIG) shl(k uint) { + n:=k%BASEBITS + m:=int(k/BASEBITS) + + r.w[DNLEN-1]=((r.w[DNLEN-1-m]<<n))|(r.w[DNLEN-m-2]>>(BASEBITS-n)) + for i:=DNLEN-2;i>m;i-- { + r.w[i]=((r.w[i-m]<<n)&BMASK)|(r.w[i-m-1]>>(BASEBITS-n)) + } + r.w[m]=(r.w[0]<<n)&BMASK; + for i:=0;i<m;i++ {r.w[i]=0} +} + +/* general shift right */ +func (r *DBIG) shr(k uint) { + n:=(k%BASEBITS) + m:=int(k/BASEBITS) + for i:=0;i<DNLEN-m-1;i++ { + r.w[i]=(r.w[m+i]>>n)|((r.w[m+i+1]<<(BASEBITS-n))&BMASK) + } + r.w[DNLEN-m-1]=r.w[DNLEN-1]>>n; + for i:=DNLEN-m;i<DNLEN;i++ {r.w[i]=0} +} + +/* reduces this DBIG mod a BIG, and returns the BIG */ +func (r *DBIG) mod(c *BIG) *BIG { + r.norm() + m:=NewDBIGscopy(c) + dr:=NewDBIG(); + + if dcomp(r,m)<0 { + return NewBIGdcopy(r) + } + + m.shl(1); + k:=1; + + for dcomp(r,m)>=0 { + m.shl(1); + k++; + } + + for k>0 { + m.shr(1); + + dr.copy(r); + dr.sub(m); + dr.norm(); + r.cmove(dr,int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1))); +/* + if dcomp(r,m)>=0 { + r.sub(m); + r.norm(); + } */ + k--; + } + return NewBIGdcopy(r) +} + +/* return this/c */ +func (r *DBIG) div(c *BIG) *BIG { + var d int + k:=0 + m:=NewDBIGscopy(c) + a:=NewBIGint(0) + e:=NewBIGint(1) + sr:=NewBIG() + dr:=NewDBIG() + r.norm() + + for dcomp(r,m)>=0 { + e.fshl(1) + m.shl(1) + k++ + } + + for k>0 { + m.shr(1) + e.shr(1) + + dr.copy(r); + dr.sub(m); + dr.norm(); + d=int(1-((dr.w[DNLEN-1]>>uint(CHUNK-1))&1)); + r.cmove(dr,d); + sr.copy(a); + sr.add(e); + sr.norm(); + a.cmove(sr,d); + +/* + if dcomp(r,m)>0 { + a.add(e) + a.norm() + r.sub(m) + r.norm() + } */ + k-- + } + return a +} + +/* Convert to Hex String */ +func (r *DBIG) toString() string { + s:="" + len:=r.nbits() + + if len%4==0 { + len/=4 + } else { + len/=4 + len++ + + } + + for i:=len-1;i>=0;i-- { + b:=NewDBIGcopy(r) + + b.shr(uint(i*4)) + s+=strconv.FormatInt(int64(b.w[0]&15),16) + } + return s +} + +/* return number of bits */ +func (r *DBIG) nbits() int { + k:=DNLEN-1 + r.norm() + for (k>=0 && r.w[k]==0) {k--} + if k<0 {return 0} + bts:=int(BASEBITS)*k; + c:=r.w[k]; + for c!=0 {c/=2; bts++} + return bts +} + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/ECDH.go ---------------------------------------------------------------------- diff --git a/version22/go/ECDH.go b/version22/go/ECDH.go new file mode 100644 index 0000000..9656113 --- /dev/null +++ b/version22/go/ECDH.go @@ -0,0 +1,547 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +*/ + +/* Elliptic Curve API high-level functions */ + +package main + +//import "fmt" + +const ECDH_INVALID_PUBLIC_KEY int=-2 +const ECDH_ERROR int=-3 +const ECDH_INVALID int=-4 +const ECDH_EFS int=int(MODBYTES) +const ECDH_EGS int=int(MODBYTES) +const ECDH_EAS int=16 +const ECDH_EBS int=16 +const ECDH_SHA256 int=32 +const ECDH_SHA384 int=48 +const ECDH_SHA512 int=64 + +const ECDH_HASH_TYPE int=ECDH_SHA512 + +/* Convert Integer to n-byte array */ +func inttoBytes(n int,len int) []byte { + var b []byte + var i int + for i=0;i<len;i++ {b=append(b,0)} + i=len + for (n>0 && i>0) { + i--; + b[i]=byte(n&0xff) + n/=256 + } + return b +} + +func ehashit(sha int,A []byte,n int,B []byte,pad int) []byte { + var R []byte + if sha==ECDH_SHA256 { + H:=NewHASH256() + H.Process_array(A) + if n>0 {H.Process_num(int32(n))} + if B!=nil {H.Process_array(B)} + R=H.Hash() + } + if sha==ECDH_SHA384 { + H:=NewHASH384() + H.Process_array(A) + if n>0 {H.Process_num(int32(n))} + if B!=nil {H.Process_array(B)} + R=H.Hash() + } + if sha==ECDH_SHA512 { + H:=NewHASH512() + H.Process_array(A) + if n>0 {H.Process_num(int32(n))} + if B!=nil {H.Process_array(B)} + R=H.Hash() + } + if R==nil {return nil} + + if pad==0 {return R} + var W []byte + for i:=0;i<pad;i++ {W=append(W,0)} + if pad<=sha { + for i:=0;i<pad;i++ {W[i]=R[i]} + } else { + for i:=0;i<sha;i++ {W[i]=R[i]} + for i:=sha;i<pad;i++ {W[i]=0} + } + return W +} + +/* Key Derivation Functions */ +/* Input octet Z */ +/* Output key of length olen */ +func KDF1(sha int,Z []byte,olen int) []byte { +/* NOTE: the parameter olen is the length of the output K in bytes */ + hlen:=sha + var K []byte + k:=0 + + for i:=0;i<olen;i++ {K=append(K,0)} + + cthreshold:=olen/hlen; if olen%hlen!=0 {cthreshold++} + + for counter:=0;counter<cthreshold;counter++ { + B:=ehashit(sha,Z,counter,nil,0) + if k+hlen>olen { + for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++} + } else { + for i:=0;i<hlen;i++ {K[k]=B[i]; k++} + } + } + return K; +} + +func KDF2(sha int,Z []byte,P []byte,olen int) []byte { +/* NOTE: the parameter olen is the length of the output k in bytes */ + hlen:=sha + var K []byte + k:=0 + + for i:=0;i<olen;i++ {K=append(K,0)} + + cthreshold:=olen/hlen; if olen%hlen!=0 {cthreshold++} + + for counter:=1;counter<=cthreshold;counter++ { + B:=ehashit(sha,Z,counter,P,0) + if k+hlen>olen { + for i:=0;i<olen%hlen;i++ {K[k]=B[i]; k++} + } else { + for i:=0;i<hlen;i++ {K[k]=B[i]; k++} + } + } + return K +} + +/* Password based Key Derivation Function */ +/* Input password p, salt s, and repeat count */ +/* Output key of length olen */ +func PBKDF2(sha int,Pass []byte,Salt []byte,rep int,olen int) []byte { + d:=olen/sha; if olen%sha!=0 {d++} + + var F []byte + var U []byte + var S []byte + var K []byte + + for i:=0;i<sha;i++{F=append(F,0); U=append(U,0)} + + for i:=1;i<=d;i++ { + for j:=0;j<len(Salt);j++ {S=append(S,Salt[j])} + N:=inttoBytes(i,4) + for j:=0;j<4;j++ {S=append(S,N[j])} + + HMAC(sha,S,Pass,F[:]) + + for j:=0;j<sha;j++ {U[j]=F[j]} + for j:=2;j<=rep;j++ { + HMAC(sha,U[:],Pass,U[:]); + for k:=0;k<sha;k++ {F[k]^=U[k]} + } + for j:=0;j<sha;j++ {K=append(K,F[j])} + } + var key []byte + for i:=0;i<olen;i++ {key=append(key,K[i])} + return key +} + +/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */ +func HMAC(sha int,M []byte,K []byte,tag []byte) int { + /* Input is from an octet m * + * olen is requested output length in bytes. k is the key * + * The output is the calculated tag */ + var B []byte + b:=64 + if sha>32 {b=128} + + var K0 [128]byte + olen:=len(tag) + + if (olen<4 /*|| olen>sha */) {return 0} + + for i:=0;i<b;i++ {K0[i]=0} + + if len(K) > b { + B=ehashit(sha,K,0,nil,0) + for i:=0;i<sha;i++ {K0[i]=B[i]} + } else { + for i:=0;i<len(K);i++ {K0[i]=K[i]} + } + + for i:=0;i<b;i++ {K0[i]^=0x36} + B=ehashit(sha,K0[0:b],0,M,0); + + for i:=0;i<b;i++ {K0[i]^=0x6a} + B=ehashit(sha,K0[0:b],0,B,olen) + + for i:=0;i<olen;i++ {tag[i]=B[i]} + + return 1 +} + +/* AES encryption/decryption. Encrypt byte array M using key K and returns ciphertext */ +func AES_CBC_IV0_ENCRYPT(K []byte,M []byte) []byte { /* AES CBC encryption, with Null IV and key K */ + /* Input is from an octet string M, output is to an octet string C */ + /* Input is padded as necessary to make up a full final block */ + a:=NewAES() + fin:=false + + var buff [16]byte + var C []byte + + a.Init(aes_CBC,len(K),K,nil) + + ipt:=0; //opt:=0 + var i int + for true { + for i=0;i<16;i++ { + if ipt<len(M) { + buff[i]=M[ipt]; ipt++; + } else {fin=true; break;} + } + if fin {break} + a.Encrypt(buff[:]) + for i=0;i<16;i++ { + C=append(C,buff[i]) + } + } + +/* last block, filled up to i-th index */ + + padlen:=16-i + for j:=i;j<16;j++ {buff[j]=byte(padlen)} + + a.Encrypt(buff[:]) + + for i=0;i<16;i++ { + C=append(C,buff[i]) + } + a.End() + return C +} + +/* returns plaintext if all consistent, else returns null string */ +func AES_CBC_IV0_DECRYPT(K []byte,C []byte) []byte { /* padding is removed */ + a:=NewAES() + var buff [16]byte + var MM []byte + var M []byte + + var i int + ipt:=0; opt:=0 + + a.Init(aes_CBC,len(K),K,nil); + + if len(C)==0 {return nil} + ch:=C[ipt]; ipt++ + + fin:=false + + for true { + for i=0;i<16;i++ { + buff[i]=ch + if ipt>=len(C) { + fin=true; break + } else {ch=C[ipt]; ipt++ } + } + a.Decrypt(buff[:]) + if fin {break} + for i=0;i<16;i++ { + MM=append(MM,buff[i]); opt++ + } + } + + a.End(); + bad:=false + padlen:=int(buff[15]) + if (i!=15 || padlen<1 || padlen>16) {bad=true} + if (padlen>=2 && padlen<=16) { + for i=16-padlen;i<16;i++ { + if buff[i]!=byte(padlen) {bad=true} + } + } + + if !bad { + for i=0;i<16-padlen;i++ { + MM=append(MM,buff[i]); opt++ + } + } + + if bad {return nil} + + for i=0;i<opt;i++ {M=append(M,MM[i])} + + return M; +} + +/* Calculate a public/private EC GF(p) key pair W,S where W=S.G mod EC(p), + * where S is the secret key and W is the public key + * and G is fixed generator. + * If RNG is NULL then the private key is provided externally in S + * otherwise it is generated randomly internally */ +func ECDH_KEY_PAIR_GENERATE(RNG *RAND,S []byte,W []byte) int { + res:=0 +// var T [ECDH_EFS]byte + var s *BIG + var G *ECP + + gx:=NewBIGints(CURVE_Gx) + if CURVETYPE!=MONTGOMERY { + gy:=NewBIGints(CURVE_Gy) + G=NewECPbigs(gx,gy) + } else { + G=NewECPbig(gx) + } + + r:=NewBIGints(CURVE_Order) + + if RNG==nil { + s=fromBytes(S) + s.mod(r) + } else { + s=randomnum(r,RNG) + + // s.toBytes(T[:]) + // for i:=0;i<ECDH_EGS;i++ {S[i]=T[i]} + } + + if AES_S>0 { + s.mod2m(2*AES_S) + } + s.toBytes(S) + + WP:=G.mul(s) + + WP.toBytes(W) + + return res +} + +/* validate public key. Set full=true for fuller check */ +func ECDH_PUBLIC_KEY_VALIDATE(full bool,W []byte) int { + WP:=ECP_fromBytes(W) + res:=0 + + r:=NewBIGints(CURVE_Order) + + if WP.is_infinity() {res=ECDH_INVALID_PUBLIC_KEY} + if res==0 && full { + WP=WP.mul(r) + if !WP.is_infinity() {res=ECDH_INVALID_PUBLIC_KEY} + } + return res +} + +/* IEEE-1363 Diffie-Hellman online calculation Z=S.WD */ +func ECPSVDP_DH(S []byte,WD []byte,Z []byte) int { + res:=0; + var T [ECDH_EFS]byte + + s:=fromBytes(S) + + W:=ECP_fromBytes(WD) + if W.is_infinity() {res=ECDH_ERROR} + + if res==0 { + r:=NewBIGints(CURVE_Order) + s.mod(r) + W=W.mul(s) + if W.is_infinity() { + res=ECDH_ERROR + } else { + W.getX().toBytes(T[:]) + for i:=0;i<ECDH_EFS;i++ {Z[i]=T[i]} + } + } + return res +} + +/* IEEE ECDSA Signature, C and D are signature on F using private key S */ +func ECPSP_DSA(sha int,RNG *RAND,S []byte,F []byte,C []byte,D []byte) int { + var T [ECDH_EFS]byte + + B:=ehashit(sha,F,0,nil,int(MODBYTES)); + + gx:=NewBIGints(CURVE_Gx) + gy:=NewBIGints(CURVE_Gy) + + G:=NewECPbigs(gx,gy) + r:=NewBIGints(CURVE_Order) + + s:=fromBytes(S) + f:=fromBytes(B[:]) + + c:=NewBIGint(0) + d:=NewBIGint(0) + V:=NewECP() + + for d.iszilch() { + u:=randomnum(r,RNG); + w:=randomnum(r,RNG); + if AES_S>0 { + u.mod2m(2*AES_S) + } + V.copy(G) + V=V.mul(u) + vx:=V.getX() + c.copy(vx) + c.mod(r); + if c.iszilch() {continue} + u.copy(modmul(u,w,r)) + u.invmodp(r) + d.copy(modmul(s,c,r)) + d.add(f) + d.copy(modmul(d,w,r)) + d.copy(modmul(u,d,r)) + } + + c.toBytes(T[:]) + for i:=0;i<ECDH_EFS;i++ {C[i]=T[i]} + d.toBytes(T[:]) + for i:=0;i<ECDH_EFS;i++ {D[i]=T[i]} + return 0 +} + +/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */ +func ECPVP_DSA(sha int,W []byte,F []byte,C []byte,D []byte) int { + res:=0 + + B:=ehashit(sha,F,0,nil,int(MODBYTES)); + + gx:=NewBIGints(CURVE_Gx) + gy:=NewBIGints(CURVE_Gy) + + G:=NewECPbigs(gx,gy) + r:=NewBIGints(CURVE_Order) + + c:=fromBytes(C) + d:=fromBytes(D) + f:=fromBytes(B[:]) + + if (c.iszilch() || comp(c,r)>=0 || d.iszilch() || comp(d,r)>=0) { + res=ECDH_INVALID; + } + + if res==0 { + d.invmodp(r) + f.copy(modmul(f,d,r)) + h2:=modmul(c,d,r) + + WP:=ECP_fromBytes(W) + if WP.is_infinity() { + res=ECDH_ERROR + } else { + P:=NewECP() + P.copy(WP) + + P=P.mul2(h2,G,f) + + if P.is_infinity() { + res=ECDH_INVALID; + } else { + d=P.getX() + d.mod(r) + + if comp(d,c)!=0 {res=ECDH_INVALID} + } + } + } + + return res +} + +/* IEEE1363 ECIES encryption. Encryption of plaintext M uses public key W and produces ciphertext V,C,T */ +func ECIES_ENCRYPT(sha int,P1 []byte,P2 []byte,RNG *RAND,W []byte,M []byte,V []byte,T []byte) []byte { + var Z [ECDH_EFS]byte + var VZ [3*ECDH_EFS+1]byte + var K1 [ECDH_EAS]byte + var K2 [ECDH_EAS]byte + var U [ECDH_EGS]byte + + if ECDH_KEY_PAIR_GENERATE(RNG,U[:],V)!=0 {return nil} + if ECPSVDP_DH(U[:],W,Z[:])!=0 {return nil} + + for i:=0;i<2*ECDH_EFS+1;i++ {VZ[i]=V[i]} + for i:=0;i<ECDH_EFS;i++ {VZ[2*ECDH_EFS+1+i]=Z[i]} + + + K:=KDF2(sha,VZ[:],P1,ECDH_EFS) + + for i:=0;i<ECDH_EAS;i++ {K1[i]=K[i]; K2[i]=K[ECDH_EAS+i]} + + C:=AES_CBC_IV0_ENCRYPT(K1[:],M) + + L2:=inttoBytes(len(P2),8) + + var AC []byte + + for i:=0;i<len(C);i++ {AC=append(AC,C[i])} + for i:=0;i<len(P2);i++ {AC=append(AC,P2[i])} + for i:=0;i<8;i++ {AC=append(AC,L2[i])} + + HMAC(sha,AC,K2[:],T) + + return C +} + +/* IEEE1363 ECIES decryption. Decryption of ciphertext V,C,T using private key U outputs plaintext M */ +func ECIES_DECRYPT(sha int,P1 []byte,P2 []byte,V []byte,C []byte,T []byte,U []byte) []byte { + var Z [ECDH_EFS]byte + var VZ [3*ECDH_EFS+1]byte + var K1 [ECDH_EAS]byte + var K2 [ECDH_EAS]byte + + var TAG []byte =T[:] + + if ECPSVDP_DH(U,V,Z[:])!=0 {return nil} + + for i:=0;i<2*ECDH_EFS+1;i++ {VZ[i]=V[i]} + for i:=0;i<ECDH_EFS;i++ {VZ[2*ECDH_EFS+1+i]=Z[i]} + + K:=KDF2(sha,VZ[:],P1,ECDH_EFS) + + for i:=0;i<ECDH_EAS;i++ {K1[i]=K[i]; K2[i]=K[ECDH_EAS+i]} + + M:=AES_CBC_IV0_DECRYPT(K1[:],C) + + if M==nil {return nil} + + L2:=inttoBytes(len(P2),8) + + var AC []byte + + for i:=0;i<len(C);i++ {AC=append(AC,C[i])} + for i:=0;i<len(P2);i++ {AC=append(AC,P2[i])} + for i:=0;i<8;i++ {AC=append(AC,L2[i])} + + HMAC(sha,AC,K2[:],TAG) + + same:=true + for i:=0;i<len(T);i++ { + if T[i]!=TAG[i] {same=false} + } + if !same {return nil} + + return M +} + + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/go/ECP.go ---------------------------------------------------------------------- diff --git a/version22/go/ECP.go b/version22/go/ECP.go new file mode 100644 index 0000000..e33b52b --- /dev/null +++ b/version22/go/ECP.go @@ -0,0 +1,893 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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 main + +//import "fmt" + +/* Elliptic Curve Point Structure */ + +type ECP struct { + x *FP + y *FP + z *FP + INF bool +} + +/* Constructors */ +func NewECP() *ECP { + E:=new(ECP) + E.x=NewFPint(0) + E.y=NewFPint(0) + E.z=NewFPint(0) + E.INF=true + return E +} + +/* set (x,y) from two BIGs */ +func NewECPbigs(ix *BIG,iy *BIG) *ECP { + E:=new(ECP) + E.x=NewFPbig(ix) + E.y=NewFPbig(iy) + E.z=NewFPint(1) + rhs:=RHS(E.x) + + if CURVETYPE==MONTGOMERY { + if rhs.jacobi()==1 { + E.INF=false + } else {E.inf()} + } else { + y2:=NewFPcopy(E.y) + y2.sqr() + if y2.equals(rhs) { + E.INF=false + } else {E.inf()} + } + return E +} + +/* set (x,y) from BIG and a bit */ +func NewECPbigint(ix *BIG,s int) *ECP { + E:=new(ECP) + E.x=NewFPbig(ix) + E.y=NewFPint(0) + rhs:=RHS(E.x) + E.z=NewFPint(1) + if rhs.jacobi()==1 { + ny:=rhs.sqrt() + if ny.redc().parity()!=s {ny.neg()} + E.y.copy(ny) + E.INF=false + } else {E.inf()} + return E; +} + +/* set from x - calculate y from curve equation */ +func NewECPbig(ix *BIG) *ECP { + E:=new(ECP) + E.x=NewFPbig(ix) + E.y=NewFPint(0) + rhs:=RHS(E.x) + E.z=NewFPint(1) + if rhs.jacobi()==1 { + if CURVETYPE!=MONTGOMERY {E.y.copy(rhs.sqrt())} + E.INF=false + } else {E.INF=true} + return E +} + +/* test for O point-at-infinity */ +func (E *ECP) is_infinity() bool { + if CURVETYPE==EDWARDS { + E.x.reduce(); E.y.reduce(); E.z.reduce() + return (E.x.iszilch() && E.y.equals(E.z)) + } else {return E.INF} +} + +/* Conditional swap of P and Q dependant on d */ +func (E *ECP) cswap(Q *ECP,d int) { + E.x.cswap(Q.x,d) + if CURVETYPE!=MONTGOMERY {E.y.cswap(Q.y,d)} + E.z.cswap(Q.z,d) + if CURVETYPE!=EDWARDS { + bd:=true + if d==0 {bd=false} + bd=bd&&(E.INF!=Q.INF) + E.INF=(bd!=E.INF) + Q.INF=(bd!=Q.INF) + } +} + +/* Conditional move of Q to P dependant on d */ +func (E *ECP) cmove(Q *ECP,d int) { + E.x.cmove(Q.x,d) + if CURVETYPE!=MONTGOMERY {E.y.cmove(Q.y,d)} + E.z.cmove(Q.z,d); + if CURVETYPE!=EDWARDS { + bd:=true + if d==0 {bd=false} + E.INF=(E.INF!=((E.INF!=Q.INF)&&bd)) + } +} + +/* return 1 if b==c, no branching */ +func teq(b int32,c int32) int { + x:=b^c + x-=1 // if x=0, x now -1 + return int((x>>31)&1) +} + +/* this=P */ +func (E *ECP) copy(P *ECP) { + E.x.copy(P.x); + if CURVETYPE!=MONTGOMERY {E.y.copy(P.y)} + E.z.copy(P.z); + E.INF=P.INF; +} + +/* this=-this */ +func (E *ECP) neg() { + if E.is_infinity() {return} + if CURVETYPE==WEIERSTRASS { + E.y.neg(); E.y.norm() + } + if CURVETYPE==EDWARDS { + E.x.neg(); E.x.norm() + } + return; +} + +/* Constant time select from pre-computed table */ +func (E *ECP) selector(W []*ECP,b int32) { + MP:=NewECP() + m:=b>>31; + babs:=(b^m)-m; + + babs=(babs-1)/2 + + E.cmove(W[0],teq(babs,0)) // conditional move + E.cmove(W[1],teq(babs,1)) + E.cmove(W[2],teq(babs,2)) + E.cmove(W[3],teq(babs,3)) + E.cmove(W[4],teq(babs,4)) + E.cmove(W[5],teq(babs,5)) + E.cmove(W[6],teq(babs,6)) + E.cmove(W[7],teq(babs,7)) + + MP.copy(E); + MP.neg() + E.cmove(MP,int(m&1)); +} + +/* set this=O */ +func (E *ECP) inf() { + E.INF=true; + E.x.zero() + E.y.one() + E.z.one() +} + +/* Test P == Q */ +func( E *ECP) equals(Q *ECP) bool { + if E.is_infinity() && Q.is_infinity() {return true} + if E.is_infinity() || Q.is_infinity() {return false} + if CURVETYPE==WEIERSTRASS { + zs2:=NewFPcopy(E.z); zs2.sqr() + zo2:=NewFPcopy(Q.z); zo2.sqr() + zs3:=NewFPcopy(zs2); zs3.mul(E.z) + zo3:=NewFPcopy(zo2); zo3.mul(Q.z) + zs2.mul(Q.x) + zo2.mul(E.x) + if !zs2.equals(zo2) {return false} + zs3.mul(Q.y) + zo3.mul(E.y) + if !zs3.equals(zo3) {return false} + } else { + a:=NewFPint(0) + b:=NewFPint(0) + a.copy(E.x); a.mul(Q.z); a.reduce() + b.copy(Q.x); b.mul(E.z); b.reduce() + if !a.equals(b) {return false} + if CURVETYPE==EDWARDS { + a.copy(E.y); a.mul(Q.z); a.reduce() + b.copy(Q.y); b.mul(E.z); b.reduce() + if !a.equals(b) {return false} + } + } + return true +} + +/* Calculate RHS of curve equation */ +func RHS(x *FP) *FP { + x.norm() + r:=NewFPcopy(x) + r.sqr(); + + if CURVETYPE==WEIERSTRASS { // x^3+Ax+B + b:=NewFPbig(NewBIGints(CURVE_B)) + r.mul(x); + if CURVE_A==-3 { + cx:=NewFPcopy(x) + cx.imul(3) + cx.neg(); cx.norm() + r.add(cx) + } + r.add(b) + } + if CURVETYPE==EDWARDS { // (Ax^2-1)/(Bx^2-1) + b:=NewFPbig(NewBIGints(CURVE_B)) + + one:=NewFPint(1) + b.mul(r) + b.sub(one) + if CURVE_A==-1 {r.neg()} + r.sub(one) + b.inverse() + r.mul(b) + } + if CURVETYPE==MONTGOMERY { // x^3+Ax^2+x + x3:=NewFPint(0) + x3.copy(r) + x3.mul(x) + r.imul(CURVE_A) + r.add(x3) + r.add(x) + } + r.reduce() + return r +} + +/* set to affine - from (x,y,z) to (x,y) */ +func (E *ECP) affine() { + if E.is_infinity() {return} + one:=NewFPint(1) + if E.z.equals(one) {return} + E.z.inverse() + if CURVETYPE==WEIERSTRASS { + z2:=NewFPcopy(E.z) + z2.sqr() + E.x.mul(z2); E.x.reduce() + E.y.mul(z2) + E.y.mul(E.z); E.y.reduce() + } + if CURVETYPE==EDWARDS { + E.x.mul(E.z); E.x.reduce() + E.y.mul(E.z); E.y.reduce() + } + if CURVETYPE==MONTGOMERY { + E.x.mul(E.z); E.x.reduce() + } + E.z.one() +} + +/* extract x as a BIG */ +func (E *ECP) getX() *BIG { + E.affine() + return E.x.redc() +} +/* extract y as a BIG */ +func (E *ECP) getY() *BIG { + E.affine() + return E.y.redc() +} + +/* get sign of Y */ +func (E *ECP) getS() int { + E.affine() + y:=E.getY() + return y.parity() +} +/* extract x as an FP */ +func (E *ECP) getx() *FP { + return E.x; +} +/* extract y as an FP */ +func (E *ECP) gety() *FP { + return E.y +} +/* extract z as an FP */ +func (E *ECP) getz() *FP { + return E.z +} + +/* convert to byte array */ +func (E *ECP) toBytes(b []byte) { + var t [int(MODBYTES)]byte + MB:=int(MODBYTES) + if CURVETYPE!=MONTGOMERY { + b[0]=0x04 + } else {b[0]=0x02} + + E.affine() + E.x.redc().toBytes(t[:]) + for i:=0;i<MB;i++ {b[i+1]=t[i]} + if CURVETYPE!=MONTGOMERY { + E.y.redc().toBytes(t[:]) + for i:=0;i<MB;i++ {b[i+MB+1]=t[i]} + } +} + +/* convert from byte array to point */ +func ECP_fromBytes(b []byte) *ECP { + var t [int(MODBYTES)]byte + MB:=int(MODBYTES) + p:=NewBIGints(Modulus) + + for i:=0;i<MB;i++ {t[i]=b[i+1]} + px:=fromBytes(t[:]) + if comp(px,p)>=0 {return NewECP()} + + if (b[0]==0x04) { + for i:=0;i<MB;i++ {t[i]=b[i+MB+1]} + py:=fromBytes(t[:]) + if comp(py,p)>=0 {return NewECP()} + return NewECPbigs(px,py) + } else {return NewECPbig(px)} +} + +/* convert to hex string */ +func (E *ECP) toString() string { + if E.is_infinity() {return "infinity"} + E.affine(); + if CURVETYPE==MONTGOMERY { + return "("+E.x.redc().toString()+")" + } else {return "("+E.x.redc().toString()+","+E.y.redc().toString()+")"} +} + +/* this*=2 */ +func (E *ECP) dbl() { + if CURVETYPE==WEIERSTRASS { + if E.INF {return} + if E.y.iszilch() { + E.inf() + return + } + + w1:=NewFPcopy(E.x); + w6:=NewFPcopy(E.z); + w2:=NewFPint(0); + w3:=NewFPcopy(E.x) + w8:=NewFPcopy(E.x) + + if CURVE_A==-3 { + w6.sqr() + w1.copy(w6) + w1.neg() + w3.add(w1) + + w8.add(w6) + + w3.mul(w8) + w8.copy(w3) + w8.imul(3) + } else { + w1.sqr() + w8.copy(w1) + w8.imul(3) + } + + w2.copy(E.y); w2.sqr() + w3.copy(E.x); w3.mul(w2) + w3.imul(4) + w1.copy(w3); w1.neg() + // w1.norm(); + + + E.x.copy(w8); E.x.sqr() + E.x.add(w1) + E.x.add(w1) + // x.reduce(); + E.x.norm() + + E.z.mul(E.y) + E.z.add(E.z) + + w2.add(w2) + w2.sqr() + w2.add(w2) + w3.sub(E.x) + E.y.copy(w8); E.y.mul(w3); + // w2.norm(); + E.y.sub(w2) + // y.reduce(); + // z.reduce(); + E.y.norm() + E.z.norm() + + } + if CURVETYPE==EDWARDS { + C:=NewFPcopy(E.x) + D:=NewFPcopy(E.y) + H:=NewFPcopy(E.z) + J:=NewFPint(0) + + E.x.mul(E.y); E.x.add(E.x) + C.sqr() + D.sqr() + if CURVE_A==-1 {C.neg()} + E.y.copy(C); E.y.add(D) + // y.norm(); + H.sqr(); H.add(H) + E.z.copy(E.y) + J.copy(E.y); J.sub(H) + E.x.mul(J) + C.sub(D) + E.y.mul(C) + E.z.mul(J) + + E.x.norm() + E.y.norm() + E.z.norm() + } + if CURVETYPE==MONTGOMERY { + A:=NewFPcopy(E.x) + B:=NewFPcopy(E.x) + AA:=NewFPint(0) + BB:=NewFPint(0) + C:=NewFPint(0) + + if E.INF {return} + + A.add(E.z) + AA.copy(A); AA.sqr() + B.sub(E.z) + BB.copy(B); BB.sqr() + C.copy(AA); C.sub(BB) + // C.norm(); + + E.x.copy(AA); E.x.mul(BB) + + A.copy(C); A.imul((CURVE_A+2)/4) + + BB.add(A) + E.z.copy(BB); E.z.mul(C) + // x.reduce(); + // z.reduce(); + E.x.norm() + E.z.norm() + } + return; +} + +/* this+=Q */ +func (E *ECP) add(Q *ECP) { + if CURVETYPE==WEIERSTRASS { + if E.INF { + E.copy(Q) + return + } + if Q.INF {return} + + aff:=false + + one:=NewFPint(1) + if Q.z.equals(one) {aff=true} + + var A,C *FP + B:=NewFPcopy(E.z) + D:=NewFPcopy(E.z) + if !aff { + A=NewFPcopy(Q.z) + C=NewFPcopy(Q.z) + + A.sqr(); B.sqr() + C.mul(A); D.mul(B) + + A.mul(E.x) + C.mul(E.y) + } else { + A=NewFPcopy(E.x) + C=NewFPcopy(E.y) + + B.sqr() + D.mul(B) + } + + B.mul(Q.x); B.sub(A) + D.mul(Q.y); D.sub(C) + + if B.iszilch() { + if D.iszilch() { + E.dbl() + return + } else { + E.INF=true + return + } + } + + if !aff {E.z.mul(Q.z)} + E.z.mul(B) + + e:=NewFPcopy(B); e.sqr() + B.mul(e) + A.mul(e) + + e.copy(A) + e.add(A); e.add(B) + E.x.copy(D); E.x.sqr(); E.x.sub(e); + + A.sub(E.x); + E.y.copy(A); E.y.mul(D) + C.mul(B); E.y.sub(C) + + // x.reduce(); + // y.reduce(); + // z.reduce(); + E.x.norm() + E.y.norm() + E.z.norm() + } + if CURVETYPE==EDWARDS { + b:=NewFPbig(NewBIGints(CURVE_B)) + A:=NewFPcopy(E.z) + B:=NewFPint(0) + C:=NewFPcopy(E.x) + D:=NewFPcopy(E.y) + EE:=NewFPint(0) + F:=NewFPint(0) + G:=NewFPint(0) + //H:=NewFPint(0) + //I:=NewFPint(0) + + A.mul(Q.z); + B.copy(A); B.sqr() + C.mul(Q.x) + D.mul(Q.y) + + EE.copy(C); EE.mul(D); EE.mul(b) + F.copy(B); F.sub(EE) + G.copy(B); G.add(EE) + + if CURVE_A==1 { + EE.copy(D); EE.sub(C) + } + C.add(D) + + B.copy(E.x); B.add(E.y) + D.copy(Q.x); D.add(Q.y) + B.mul(D) + B.sub(C) + B.mul(F) + E.x.copy(A); E.x.mul(B) + + if CURVE_A==1 { + C.copy(EE); C.mul(G) + } + if CURVE_A==-1 { + C.mul(G) + } + E.y.copy(A); E.y.mul(C) + E.z.copy(F); E.z.mul(G) + // x.reduce(); y.reduce(); z.reduce(); + E.x.norm(); E.y.norm(); E.z.norm() + } + return +} + +/* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ +func (E *ECP) dadd(Q *ECP,W *ECP) { + A:=NewFPcopy(E.x) + B:=NewFPcopy(E.x) + C:=NewFPcopy(Q.x) + D:=NewFPcopy(Q.x) + DA:=NewFPint(0) + CB:=NewFPint(0) + + A.add(E.z) + B.sub(E.z) + + C.add(Q.z) + D.sub(Q.z) + + DA.copy(D); DA.mul(A) + CB.copy(C); CB.mul(B) + + A.copy(DA); A.add(CB); A.sqr() + B.copy(DA); B.sub(CB); B.sqr() + + E.x.copy(A) + E.z.copy(W.x); E.z.mul(B) + + if E.z.iszilch() { + E.inf() + } else {E.INF=false;} + + // x.reduce(); + E.x.norm(); +} + +/* this-=Q */ +func (E *ECP) sub(Q *ECP) { + Q.neg() + E.add(Q) + Q.neg() +} + +func multiaffine(m int,P []*ECP) { + t1:=NewFPint(0) + t2:=NewFPint(0) + + var work []*FP + + for i:=0;i<m;i++ { + work=append(work,NewFPint(0)) + } + + work[0].one() + work[1].copy(P[0].z) + + for i:=2;i<m;i++ { + work[i].copy(work[i-1]) + work[i].mul(P[i-1].z) + } + + t1.copy(work[m-1]) + t1.mul(P[m-1].z) + t1.inverse() + t2.copy(P[m-1].z) + work[m-1].mul(t1) + + for i:=m-2;;i-- { + if i==0 { + work[0].copy(t1) + work[0].mul(t2) + break + } + work[i].mul(t2) + work[i].mul(t1) + t2.mul(P[i].z) + } +/* now work[] contains inverses of all Z coordinates */ + + for i:=0;i<m;i++ { + P[i].z.one() + t1.copy(work[i]) + t1.sqr() + P[i].x.mul(t1) + t1.mul(work[i]) + P[i].y.mul(t1) + } +} + +/* constant time multiply by small integer of length bts - use ladder */ +func (E *ECP) pinmul(e int32,bts int32) *ECP { + if CURVETYPE==MONTGOMERY { + return E.mul(NewBIGint(int(e))) + } else { + P:=NewECP() + R0:=NewECP() + R1:=NewECP(); R1.copy(E) + + for i:=bts-1;i>=0;i-- { + b:=int((e>>uint32(i))&1) + P.copy(R1) + P.add(R0) + R0.cswap(R1,b) + R1.copy(P) + R0.dbl() + R0.cswap(R1,b) + } + P.copy(R0) + P.affine() + return P + } +} + +/* return e.this */ + +func (E *ECP) mul(e *BIG) *ECP { + if (e.iszilch() || E.is_infinity()) {return NewECP()} + P:=NewECP() + if CURVETYPE==MONTGOMERY { +/* use Ladder */ + D:=NewECP(); + R0:=NewECP(); R0.copy(E) + R1:=NewECP(); R1.copy(E) + R1.dbl() + D.copy(E); D.affine() + nb:=e.nbits() + for i:=nb-2;i>=0;i-- { + b:=int(e.bit(i)) + P.copy(R1) + P.dadd(R0,D) + R0.cswap(R1,b) + R1.copy(P) + R0.dbl() + R0.cswap(R1,b) + } + P.copy(R0) + } else { +// fixed size windows + mt:=NewBIG() + t:=NewBIG() + Q:=NewECP() + C:=NewECP() + + var W []*ECP + var w [1+(NLEN*int(BASEBITS)+3)/4]int8 + + E.affine(); + + Q.copy(E); + Q.dbl(); + + W=append(W,NewECP()); + W[0].copy(E); + + for i:=1;i<8;i++ { + W=append(W,NewECP()) + W[i].copy(W[i-1]) + W[i].add(Q) + } + + +// convert the table to affine + if CURVETYPE==WEIERSTRASS { + multiaffine(8,W[:]) + } + + +// make exponent odd - add 2P if even, P if odd + t.copy(e) + s:=int(t.parity()) + t.inc(1); t.norm(); ns:=int(t.parity()); mt.copy(t); mt.inc(1); mt.norm() + t.cmove(mt,s) + Q.cmove(E,ns) + C.copy(Q) + + nb:=1+(t.nbits()+3)/4 + +// convert exponent to signed 4-bit window + for i:=0;i<nb;i++ { + w[i]=int8(t.lastbits(5)-16) + t.dec(int(w[i])); t.norm() + t.fshr(4) + } + w[nb]=int8(t.lastbits(5)) + + P.copy(W[(int(w[nb])-1)/2]) + for i:=nb-1;i>=0;i-- { + Q.selector(W,int32(w[i])) + P.dbl() + P.dbl() + P.dbl() + P.dbl() + P.add(Q) + } + P.sub(C) /* apply correction */ + } + P.affine() + return P +} + +/* Return e.this+f.Q */ + +func (E *ECP) mul2(e *BIG,Q *ECP,f *BIG) *ECP { + te:=NewBIG() + tf:=NewBIG() + mt:=NewBIG() + S:=NewECP() + T:=NewECP() + C:=NewECP() + var W [] *ECP + //ECP[] W=new ECP[8]; + var w [1+(NLEN*int(BASEBITS)+1)/2]int8 + + E.affine() + Q.affine() + + te.copy(e) + tf.copy(f) + +// precompute table + for i:=0;i<8;i++ { + W=append(W,NewECP()) + } + W[1].copy(E); W[1].sub(Q) + W[2].copy(E); W[2].add(Q); + S.copy(Q); S.dbl(); + W[0].copy(W[1]); W[0].sub(S); + W[3].copy(W[2]); W[3].add(S); + T.copy(E); T.dbl(); + W[5].copy(W[1]); W[5].add(T); + W[6].copy(W[2]); W[6].add(T); + W[4].copy(W[5]); W[4].sub(S); + W[7].copy(W[6]); W[7].add(S); + +// convert the table to affine + if CURVETYPE==WEIERSTRASS { + multiaffine(8,W) + } + +// if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction + + s:=int(te.parity()); + te.inc(1); te.norm(); ns:=int(te.parity()); mt.copy(te); mt.inc(1); mt.norm() + te.cmove(mt,s) + T.cmove(E,ns) + C.copy(T) + + s=int(tf.parity()) + tf.inc(1); tf.norm(); ns=int(tf.parity()); mt.copy(tf); mt.inc(1); mt.norm() + tf.cmove(mt,s) + S.cmove(Q,ns) + C.add(S) + + mt.copy(te); mt.add(tf); mt.norm() + nb:=1+(mt.nbits()+1)/2 + +// convert exponent to signed 2-bit window + for i:=0;i<nb;i++ { + a:=(te.lastbits(3)-4) + te.dec(int(a)); te.norm() + te.fshr(2) + b:=(tf.lastbits(3)-4) + tf.dec(int(b)); tf.norm() + tf.fshr(2) + w[i]=int8(4*a+b) + } + w[nb]=int8(4*te.lastbits(3)+tf.lastbits(3)) + S.copy(W[(w[nb]-1)/2]) + + for i:=nb-1;i>=0;i-- { + T.selector(W,int32(w[i])); + S.dbl() + S.dbl() + S.add(T) + } + S.sub(C) /* apply correction */ + S.affine() + return S +} + +/* +func main() { + Gx:=NewBIGints(CURVE_Gx); + var Gy *BIG + var P *ECP + + if CURVETYPE!=MONTGOMERY {Gy=NewBIGints(CURVE_Gy)} + r:=NewBIGints(CURVE_Order) + + //r.dec(7); + + fmt.Printf("Gx= "+Gx.toString()) + fmt.Printf("\n") + + if CURVETYPE!=MONTGOMERY { + fmt.Printf("Gy= "+Gy.toString()) + fmt.Printf("\n") + } + + if CURVETYPE!=MONTGOMERY { + P=NewECPbigs(Gx,Gy) + } else {P=NewECPbig(Gx)} + + fmt.Printf("P= "+P.toString()); + fmt.Printf("\n") + + R:=P.mul(r); + //for (int i=0;i<10000;i++) + // R=P.mul(r); + + fmt.Printf("R= "+R.toString()) + fmt.Printf("\n") +} +*/ \ No newline at end of file
