// EncryptOAEP encrypts the given message with RSA-OAEP. // The message must be no longer than the length of the public modulus less // twice the hash length plus 2. func EncryptOAEP(hash hash.Hash, rand io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err os.Error) { hash.Reset() k := (pub.N.Len() + 7) / 8 if len(msg) > k-2*hash.Size()-2 { err = MessageTooLongError{} return } hash.Write(label) lHash := hash.Sum() hash.Reset() em := make([]byte, k) seed := em[1 : 1+hash.Size()] db := em[1+hash.Size():] copy(db[0:hash.Size()], lHash) db[len(db)-len(msg)-1] = 1 copy(db[len(db)-len(msg):], msg) _, err = io.ReadFull(rand, seed) if err != nil { return } mgf1XOR(db, hash, seed) mgf1XOR(seed, hash, db) m := new(big.Int) m.SetBytes(em) c := encrypt(new(big.Int), pub, m) out = c.Bytes() return }
func (h *Hash) l3(m []byte, iter int) []byte { i := 0 k1 := new(big.Int) k2 := new(big.Int) for need := iter + 1; need > 0; i++ { t := h.kdf(224, 128*(i+1))[16*i : 16*(i+1)] k1.SetBytes(t[:8]) k2.SetBytes(t[8:]) if k1.Cmp(p64) == -1 && k2.Cmp(p64) == -1 { need-- } } mint := newInt(m) m1 := new(big.Int).Div(mint, p64p32) m2 := new(big.Int).Mod(mint, p64p32) y := new(big.Int).Add(m1, k1) y.Mul(y, new(big.Int).Add(m2, k2)) y.Mod(y, p64) Y := make([]byte, 8) copy(Y[8-len(y.Bytes()):], y.Bytes()) return Y }
// Sign signs an arbitrary length hash (which should be the result of hashing a // larger message) using the private key, priv. It returns the signature as a // pair of integers. The security of the private key depends on the entropy of // rand. func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.Error) { // FIPS 186-3, section 4.6 n := priv.Q.BitLen() if n&7 != 0 { err = InvalidPublicKeyError return } n >>= 3 for { k := new(big.Int) buf := make([]byte, n) for { _, err = io.ReadFull(rand, buf) if err != nil { return } k.SetBytes(buf) if k.Sign() > 0 && k.Cmp(priv.Q) < 0 { break } } kInv := new(big.Int).ModInverse(k, priv.Q) r = new(big.Int).Exp(priv.G, k, priv.P) r.Mod(r, priv.Q) if r.Sign() == 0 { continue } if n > len(hash) { n = len(hash) } z := k.SetBytes(hash[:n]) s = new(big.Int).Mul(priv.X, r) s.Add(s, z) s.Mod(s, priv.Q) s.Mul(s, kInv) s.Mod(s, priv.Q) if s.Sign() != 0 { break } } return }
// parseBigInt treats the given bytes as a big-endian, signed integer and returns // the result. func parseBigInt(bytes []byte) *big.Int { ret := new(big.Int) if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { // This is a negative number. notBytes := make([]byte, len(bytes)) for i := range notBytes { notBytes[i] = ^bytes[i] } ret.SetBytes(notBytes) ret.Add(ret, bigOne) ret.Neg(ret) return ret } ret.SetBytes(bytes) return ret }
// EncryptOAEP encrypts the given message with RSA-OAEP. // The message must be no longer than the length of the public modulus less // twice the hash length plus 2. func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) { hash.Reset() k := (pub.N.BitLen() + 7) / 8 if len(msg) > k-2*hash.Size()-2 { err = MessageTooLongError{} return } hash.Write(label) lHash := hash.Sum() hash.Reset() em := make([]byte, k) seed := em[1 : 1+hash.Size()] db := em[1+hash.Size():] copy(db[0:hash.Size()], lHash) db[len(db)-len(msg)-1] = 1 copy(db[len(db)-len(msg):], msg) _, err = io.ReadFull(random, seed) if err != nil { return } mgf1XOR(db, hash, seed) mgf1XOR(seed, hash, db) m := new(big.Int) m.SetBytes(em) c := encrypt(new(big.Int), pub, m) out = c.Bytes() if len(out) < k { // If the output is too small, we need to left-pad with zeros. t := make([]byte, k) copy(t[k-len(out):], out) out = t } return }
func B64ToBigInt(in string, b *big.Int) (err os.Error) { bsize := base64.StdEncoding.DecodedLen(len(in)) buff := make([]byte, bsize) n, err := base64.StdEncoding.Decode(buff, bytes.NewBufferString(in).Bytes()) neg := false if err == nil { buff = buff[0:n] if buff[0]&0x80 == 0x80 { neg = true buff[0] &= 0x7f } b.SetBytes(buff) // In case the passed in big was negative... b.Abs(b) if neg { b.Neg(b) } } return }
// GenerateKey generates a public&private key pair. The Parameters of the // PrivateKey must already be valid (see GenerateParameters). func GenerateKey(priv *PrivateKey, rand io.Reader) os.Error { if priv.P == nil || priv.Q == nil || priv.G == nil { return os.ErrorString("crypto/dsa: parameters not set up before generating key") } x := new(big.Int) xBytes := make([]byte, priv.Q.BitLen()/8) for { _, err := io.ReadFull(rand, xBytes) if err != nil { return err } x.SetBytes(xBytes) if x.Sign() != 0 && x.Cmp(priv.Q) < 0 { break } } priv.X = x priv.Y = new(big.Int) priv.Y.Exp(priv.G, x, priv.P) return nil }
// GenerateParameters puts a random, valid set of DSA parameters into params. // This function takes many seconds, even on fast machines. func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err os.Error) { // This function doesn't follow FIPS 186-3 exactly in that it doesn't // use a verification seed to generate the primes. The verification // seed doesn't appear to be exported or used by other code and // omitting it makes the code cleaner. var L, N int switch sizes { case L1024N160: L = 1024 N = 160 case L2048N224: L = 2048 N = 224 case L2048N256: L = 2048 N = 256 case L3072N256: L = 3072 N = 256 default: return os.ErrorString("crypto/dsa: invalid ParameterSizes") } qBytes := make([]byte, N/8) pBytes := make([]byte, L/8) q := new(big.Int) p := new(big.Int) rem := new(big.Int) one := new(big.Int) one.SetInt64(1) GeneratePrimes: for { _, err = io.ReadFull(rand, qBytes) if err != nil { return } qBytes[len(qBytes)-1] |= 1 qBytes[0] |= 0x80 q.SetBytes(qBytes) if !big.ProbablyPrime(q, numMRTests) { continue } for i := 0; i < 4*L; i++ { _, err = io.ReadFull(rand, pBytes) if err != nil { return } pBytes[len(pBytes)-1] |= 1 pBytes[0] |= 0x80 p.SetBytes(pBytes) rem.Mod(p, q) rem.Sub(rem, one) p.Sub(p, rem) if p.BitLen() < L { continue } if !big.ProbablyPrime(p, numMRTests) { continue } params.P = p params.Q = q break GeneratePrimes } } h := new(big.Int) h.SetInt64(2) g := new(big.Int) pm1 := new(big.Int).Sub(p, one) e := new(big.Int).Div(pm1, q) for { g.Exp(h, e, p) if g.Cmp(one) == 0 { h.Add(h, one) continue } params.G = g return } panic("unreachable") }