| /* |
| 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. |
| */ |
| |
| /* RSA API high-level functions */ |
| |
| package XXX |
| |
| //import "fmt" |
| import "github.com/milagro-crypto/amcl/version3/go/amcl" |
| |
| const RFS int = int(MODBYTES) * FFLEN |
| |
| const RSA_HASH_TYPE int = amcl.SHA256 |
| |
| type rsa_private_key struct { |
| p, q, dp, dq, c *FF |
| } |
| |
| func New_private_key(n int) *rsa_private_key { |
| SK := new(rsa_private_key) |
| SK.p = NewFFint(n) |
| SK.q = NewFFint(n) |
| SK.dp = NewFFint(n) |
| SK.dq = NewFFint(n) |
| SK.c = NewFFint(n) |
| return SK |
| } |
| |
| type rsa_public_key struct { |
| e int |
| n *FF |
| } |
| |
| func New_public_key(m int) *rsa_public_key { |
| PK := new(rsa_public_key) |
| PK.e = 0 |
| PK.n = NewFFint(m) |
| return PK |
| } |
| |
| func hashit(sha int, A []byte, n int) []byte { |
| var R []byte |
| if sha == amcl.SHA256 { |
| H := amcl.NewHASH256() |
| if A != nil { |
| H.Process_array(A) |
| } |
| if n >= 0 { |
| H.Process_num(int32(n)) |
| } |
| R = H.Hash() |
| } |
| if sha == amcl.SHA384 { |
| H := amcl.NewHASH384() |
| if A != nil { |
| H.Process_array(A) |
| } |
| if n >= 0 { |
| H.Process_num(int32(n)) |
| } |
| R = H.Hash() |
| } |
| if sha == amcl.SHA512 { |
| H := amcl.NewHASH512() |
| if A != nil { |
| H.Process_array(A) |
| } |
| if n >= 0 { |
| H.Process_num(int32(n)) |
| } |
| R = H.Hash() |
| } |
| return R |
| } |
| |
| func RSA_KEY_PAIR(rng *amcl.RAND, e int, PRIV *rsa_private_key, PUB *rsa_public_key) { /* IEEE1363 A16.11/A16.12 more or less */ |
| n := PUB.n.getlen() / 2 |
| t := NewFFint(n) |
| p1 := NewFFint(n) |
| q1 := NewFFint(n) |
| |
| for true { |
| PRIV.p.random(rng) |
| for PRIV.p.lastbits(2) != 3 { |
| PRIV.p.inc(1) |
| } |
| for !prime(PRIV.p, rng) { |
| PRIV.p.inc(4) |
| } |
| |
| p1.copy(PRIV.p) |
| p1.dec(1) |
| |
| if p1.cfactor(e) { |
| continue |
| } |
| break |
| } |
| |
| for true { |
| PRIV.q.random(rng) |
| for PRIV.q.lastbits(2) != 3 { |
| PRIV.q.inc(1) |
| } |
| for !prime(PRIV.q, rng) { |
| PRIV.q.inc(4) |
| } |
| |
| q1.copy(PRIV.q) |
| q1.dec(1) |
| |
| if q1.cfactor(e) { |
| continue |
| } |
| |
| break |
| } |
| |
| PUB.n = ff_mul(PRIV.p, PRIV.q) |
| PUB.e = e |
| |
| t.copy(p1) |
| t.shr() |
| PRIV.dp.set(e) |
| PRIV.dp.invmodp(t) |
| if PRIV.dp.parity() == 0 { |
| PRIV.dp.add(t) |
| } |
| PRIV.dp.norm() |
| |
| t.copy(q1) |
| t.shr() |
| PRIV.dq.set(e) |
| PRIV.dq.invmodp(t) |
| if PRIV.dq.parity() == 0 { |
| PRIV.dq.add(t) |
| } |
| PRIV.dq.norm() |
| |
| PRIV.c.copy(PRIV.p) |
| PRIV.c.invmodp(PRIV.q) |
| |
| } |
| |
| /* Mask Generation Function */ |
| |
| func MGF1(sha int, Z []byte, olen int, K []byte) { |
| hlen := sha |
| |
| var k int = 0 |
| for i := 0; i < len(K); i++ { |
| K[i] = 0 |
| } |
| |
| cthreshold := olen / hlen |
| if olen%hlen != 0 { |
| cthreshold++ |
| } |
| for counter := 0; counter < cthreshold; counter++ { |
| B := hashit(sha, Z, counter) |
| |
| 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++ |
| } |
| } |
| } |
| } |
| |
| /* SHAXXX identifier strings */ |
| var SHA256ID = [...]byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20} |
| var SHA384ID = [...]byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30} |
| var SHA512ID = [...]byte{0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40} |
| |
| func RSA_PKCS15(sha int, m []byte, w []byte) bool { |
| olen := FF_BITS / 8 |
| hlen := sha |
| idlen := 19 |
| |
| if olen < idlen+hlen+10 { |
| return false |
| } |
| H := hashit(sha, m, -1) |
| |
| for i := 0; i < len(w); i++ { |
| w[i] = 0 |
| } |
| i := 0 |
| w[i] = 0 |
| i++ |
| w[i] = 1 |
| i++ |
| for j := 0; j < olen-idlen-hlen-3; j++ { |
| w[i] = 0xff |
| i++ |
| } |
| w[i] = 0 |
| i++ |
| |
| if hlen == amcl.SHA256 { |
| for j := 0; j < idlen; j++ { |
| w[i] = SHA256ID[j] |
| i++ |
| } |
| } |
| if hlen == amcl.SHA384 { |
| for j := 0; j < idlen; j++ { |
| w[i] = SHA384ID[j] |
| i++ |
| } |
| } |
| if hlen == amcl.SHA512 { |
| for j := 0; j < idlen; j++ { |
| w[i] = SHA512ID[j] |
| i++ |
| } |
| } |
| for j := 0; j < hlen; j++ { |
| w[i] = H[j] |
| i++ |
| } |
| |
| return true |
| } |
| |
| /* OAEP Message Encoding for Encryption */ |
| func RSA_OAEP_ENCODE(sha int, m []byte, rng *amcl.RAND, p []byte) []byte { |
| olen := RFS - 1 |
| mlen := len(m) |
| var f [RFS]byte |
| |
| hlen := sha |
| |
| SEED := make([]byte, hlen) |
| |
| seedlen := hlen |
| if mlen > olen-hlen-seedlen-1 { |
| return nil |
| } |
| |
| DBMASK := make([]byte, olen-seedlen) |
| |
| h := hashit(sha, p, -1) |
| |
| for i := 0; i < hlen; i++ { |
| f[i] = h[i] |
| } |
| |
| slen := olen - mlen - hlen - seedlen - 1 |
| |
| for i := 0; i < slen; i++ { |
| f[hlen+i] = 0 |
| } |
| f[hlen+slen] = 1 |
| for i := 0; i < mlen; i++ { |
| f[hlen+slen+1+i] = m[i] |
| } |
| |
| for i := 0; i < seedlen; i++ { |
| SEED[i] = rng.GetByte() |
| } |
| MGF1(sha, SEED, olen-seedlen, DBMASK) |
| |
| for i := 0; i < olen-seedlen; i++ { |
| DBMASK[i] ^= f[i] |
| } |
| |
| MGF1(sha, DBMASK, seedlen, f[:]) |
| |
| for i := 0; i < seedlen; i++ { |
| f[i] ^= SEED[i] |
| } |
| |
| for i := 0; i < olen-seedlen; i++ { |
| f[i+seedlen] = DBMASK[i] |
| } |
| |
| /* pad to length RFS */ |
| d := 1 |
| for i := RFS - 1; i >= d; i-- { |
| f[i] = f[i-d] |
| } |
| for i := d - 1; i >= 0; i-- { |
| f[i] = 0 |
| } |
| return f[:] |
| } |
| |
| /* OAEP Message Decoding for Decryption */ |
| func RSA_OAEP_DECODE(sha int, p []byte, f []byte) []byte { |
| olen := RFS - 1 |
| |
| hlen := sha |
| SEED := make([]byte, hlen) |
| seedlen := hlen |
| CHASH := make([]byte, hlen) |
| |
| if olen < seedlen+hlen+1 { |
| return nil |
| } |
| DBMASK := make([]byte, olen-seedlen) |
| for i := 0; i < olen-seedlen; i++ { |
| DBMASK[i] = 0 |
| } |
| |
| if len(f) < RFS { |
| d := RFS - len(f) |
| for i := RFS - 1; i >= d; i-- { |
| f[i] = f[i-d] |
| } |
| for i := d - 1; i >= 0; i-- { |
| f[i] = 0 |
| } |
| } |
| |
| h := hashit(sha, p, -1) |
| for i := 0; i < hlen; i++ { |
| CHASH[i] = h[i] |
| } |
| |
| x := f[0] |
| |
| for i := seedlen; i < olen; i++ { |
| DBMASK[i-seedlen] = f[i+1] |
| } |
| |
| MGF1(sha, DBMASK, seedlen, SEED) |
| for i := 0; i < seedlen; i++ { |
| SEED[i] ^= f[i+1] |
| } |
| MGF1(sha, SEED, olen-seedlen, f) |
| for i := 0; i < olen-seedlen; i++ { |
| DBMASK[i] ^= f[i] |
| } |
| |
| comp := true |
| for i := 0; i < hlen; i++ { |
| if CHASH[i] != DBMASK[i] { |
| comp = false |
| } |
| } |
| |
| for i := 0; i < olen-seedlen-hlen; i++ { |
| DBMASK[i] = DBMASK[i+hlen] |
| } |
| |
| for i := 0; i < hlen; i++ { |
| SEED[i] = 0 |
| CHASH[i] = 0 |
| } |
| |
| var k int |
| for k = 0; ; k++ { |
| if k >= olen-seedlen-hlen { |
| return nil |
| } |
| if DBMASK[k] != 0 { |
| break |
| } |
| } |
| |
| t := DBMASK[k] |
| if !comp || x != 0 || t != 0x01 { |
| for i := 0; i < olen-seedlen; i++ { |
| DBMASK[i] = 0 |
| } |
| return nil |
| } |
| |
| var r = make([]byte, olen-seedlen-hlen-k-1) |
| |
| for i := 0; i < olen-seedlen-hlen-k-1; i++ { |
| r[i] = DBMASK[i+k+1] |
| } |
| |
| for i := 0; i < olen-seedlen; i++ { |
| DBMASK[i] = 0 |
| } |
| |
| return r |
| } |
| |
| /* destroy the Private Key structure */ |
| func RSA_PRIVATE_KEY_KILL(PRIV *rsa_private_key) { |
| PRIV.p.zero() |
| PRIV.q.zero() |
| PRIV.dp.zero() |
| PRIV.dq.zero() |
| PRIV.c.zero() |
| } |
| |
| /* RSA encryption with the public key */ |
| func RSA_ENCRYPT(PUB *rsa_public_key, F []byte, G []byte) { |
| n := PUB.n.getlen() |
| f := NewFFint(n) |
| |
| ff_fromBytes(f, F) |
| f.power(PUB.e, PUB.n) |
| f.toBytes(G) |
| } |
| |
| /* RSA decryption with the private key */ |
| func RSA_DECRYPT(PRIV *rsa_private_key, G []byte, F []byte) { |
| n := PRIV.p.getlen() |
| g := NewFFint(2 * n) |
| |
| ff_fromBytes(g, G) |
| jp := g.dmod(PRIV.p) |
| jq := g.dmod(PRIV.q) |
| |
| jp.skpow(PRIV.dp, PRIV.p) |
| jq.skpow(PRIV.dq, PRIV.q) |
| |
| g.zero() |
| g.dscopy(jp) |
| jp.mod(PRIV.q) |
| if ff_comp(jp, jq) > 0 { |
| jq.add(PRIV.q) |
| } |
| jq.sub(jp) |
| jq.norm() |
| |
| t := ff_mul(PRIV.c, jq) |
| jq = t.dmod(PRIV.q) |
| |
| t = ff_mul(jq, PRIV.p) |
| g.add(t) |
| g.norm() |
| |
| g.toBytes(F) |
| } |